背景與目的##
首先,這是一個(gè)機(jī)器學(xué)習(xí)初學(xué)者兼非數(shù)學(xué)科班出身的非典型工程師的自學(xué)記錄。所以本文不會(huì)特別理論神帅,也不會(huì)太深入地講解公式挠将,但是會(huì)非常有目的性胳岂,針對(duì)一個(gè)特別現(xiàn)實(shí)的問(wèn)題,從頭開(kāi)始分享解決方案舔稀,包括某些優(yōu)化方案乳丰。
另外,我不是“理論搬運(yùn)工”内贮。我開(kāi)發(fā)的產(chǎn)品海鳥(niǎo)電波(我的其它文章也有介紹到产园,或者可以百度一下)的后臺(tái)圖書(shū)分類(lèi)也用到了這個(gè)分類(lèi)器。
從問(wèn)題開(kāi)始##
我們要解決的問(wèn)題夜郁,是對(duì)圖書(shū)進(jìn)行二元分類(lèi)什燕。分類(lèi)的依據(jù)是圖書(shū)的tag。這些tag可能來(lái)自專(zhuān)家竞端,或者編輯秋冰,或者用戶(hù)。例如“外國(guó)文學(xué)”婶熬,“偵探”剑勾,“計(jì)算機(jī)”埃撵,“python”都屬于tag。
出于我們的小小實(shí)驗(yàn)項(xiàng)目的需求虽另,簡(jiǎn)化問(wèn)題暂刘,我們現(xiàn)在要把圖書(shū)分為“人文”或者“非人文”兩類(lèi)。所以捂刺,正如上文所說(shuō)谣拣,這是一個(gè)對(duì)圖書(shū)進(jìn)行的二元分類(lèi)問(wèn)題。
例如族展,《計(jì)算機(jī)科學(xué)導(dǎo)論》森缠,它的標(biāo)簽有“計(jì)算機(jī)”“科學(xué)”“經(jīng)典”“導(dǎo)論”,它屬于“非人文”仪缸」蠛《麥田里的守望者》,它的標(biāo)簽有“小說(shuō)”“文學(xué)”“美國(guó)”恰画,它屬于“人文”宾茂。我們的分類(lèi)器有能力根據(jù)一本書(shū)的標(biāo)簽,自動(dòng)地將其歸類(lèi)為“人文”或者“非人文”拴还。試試看跨晴,蠻有意思的!
為了解決這個(gè)問(wèn)題片林,我們給出若干個(gè)前提:
- 任何一本書(shū)只可能歸類(lèi)為“人文”或“非人文”中的一類(lèi)
- 1本書(shū)有1個(gè)或以上的tag
- 所有書(shū)都沒(méi)有“人文”和“非人文” 的tag(什么端盆?你不相信?看看亞馬遜京東就知道了)
- 你需要很少的概率知識(shí)费封,比如什么是概率爱谁?條件概率又是什么?
使用python和numpy##
我們將使用python作為這個(gè)實(shí)驗(yàn)項(xiàng)目的編程語(yǔ)言孝偎。
numpy是一個(gè)python的科學(xué)計(jì)算庫(kù),需要你自行安裝凉敲。因?yàn)槲覀兊某绦蛏婕耙恍┖?jiǎn)單的矩陣運(yùn)算衣盾,用numpy可以大大簡(jiǎn)化編程工作量。
基本原理##
貝葉斯分類(lèi)器的工作原理###
還是需要了解一定的理論知識(shí)的爷抓,別擔(dān)心势决,這部分很快就過(guò)去。我會(huì)直接結(jié)合要解決的問(wèn)題來(lái)講解蓝撇。
基本上果复,用貝葉斯分類(lèi)是要解決一個(gè)這樣的問(wèn)題:已知一本書(shū)有這些tag:tag1,tag2,tag3......它屬于“人文”分類(lèi)的概率是多少?屬于“非人文”分類(lèi)的概率呢渤昌?
假設(shè)p1表示在這種情況下虽抄,它屬于“人文”的概率走搁,p2表示這種情況下,它屬于“非人文”的概率迈窟。
如果p1>p2私植,那么這本書(shū)就屬于“人文”,反過(guò)來(lái)就是“非人文”车酣。我們不考慮p1=p2的情況曲稼。
很簡(jiǎn)單,不是么湖员?
所以贫悄,問(wèn)題就變成了,如何通過(guò)tag1,tag2,tag3...來(lái)計(jì)算p1和p2娘摔?畢竟窄坦,只要知道了這兩個(gè)值,我們的最終問(wèn)題就解決了晰筛。
條件概率###
其實(shí)嫡丙,這是一個(gè)條件概率的問(wèn)題。所謂條件概率读第,就是求:在已知b發(fā)生的情況下曙博,a發(fā)生的概率。我們寫(xiě)做:p(a|b)怜瞒。
結(jié)合我們的實(shí)際問(wèn)題父泳,那就是在tag1,tag2,tag3...已經(jīng)發(fā)生的情況下(也就是這本書(shū)的tag就是tag1,tag2,tag3...),這本書(shū)屬于“人文”和“非人文”的概率吴汪。我們寫(xiě)做:
p(cate1|tag1,tag2,tag3...) 意思是在tag1,tag2,tag3...發(fā)生的情況下惠窄,這本書(shū)屬于cate1的概率(cate1=“人文”)
p(cate2|tag1,tag2,tag3...) 意思是在tag1,tag2,tag3...發(fā)生的情況下,這本書(shū)屬于cate2的概率(cate2=“非人文”)
這里的p(cate1|tag1,tag2,tag3...)其實(shí)就是上面說(shuō)的p1,我們這里用更為專(zhuān)業(yè)的方法來(lái)寫(xiě)漾橙。
條件概率怎么求呢杆融?這就是貝葉斯公式:
p(a|b) = p(b|a) * p(a) / p(b)
這個(gè)意思就是:想要求p(a|b),而你又知道p(b|a)霜运,p(a)和p(b)的值脾歇,那你就可以通過(guò)p(b|a)*p(a)/p(b)來(lái)求得p(a|b)。
換成我們要解決的實(shí)際問(wèn)題淘捡,等于:
p(cate1|tag1,tag2,tag3...) = p(tag1,tag2,tag3...|cate1) * p(cate1) / p(tag1,tag2,tag3...)
翻譯為人話藕各,那就是你想求p(cate1|tag1,tag2,tag3...),而你現(xiàn)在知道:
- p(tag1,tag2,tag3...|cate1)的值焦除,也就是你知道在一本書(shū)已經(jīng)被分類(lèi)為“人文”的情況下激况,tag1,tag2,tag3...一起出現(xiàn)的概率
- p(cate1),也就是所有被標(biāo)記為“人文”分類(lèi)的書(shū),(在訓(xùn)練集中)在所有書(shū)(“人文”和“非人文”)中出現(xiàn)的概率
- p(tag1,tag2,tag3...)乌逐,也就是tag1,tag2,tag3...(在訓(xùn)練集)所有tag中出現(xiàn)的概率
也就是說(shuō)竭讳,我們只要挨個(gè)求出上述3項(xiàng),我們就可以求出p(cate1|tag1,tag2,tag3...)了黔帕。同樣代咸,p(cate2|tag1,tag2,tag3...)也可以求出。
這里有個(gè)值得注意的技巧成黄,上述3項(xiàng)中呐芥,其實(shí)第3項(xiàng)不需要我們計(jì)算。因?yàn)槲覀兊哪康氖潜容^p(cate1|tag1,tag2,tag3...)與p(cate2|tag1,tag2,tag3...)的大小奋岁,不是為了得到實(shí)際的值思瘟,由于上述公式里的分母p(tag1,tag2,tag3...)是一樣的,所以闻伶,我們只需要比較分子的大小就可以了滨攻。也就是比較:
p(tag1,tag2,tag3...|cate1) * p(cate1),
與p(tag1,tag2,tag3...|cate2) * p(cate2)的大小
這樣可以省去我們一些計(jì)算蓝翰。
樸素貝葉斯###
那么光绕,如何計(jì)算p(tag1,tag2,tag3...|cate1)呢?這里要用到樸素貝葉斯的概念畜份,就是說(shuō)诞帐,我們認(rèn)為,在一本書(shū)中的標(biāo)簽里爆雹,每個(gè)標(biāo)簽都是相互獨(dú)立的停蕉,與對(duì)方是否出現(xiàn)沒(méi)有關(guān)系。也就是說(shuō)“計(jì)算機(jī)”和“經(jīng)典”出現(xiàn)的概率互不相關(guān)钙态,不會(huì)因?yàn)椤坝?jì)算機(jī)”出現(xiàn)了就導(dǎo)致“經(jīng)典”出現(xiàn)的概率高慧起。
既然是相互獨(dú)立,那么册倒,p(tag1,tag2,tag3...|cate1)就等于:
p(tag1|cate1) x p(tag2|cate1) x p(tag3|cate1) x ...
p(tag1,tag2,tag3...|cate2)就等于:
p(tag1|cate2) x p(tag2|cate2) x p(tag3|cate2) x ...
也就是說(shuō)蚓挤,我們可以計(jì)算每一個(gè)tag,分別在“人文”和“非人文”書(shū)籍的所有tag中出現(xiàn)的概率驻子,然后將它們乘起來(lái)灿意,就得到我們想要的。
舉例分析###
我們現(xiàn)在有一本書(shū)《計(jì)算機(jī)科學(xué)導(dǎo)論》拴孤,它的標(biāo)簽是“計(jì)算機(jī)”“科學(xué)”“理論”“經(jīng)典”“導(dǎo)論”,我們想知道在這幾個(gè)標(biāo)簽出現(xiàn)的情況下甲捏,《計(jì)算機(jī)科學(xué)導(dǎo)論》分別屬于“人文”和“非人文”的概率演熟。
那么,我們已經(jīng)有了什么呢?幸運(yùn)的是芒粹,我們目前手頭有10本書(shū)兄纺,已知其中6本是“人文”,4本是“非人文”化漆。這10本書(shū)估脆,經(jīng)過(guò)排重,一共有70個(gè)不同的標(biāo)簽座云,“計(jì)算機(jī)”疙赠,“科學(xué)”,“理論”朦拖,“導(dǎo)論”也在其中圃阳。
基于此,我們可以得出璧帝,p(cate1)=6/10=0.6捍岳,p(cate2)=1-0.6=0.4。也就是說(shuō)“人文”書(shū)在所有書(shū)中的概率是0.6睬隶,“非人文”是0.4锣夹。
接下來(lái)就是p(tag1,tag2,tag3...|cate1)和p(tag1,tag2,tag3...|cate2)了。也就是苏潜,我們要算出银萍,在“人文”類(lèi)里的所有書(shū)中,“計(jì)算機(jī)”“科學(xué)”“理論”“經(jīng)典”“導(dǎo)論”這幾個(gè)tag在“人文”書(shū)的所有tag里出現(xiàn)的概率窖贤。同樣砖顷,我們還要算出,在“非人文”類(lèi)里的所有書(shū)中赃梧,上述這幾個(gè)tag在所有“非人文”書(shū)中的所有tag里出現(xiàn)的概率滤蝠。計(jì)算的方法,就是將每個(gè)tag在“人文”和“非人文”中出現(xiàn)的概率授嘀,相乘物咳,然后再分別乘以0.6和0.4。
然后比較一下大小就可以了蹄皱。也就是比較p(cate1) x p(tag1,tag2,tag3...|cate1)與p(cate2) x p(tag1,tag2,tag3...|cate2)的大小览闰。
開(kāi)始動(dòng)手##
1.準(zhǔn)備訓(xùn)練集###
幾乎所有的機(jī)器學(xué)習(xí)都需要訓(xùn)練集。貝葉斯分類(lèi)也一樣巷折。事實(shí)上压鉴,我們上面所說(shuō)的我們##已知##的數(shù)據(jù),就是訓(xùn)練集锻拘。上面例子中舉出的那10本書(shū)油吭,以及這10本書(shū)所有排重后的tag击蹲,就是我們的訓(xùn)練集;而0.6和0.4這兩個(gè)概率婉宰,還有p1(tag1,tag2,tag3...|cate1)和p2(tag1,tag2,tag3...|cate2)歌豺,就是我們基于訓(xùn)練集的數(shù)據(jù)計(jì)算出來(lái)的,機(jī)器學(xué)習(xí)管這叫“訓(xùn)練”心包。
基于我們的問(wèn)題类咧,我們需要準(zhǔn)備100本書(shū),人為地分為“人文”和“非人文”兩類(lèi)蟹腾,并且收集將這些書(shū)的所有tag痕惋。這些書(shū)如何獲得?你可以爬取亞馬遜或者豆瓣上的書(shū)籍資源岭佳。
2.形成tag集###
將上述所說(shuō)的tag血巍,用python里的列表來(lái)保存,我們令其為dicts.dicts里的每一個(gè)元素是一個(gè)tag珊随,例如:
dicts = ['科學(xué)','理論','c++']這樣的形式述寡。
3.計(jì)算訓(xùn)練集中“人文”和“非人文”的概率###
非常簡(jiǎn)單,如我們的例子所說(shuō)叶洞,假設(shè)這訓(xùn)練集中的這100本書(shū)鲫凶,有60本是“人文”,那么p(cate1)=60/100=0.6衩辟。p(cate2)=1-p(cate1)=0.4螟炫。這里我們用變量:
pcate1 = 0.6
pcate2 = 0.4
4.計(jì)算tag集中每個(gè)tag在訓(xùn)練集“人文”書(shū)籍中的tag出現(xiàn)的概率###
首先,我們基于訓(xùn)練集構(gòu)造一個(gè)列表艺晴,這個(gè)列表里的每一項(xiàng)又是一個(gè)列表昼钻,這個(gè)列表里的每一項(xiàng),不是1就是0封寞。1表示這個(gè)詞典中這個(gè)位置的tag是這本書(shū)的一個(gè)tag然评。
舉例:假設(shè)我們的dicts是這樣的:
['計(jì)算機(jī)','小說(shuō)','心理','科學(xué)','編程','行為','導(dǎo)論','經(jīng)典','游記','美國(guó)']
我們有這樣一個(gè)列表:tag_vector_cate1
[
[0,1,0,0,0,0,0,1,0,1],
[0,0,1,0,0,1,0,0,0,1],
..............
]
這個(gè)列表對(duì)應(yīng)的是“人文”類(lèi)。
每一行代表訓(xùn)練集中“人文”類(lèi)的一本書(shū)狈究。第一行對(duì)應(yīng)的書(shū)是《麥田里的守望者》碗淌,它的標(biāo)簽是“小說(shuō)”,“經(jīng)典”抖锥,“美國(guó)”亿眠。第二行對(duì)應(yīng)的書(shū)是《可預(yù)測(cè)的非理性》,它的標(biāo)簽是“心理”磅废,“行為”纳像,“美國(guó)”。注意拯勉,我們是用整個(gè)tag集dicts來(lái)表示一本書(shū)的tag竟趾。所以耙考,第一行第1列(我們從0開(kāi)始計(jì)數(shù))的1,表示《每天里的守望者》有一個(gè)'小說(shuō)'的tag(對(duì)應(yīng)dicts里的第1列)潭兽;第一行第2列的0,表示《麥田里的守望者》這本書(shū)沒(méi)有'心理'這個(gè)tag(對(duì)應(yīng)dicts里的第2列)斗遏。同理山卦,我們看到第一行和第二行的第9列都是1,說(shuō)明《麥田里的守望者》和《可預(yù)測(cè)的非理性》都有'美國(guó)'這個(gè)tag诵次。
有了這樣的數(shù)據(jù)账蓉,我們就很好計(jì)算了。現(xiàn)在以計(jì)算p(tag1|cate1)為例逾一。對(duì)于tag1铸本,我們計(jì)算出在訓(xùn)練集里“人文”的所有書(shū)中,tag1出現(xiàn)了多少次遵堵。例如:在訓(xùn)練集里箱玷,“人文”有60本,其中40本書(shū)都有“經(jīng)典”這個(gè)tag陌宿,那么我們就令num_of_tag1=40锡足。按照這個(gè)方法,我們求出每個(gè)tag出現(xiàn)了多少次壳坪,比如:num_of_tag2=32,num_of_tage=18......
然后舶得,我們求出在“人文”類(lèi)里,所有書(shū)的tag標(biāo)簽總數(shù)(注意這里是不排重的)爽蝴。例如“人文”類(lèi)有2本書(shū)沐批,第一本書(shū)的標(biāo)簽是“散文”“經(jīng)典”“外國(guó)”,第二本是“經(jīng)典”“小說(shuō)”蝎亚。那么九孩,所有書(shū)的tag標(biāo)簽總數(shù)就是3+2=5。現(xiàn)在颖对,我們求出訓(xùn)練集里所有100本的tag標(biāo)簽總數(shù)捻撑。假設(shè)總數(shù)是700。我們令total_cate1=700缤底。
于是顾患,tag1在“人文”類(lèi)里出現(xiàn)的概率:p(tag1|cate1) = num_of_tag1 / total_cate1 = 40/700 = 0.057。同理个唧,我們得出p(tag2|cate1)江解,p(tag3|cate1)...
利用numpy,我們可以很方便地用幾句代碼來(lái)實(shí)現(xiàn)這個(gè)過(guò)程徙歼。
from numpy import *
num_tags_cate1 = ones(len(dicts)) #(1)
total_cate1 = 2.0 #(2)
for item in tag_vector_cate1: num_tags_cate1 += item #(3) total_cate1 += sum(item) #(4) p_tags_cate1 = num_tags_cate1 / total_cate1 #(5)
這里做一下說(shuō)明犁河。
(1)代碼鳖枕,表示生成一個(gè)numpy數(shù)組。ones()是numpy的函數(shù)桨螺,返回一個(gè)填充了數(shù)值1的numpy數(shù)組宾符,參數(shù)是這個(gè)數(shù)組的長(zhǎng)度。例如:temp=ones(3)灭翔,表示生成了一個(gè)numpy數(shù)組[1,1,1]并返回給了temp魏烫。所以,(1)代碼就是以訓(xùn)練集的tag集dicts的長(zhǎng)度為參數(shù)肝箱,生成一個(gè)和dicts等長(zhǎng)的填充了1的numpy數(shù)組哄褒,返回給num_tags_cate1。為什么要和dicts登長(zhǎng)煌张?還記得吧呐赡,我們是以整個(gè)字典集來(lái)表示一本書(shū)的。我們要計(jì)算的就是這個(gè)dicts里的每一個(gè)tag的概率骏融,并放到一個(gè)數(shù)組里链嘀。num_tags_cate1就是這個(gè)數(shù)組。至于這個(gè)數(shù)組為什么要填充1档玻,稍后會(huì)說(shuō)明管闷。
(2)total_cate1 = 2.0。total_cate1是分母窃肠,分母不能是0包个,所以我們要令其初始值不為0。為什么是2.0冤留?稍后會(huì)說(shuō)明碧囊。
(3)num_tags_cate1 += item。item顯然是一個(gè)python的列表纤怒,就是我們剛才說(shuō)的[0,1,0,0,0,0,0,1,1]糯而。當(dāng)你用一個(gè)numpy數(shù)組加上一個(gè)python的list時(shí),numpy會(huì)幫你做對(duì)應(yīng)項(xiàng)目的計(jì)算泊窘,相當(dāng)于重載了+熄驼。例如,a是一個(gè)numpy數(shù)組:[1,2,3,5,0]烘豹,b是一個(gè)python的list:[0,0,3,2,1]瓜贾。a + b = [1,2,6,7,1],結(jié)果是一個(gè)numpy數(shù)組携悯。在這個(gè)例子里祭芦,相當(dāng)于“小說(shuō)”,“經(jīng)典”憔鬼,“美國(guó)”這3個(gè)標(biāo)簽的數(shù)量分別增加了1龟劲。
(4)把每本書(shū)出現(xiàn)的所有tag的數(shù)量相加胃夏。sum(item)也是numpy的函數(shù),作用是將item里的每一項(xiàng)相加昌跌。例如:sum([2,5,-1])仰禀,其結(jié)果2+5+(-1)=6。假如item是這樣的一個(gè)list:[0,1,0,0,0,0,0,1,1]蚕愤,對(duì)應(yīng)的是《麥田里的守望者》悼瘾,它的標(biāo)簽分別是“小說(shuō)”“經(jīng)典”“美國(guó)”,相當(dāng)于標(biāo)簽總數(shù)增加了3审胸。
(5)很明顯,我們用num_tags_cate1去除以total_cate1卸勺,這也是numpy重載了“/”運(yùn)算符砂沛,例如[2,4,6]/2,相當(dāng)于每一項(xiàng)分別除以2曙求,最后得到一個(gè)numpy數(shù)組碍庵,也就是[1,2,3]。在這個(gè)例子里悟狱,就相當(dāng)于我們分別用tag1,tag2,tag3...出現(xiàn)的次數(shù)去除以標(biāo)簽的總數(shù)量静浴,并得到一個(gè)numpy數(shù)組p_tags_cate1。這個(gè)數(shù)組里的每一項(xiàng)是一個(gè)概率值挤渐,代表其對(duì)應(yīng)的tag在cate1(“人文”)類(lèi)別里出現(xiàn)的概率苹享。
同樣,我們可以計(jì)算出p_tags_cate2浴麻。也就是每個(gè)tag在cate2(“非人文”)里出現(xiàn)的概率得问。
5.現(xiàn)在我們有什么###
來(lái)到這里,我們已經(jīng)有了幾乎所有的東西软免」常回憶一下貝葉斯分類(lèi)的公式:
p(cate1|tag1,tag2,tag3...) = p(tag1,tag2,tag3...|cate1) x p(cate1) / p(tag1,tag2,tag3...)
我們前面討論過(guò),分子可以忽略膏萧,不計(jì)算漓骚,也就是不需要理會(huì)分母p(tag1,tag2,tag3...)。
進(jìn)一步地榛泛,按照樸素貝葉斯理論蝌蹂,分子等于:
p(tag1,tag2,tag3...|cate1) x p(cate1) = p(tag1|cate1) x p(tag2|cate1) x p(tag3|cate1) x ... x p(cate1)
p(cate1)就是等于上面所說(shuō)的pcate1。
p(tag1|cate1)曹锨,p(tag2|cate1)......就是我們上面得出的numpy數(shù)組p_tags_cate1里的每一項(xiàng)叉信。我們只需要把它們相乘起來(lái),就得到p(tag1|cate1) x p(tag2|cate1) x ...... !
來(lái)到這里艘希,我們要解釋一下硼身,為什么上文的代碼用1來(lái)填充num_tags_cate1硅急。如果我們用0來(lái)填充,當(dāng)某個(gè)tag一直為0時(shí)(雖然理論上不可能出現(xiàn))佳遂,整個(gè)分子相乘的結(jié)果為0营袜,這樣最后的值就變?yōu)?了,影響了結(jié)果丑罪。所以荚板,為了避免這種情況,我們認(rèn)為每個(gè)tag至少要出現(xiàn)1次吩屹,所以我們用ones來(lái)填充跪另。這樣,最壞情況下煤搜,num_tags_cate1=[1,1,1,.....]免绿。
而total_cate1=2.0,就是對(duì)應(yīng)當(dāng)num_tags_cate1=[1,1,1,...]時(shí)擦盾,那么我們認(rèn)為每個(gè)tag出現(xiàn)的概率是0.5(1/2.0)嘲驾,這是一個(gè)可以調(diào)節(jié)的參數(shù),但是要記住不要令total_cate1=1.0迹卢。如果這樣辽故,那么每個(gè)tag出現(xiàn)的概率變成1了,大有問(wèn)題腐碱。
6.利用訓(xùn)練得出的數(shù)據(jù)給新書(shū)進(jìn)行分類(lèi)###
終于完成了貝葉斯分類(lèi)器慕匠,現(xiàn)在我們看看如何給新書(shū)分類(lèi)舞竿。
所謂給新書(shū)分類(lèi),就是當(dāng)已經(jīng)完成了訓(xùn)練集的訓(xùn)練后(還記得吧?那100本手工分類(lèi)的書(shū)就是訓(xùn)練集)坛吁,這時(shí)候枚冗,我們要對(duì)第101本書(shū)進(jìn)行分類(lèi)围俘。這本書(shū)不是訓(xùn)練集里的書(shū)羹呵,是新書(shū)。我們基于前面計(jì)算出來(lái)的公式里的幾個(gè)元素瓷们,來(lái)對(duì)它進(jìn)行分類(lèi)业栅。
同樣的,我們抽取新書(shū)的標(biāo)簽谬晕,并用python里的list來(lái)保存碘裕,記作:tagvects,它的形式如:[1,0,0,1,0,0,1....]攒钳。
接著帮孔,我們讓p_tags_cate1里的每個(gè)項(xiàng)乘以對(duì)應(yīng)的tagvects里的項(xiàng):
results_tags_cate1 = p_tags_cate1 * tagvects
再令num_tags_cate1里的每一項(xiàng)相乘:
temp1 = 1.0
for item in results_tags_cate1: if item != 0: temp1 = temp1 * item
同樣的方法,計(jì)算出temp2:
results_tags_cate2 = p_tags_cate2 * tagvects
temp2 = 1.0
for item in results_tags_cate2: if item != 0: temp2 = temp2 * item
最后,這樣:
p_cate1_tags = temp1 * pcate1
p_cate2_tags = temp2 x pcate2
if p_cate1_tags > p_cate2_tags: print '人文' else: print '非人文'
顯然文兢,我們通過(guò)比較p_cate1_tags與p_cate2_tags的大小晤斩,就可以為新書(shū)進(jìn)行分類(lèi)了,哪邊的值大姆坚,就分到哪邊澳泵。
優(yōu)化trick##
由于上面的公式,是多個(gè)概率相乘兼呵,當(dāng)你的tag集dicts的長(zhǎng)度非常大時(shí)(也就是你的書(shū)的標(biāo)簽特別多時(shí))兔辅,這是個(gè)很可怕的做法,由于每一項(xiàng)都是小數(shù)击喂,這么多小數(shù)相乘维苔,將可能出現(xiàn)溢出,或者數(shù)太小導(dǎo)致計(jì)算結(jié)果為0懂昂。這時(shí)候介时,需要一個(gè)trick,來(lái)做一下優(yōu)化忍法,避免這種情況。
我們?nèi)?shù)學(xué)上非常流行的做法榕吼,取對(duì)數(shù)ln饿序,來(lái)改善我們的算法。在python里羹蚣,取對(duì)數(shù)的函數(shù)是log()原探。
可以在幾個(gè)地方取對(duì)數(shù)。這里推薦這樣的做法顽素,把要計(jì)算的式子變成:
ln(p(tag1|cate1) * p(tag2|cate1) *....* p(cate1)))
展開(kāi)來(lái)咽弦,就變成:
ln(p(tag1|cate1)) + ln(p(tag2|cate1)) + ... + ln(pcate1)
回憶一下,p(tag1|cate1),p(tag2|cate1)...是我們上面算出的p_tags_cate1的每一項(xiàng)(p_tags_cate1是numpy數(shù)組胁出,其中每一項(xiàng)表示對(duì)應(yīng)的tag在“人文”分類(lèi)中出現(xiàn)的概率)型型。在我們上面的計(jì)算中:
p_tags_cate1 = num_tags_cate1 / total_cate1
現(xiàn)在我們對(duì)其取對(duì)數(shù),于是全蝶,改代碼改為:
p_tags_cate1 = log(num_tags_cate1 / total_cate1)
注意闹蒜,這里的log,是對(duì)numpy的數(shù)組中的每一項(xiàng)求log抑淫,結(jié)果還是一個(gè)數(shù)組绷落。
于是,p_tags_cate1就成為了取對(duì)數(shù)后的數(shù)組始苇。
然后求ln(pcate1)砌烁,把pcate1變?yōu)椋?br>
pcate1 = log(pcate1)
所以,上面最后分類(lèi)的代碼就改為:
results_tags_cate1 = p_tags_cate1 * tagvects
temp1 = 1.0
for item in results_tags_cate1: if item != 0: temp1 = temp1 + item
同樣的方法催式,計(jì)算出temp2:
results_tags_cate2 = p_tags_cate2 * tagvects
temp2 = 1.0
for item in results_tags_cate2: if item != 0: temp2 = temp2 + item
然后就可以分類(lèi)了:
p_cate1_tags = temp1 + pcate1
p_cate2_tags = temp2 + pcate2
if p_cate1_tags > p_cate2_tags: print '人文' else: print '非人文'
總結(jié)##
很高興你終于來(lái)到了這里函喉。本文力求簡(jiǎn)潔避归,盡量降低學(xué)習(xí)成本。但是肯定存在第一次閱讀還覺(jué)得有些不太理解的可能函似,這是正常的槐脏,凡事總有個(gè)過(guò)程,尤其是機(jī)器學(xué)習(xí)這個(gè)領(lǐng)域撇寞,需要你反復(fù)咀嚼和思考以及實(shí)踐顿天。攥寫(xiě)本文的過(guò)程中,我也在反復(fù)加深對(duì)貝葉斯分類(lèi)的理解蔑担,但是表達(dá)出來(lái)牌废,還是有不太清晰的地方。如果你有不解或者建議啤握,歡迎與我多討論鸟缕。
通過(guò)本文,我們明白了:
- 什么是樸素貝葉斯
- 為了施行樸素貝葉斯分類(lèi)排抬,應(yīng)該如何準(zhǔn)備訓(xùn)練集懂从,其中tag集是非常重要的
- 在訓(xùn)練數(shù)據(jù)的基礎(chǔ)上,得到每個(gè)tag在“人文”和“非人文”中的出現(xiàn)概率
- 利用這些出現(xiàn)概率蹲蒲,為新的文章進(jìn)行分類(lèi)
- 巧妙利用對(duì)數(shù)和一些初始值(例如ones())來(lái)為算法做一些優(yōu)化
最后番甩,給自己的一個(gè)小創(chuàng)作做一下宣傳,海鳥(niǎo)電波是一個(gè)語(yǔ)音評(píng)論書(shū)籍的平臺(tái)届搁,目前以微信公眾號(hào)h5頁(yè)面的形式來(lái)提供服務(wù)缘薛,在這里你可以自由評(píng)論書(shū)籍、傾聽(tīng)真人語(yǔ)音的點(diǎn)評(píng)卡睦,分享自己的見(jiàn)解等宴胧。另外,我也在簡(jiǎn)書(shū)上發(fā)表了一篇文章海鳥(niǎo)電波的第一天描述我開(kāi)發(fā)海鳥(niǎo)電波的緣由表锻。
本文由電流首發(fā)于簡(jiǎn)書(shū)恕齐。轉(zhuǎn)載請(qǐng)注明出處。歡迎來(lái)到原文處進(jìn)行交流瞬逊。
謝謝你的閱讀檐迟。
文章開(kāi)頭的配圖攝于某個(gè)酒吧,在酒吧里編程是一種特別的體驗(yàn)码耐。圖片歸本人所有追迟。
文章結(jié)尾的配圖攝于凡爾賽宮外,選此圖的意義是希望科技與人文藝術(shù)優(yōu)美結(jié)合骚腥。圖片歸本人所有敦间。