Created
April 22, 2017 16:35
-
-
Save shotahorii/531e131ddcc323acbf62efd0244c4db5 to your computer and use it in GitHub Desktop.
Naive bayes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import math\n", | |
"import functools\n", | |
"import MeCab\n", | |
"\n", | |
"from collections import defaultdict\n", | |
"from collections import Counter" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"#### Utility functions" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 36, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"STOPWORDS = [' ', '、', '。', '(', ')', '(', ')', 'は', 'が', 'の', 'を', 'と', 'な', 'た', 'に']\n", | |
"\n", | |
"def text2words(text):\n", | |
" '''Take a text in Japanses, return a list of words in the text.'''\n", | |
" tagger = MeCab.Tagger('mecabrc')\n", | |
" # decompose the text into table of words and information (1 row = 1 word + its information)\n", | |
" rows = [row.split(',') for row in tagger.parse(text).split('\\n') if row != '' and row != 'EOS']\n", | |
" # extracting word from each row\n", | |
" words = [row[0].split('\\t')[0] if row[6]=='*' else row[6] for row in rows] # 6th element is basic type of word\n", | |
" # removing stopwords\n", | |
" return list(filter(lambda x: x not in STOPWORDS, words))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 37, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"['ネコ', '体', '非常', '柔軟', '性', '高い']" | |
] | |
}, | |
"execution_count": 37, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# example\n", | |
"text2words(\"ネコの体は非常に柔軟性が高い。\")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"#### Naive Bayes" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"class NaiveBayes():\n", | |
" def __init__(self):\n", | |
" self.totaldocs = 0\n", | |
" self.cats = set()\n", | |
" self.vocabs = set()\n", | |
" self.doccount = defaultdict(int)\n", | |
" self.wordcount = {}\n", | |
" self.denominator = {}\n", | |
" \n", | |
" # -- callable functions --\n", | |
" \n", | |
" def train(self, docs): # docs: list of tuple containing text and category. e.g. [(\"Apple made iphone\", \"IT\"),...] \n", | |
" self.totaldocs = self.totaldocs + len(docs)\n", | |
" \n", | |
" for doc in docs:\n", | |
" self.cats.add(doc[1]) \n", | |
" \n", | |
" for cat in self.cats:\n", | |
" subsetDocs = list(filter(lambda doc: doc[1]==cat, docs))\n", | |
" if len(subsetDocs) > 0:\n", | |
" self.doccount[cat] = self.doccount[cat] + len(subsetDocs)\n", | |
" subsetWords = functools.reduce(lambda a,b: a + b, list(map(lambda x: text2words(x[0]), subsetDocs)))\n", | |
" self.vocabs = self.vocabs.union(set(subsetWords))\n", | |
"\n", | |
" if cat in self.wordcount.keys():\n", | |
" self.wordcount[cat] = defaultdict(int, Counter(self.wordcount[cat]) + Counter(subsetWords))\n", | |
" else:\n", | |
" self.wordcount[cat] = defaultdict(int, Counter(subsetWords))\n", | |
"\n", | |
" self.denominator[cat] = sum(self.wordcount[cat].values())\n", | |
" \n", | |
" def classify(self, doc):\n", | |
" probs = list(map(lambda cat: (cat, self.score(doc, cat)), self.cats))\n", | |
" probs.sort(key=lambda x:x[1], reverse=True)\n", | |
" return probs[0][0]\n", | |
" \n", | |
" def summary(self):\n", | |
" print(\"# of trained docs: \" + str(self.totaldocs))\n", | |
" print(\"# of categories: \" + str(len(self.cats)))\n", | |
" print(\"# of vocabularies: \" + str(len(self.vocabs)))\n", | |
" \n", | |
" # -- helper functions --\n", | |
" \n", | |
" def wordProb(self, word, cat):\n", | |
" return float(self.wordcount[cat][word] + 1) / float(self.denominator[cat] + len(self.vocabs))\n", | |
" \n", | |
" def score(self, doc, cat):\n", | |
" score = math.log(float(self.doccount[cat]) / self.totaldocs) # log P(cat)\n", | |
" words = text2words(doc)\n", | |
" for word in words:\n", | |
" score += math.log(self.wordProb(word, cat)) # log P(word|cat)\n", | |
" return score\n", | |
" " | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"#### Main" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 39, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"traindocs = [('''\n", | |
"ライオン(Panthera leo) は、食肉目ネコ科ヒョウ属に分類される食肉類。\n", | |
"別名はシシ(獅子)。オスであれば体重は250キログラムを超えることもあり、ネコ科ではトラに次いで2番目に大きな種である[9]。現在の主な生息地はサブサハラであるが、インドのジル国立公園のインドライオンは絶滅が危惧されている。北アフリカや西南アジアでは有史時代に姿を消している。更新世末期、約1万年前までライオンはヒトに次いで広く分布する大型陸上哺乳類だった。そのころよく見られた地域は順に、アフリカ、西ヨーロッパからインドにかけてのユーラシア、ユーコンからペルーまでのアメリカである[10]。\n", | |
"飼育個体は20年以上生きることもあるが、野生のライオンの寿命はより短く、特にオスが10年以上生きることは稀である。縄張りをめぐって他のオスと常に争うために傷を負い、それが寿命を大きく縮める原因となる[11]。典型的な棲息地はサバンナや草原であるが、茂みや森などに棲む場合もある。ライオンは他のネコ科の動物にはあまり見られない社会性を持っている。メスと子ライオン、そして少数の成熟したオスがプライド(群れ)を形成する。狩りの特徴はメスの集団が連係することであり、おもに大型の有蹄類を襲う。ライオンは捕食者の頂点でありまた象徴的な存在であるが、屍肉も漁ることもある。ライオンがヒトを襲うことはほとんどないが、ライオンによる犠牲者がいることは知られている。\n", | |
"ライオンは危急種である。アフリカではこの20年間で30-50パーセントまで頭数が減っており、おそらく回復しないだろうとされている。保護区や国立公園に指定された地以外では棲息が難しくなっている[12]。しかし、その数が減っている原因は明確にはわかっておらず、現在は棲息地の減少や人間との衝突が最大の原因だとされている。ライオンはローマ時代から見世物としても知られ、その後2000年近くにわたって世界中の動物園で観賞されている。また、世界規模でアジア種を救う養育プログラムが組まれ、動物園同士で協力しあっている。\n", | |
"世界的に百獣の王として有名であり、一般的に最も強い動物であると思われている[13]。オスの外見は鬣(たてがみ)が非常に特徴的であり、容易に認識できる。オスの容貌はあらゆる文化のなかで動物そのもののシンボルとしてもっとも広まっているものの一つであり、実際に全ての動物の中で国獣として選ばれる数はライオンが最も多い。ライオンは後期旧石器時代から描かれており、古くはラスコー洞窟やショーヴェ洞窟の洞窟画などがある。彫刻や絵画、国旗をはじめ、現代の映画や文学などでも広く扱われている。\n", | |
" ''',\n", | |
" 'Lion'), \n", | |
" ('''\n", | |
"カンガルー(英語: kangaroo)は、有袋類双前歯目の一群である。\n", | |
"カンガルー科 (Macropodidae) に分類されるが、別の分類ではネズミカンガルー科 Potoridae をカンガルー科に統合し、カンガルー科をカンガルー亜科 Macropodinae(先の分類でのカンガルー科)とネズミカンガルー亜科 Potorinae に分ける。\n", | |
"オーストラリア大陸、タスマニア島、ニューギニア島に生息している。大型の(狭義の)カンガルー、小型のワラビー、樹上性のキノボリカンガルーなどがいるが、同じカンガルー属 Macropus にオオカンガルーもアカクビワラビーも中間サイズのワラルーもおり、大型カンガルーとワラビーの区別は分類学的なものではない。\n", | |
" ''', 'Kangaroo'),\n", | |
" ('''\n", | |
"オオカミ(狼、羅: lupus、英: wolf)は、ネコ目(食肉目)イヌ科イヌ属に属する哺乳動物。広義には近縁種も含めることがあるが、通常はタイリクオオカミ(ハイイロオオカミ、Canis lupus)一種を指す。多数の亜種が認められている。同属の近縁種としてアメリカアカオオカミ、コヨーテ、アビシニアジャッカル(エチオピアオオカミ)などがいる。\n", | |
"従来はオオカミの近縁種とされていたイヌ(イエイヌ)は、近年ではオオカミの一亜種 Canis lupus familiaris とする見方が主流になりつつある(→イヌの起源)。ただし、日常語としての「オオカミ」には通常、イヌは含まれない。イヌはオオカミが飼い馴らされて家畜化したものと考えられている。\n", | |
"アメリカアカオオカミ、コヨーテ、アビシニアジャッカルとは相互に交配可能で、野生下でも雑種個体が生じ、繁殖力も有しているため生物学的種の定義に照らせば亜種であり、別種ではない。種と亜種の区分は慣習的不合理性が残存していることの一例である。亜種によっては絶滅が危惧される。日本で古来「狼」と呼ばれてきた動物は絶滅したとされるニホンオオカミであり、タイリクオオカミの一亜種と見なされる。ニホンオオカミは、12万 - 13万年前に枝分かれした亜種であり、ハイイロオオカミと同じ種であるとの遺伝子解析結果を、岐阜大の石黒直隆教授と松村秀一教授らのチームがまとめた。\n", | |
" ''',\n", | |
" 'Wolf'), \n", | |
" ('''\n", | |
"イヌ(犬、狗、学名:Canis lupus familiaris、ラテン語名:canis、英語名[国際通用名]:dog、domestic dog)は、ネコ目(食肉目)- イヌ科- イヌ属に分類される哺乳類の一種。\n", | |
"属名 Canis、種小名 lupus はラテン語でそれぞれ「犬」「狼」の意。亜種名 familiaris はやはりラテン語で、「家庭に属する」といった意味。また、英語: familiar、フランス語: familier など「慣れ親しんだ」を意味する現代語の語源でもある。\n", | |
"古く日本ではヤマイヌ(狼)に対して「イエイヌ」とも言っていた。英語名 domestic dog は、伝統的な学名 C. familiaris(家族の-犬)を英訳にしたもので、日本では domestic dog の訳語として古来からのイエイヌの語をあてるようになった。\n", | |
"また、広義の「イヌ」は広くイヌ科に属する動物(イエイヌ、オオカミ、コヨーテ、ジャッカル、キツネ、タヌキ、ヤブイヌ、リカオンなど)の総称でもあるが、日本ではこちらの用法はあまり一般的ではなく、欧文翻訳の際、イヌ科動物を表す dogs や canine の訳語として当てられるときも「イヌ類」などとしてイエイヌと区別するのが普通である。以下では狭義のイヌ(ヤマイヌなどを除くイエイヌ)についてのみ解説する。\n", | |
"イエイヌは人間の手によって作り出された動物群である。最も古くに家畜化されたと考えられる動物であり、現代でも、ネコ Felis silvestris catus と並んで代表的なペットまたはコンパニオンアニマルとして、広く飼育され、親しまれている。\n", | |
"野生化したものを野犬といい、日本語ではあたかも標準和名であるかのように片仮名で「ノイヌ」と表記されることも多いが、野犬(やけん)を誤って訓読したため生じた新語であり、分類学上は種や亜種としてイエイヌと区別される存在ではない。\n", | |
"犬種については犬の品種一覧を参照。現在[いつ?]、ジャパンケネルクラブ(JKC)では、国際畜犬連盟(FCI)が公認する331犬種を公認し、そのうち176犬種を登録してスタンダードを定めている。\n", | |
"世界全体では4億匹の犬がいると見積もられている。血液型は8種類。 現在、非公認犬種を含めて、約700~800の犬種がいます。\n", | |
" ''', 'Dog')\n", | |
" ]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 40, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"nb = NaiveBayes()\n", | |
"nb.train(traindocs)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 41, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"# of trained docs: 4\n", | |
"# of categories: 4\n", | |
"# of vocabularies: 500\n" | |
] | |
} | |
], | |
"source": [ | |
"nb.summary()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 46, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Lion\n", | |
"Kangaroo\n" | |
] | |
} | |
], | |
"source": [ | |
"doc1 = 'アフリカに生息する大きく獰猛な動物'\n", | |
"doc2 = 'オーストラリア'\n", | |
"\n", | |
"print(nb.classify(doc1))\n", | |
"print(nb.classify(doc2))" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.5.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment