樸素貝葉斯概述

貝葉斯公式

首先我們用一個例子來解釋一下貝葉斯公式的使用。

有一個村子润脸,里面一共有三個小偷毙驯,他們的偷竊能力分別是A_1,A_2,A_3,如何求出這個村子出現(xiàn)失竊案件的概率P(B)爆价?

分析:

首先我們知道,這個村子中只有三個小偷蛾号,因此三個小偷構(gòu)成了一個完備事件組,即他們的能力的總和為全集\Omega活逆,且相互之間獨立蔗候。因此我們可以建立等式:
P(B)=P(B\Omega)
P(B)=P(B(A_1\cup A_2\cup A_3))
P(B)=P(BA_1\cup BA_2\cup BA_3))
P(B)=P(BA_1\cup BA_2\cup BA_3))
\because A_1,A_2,A_3相互獨立
\therefore P(B)=P(BA_1)+P(BA_2)+P(BA_3)
P(B)=P(A_1)P(B|A_1)+P(A_2)P(B|A_2)+P(A_3)P(B|A_3)
如果這個村子里有n個小偷的話锈遥,我們可以總結(jié)成以下公式:
P(B)=\sum_{i=1}^{n}P(A_i)P(B|A_i)
以上便可以求得村子失竊的概率P(B)所灸,而這個公式也被稱為全概率公式或者全集分解爬立。

那么我們?nèi)绻胫老姥保绻遄右呀?jīng)失竊吟策,這三個小偷的誰偷的概率最大呢檩坚?按照常理來講冲杀,誰的偷盜能力最強权谁,其實誰偷竊的概率就最大旺芽。這是我們通過日常生活總結(jié)出的經(jīng)驗辐啄。那么如何用理論計算呢壶辜?
按照警察的描述砸民,一定是:在村子失竊的基礎(chǔ)上去查看他們?nèi)齻€偷盜的可能性岭参。
以計算Aj小偷的可能性為例:
P(A_j|B)=\frac {P(A_jB)} { P(B) }=\frac {P(A_j)P(B|A_j)}{P(B)}
而P(B)可以帶入全概率公式演侯,得:
P(A_j|B)=\frac{P(A_j B)}{P(B)} = \frac{P(A_j)P(B|A_j)}{\sum_{i=1}^{n}P(A_i)P(B | A_i)}
以上公式便是我們的主角——貝葉斯公式秒际。
如果小伙伴對以上推導(dǎo)過程有疑問娄徊,請參考概率公式部分匯總

貝葉斯在機器學(xué)習(xí)中化簡

對于上述三個小偷轴猎,都面臨對于此案件的調(diào)查嵌莉,也就是說對于計算三個小偷實施盜竊可能性的貝葉斯公式里,P(B)始終是恒定的捻脖。因此P(A_j|B) \propto P(A_j)P(B|A_j)锐峭。
下面通俗的介紹兩個概念:

最大似然估計:最符合觀測數(shù)據(jù)的(P(B|A)最大),最有優(yōu)勢可婶。
奧卡姆剃刀:P(A)越大的模型具有較大優(yōu)勢沿癞。

樸素貝葉斯

在上面我們已經(jīng)完整介紹了一下貝葉斯公式矛渴,接下來我們把問題細(xì)化:
假設(shè)案件B中包含b_1 \cdots b_n個小案件(如椎扬,b1=丟了一個尿壺,b2=門被撬壞了等等)具温,那么:
P(A_j)P(B|A_j)=P(A_j)P(b_1 \cdots b_n|A_j)
接下來我們可以把公式按照概率公式部分匯總中的第6個公式進(jìn)行拆分:
P(A_j)P(b_1 \cdots b_n|A_j)=P(A_j)P(b_1|A_j)P(b_2|Ajb_1) \cdots P(b_n|A_jb_1 \cdots b_{n-1})
樸素二字如何理解蚕涤?假設(shè)這些小案件全部都是獨立的,也就是說撬門和偷尿壺毫無關(guān)系時铣猩,我們繼續(xù)根據(jù)概率公式部分匯總第7個公式繼續(xù)把問題簡化:
P(A_j)P(b_1 \cdots b_n|A_j)=P(A_j)P(b_1|Aj) \dots P(b_n|Aj)
那么我們就可以把最原始的復(fù)雜問題變成了揖铜,統(tǒng)計出小偷A(chǔ)j偷尿壺的概率,撬鎖的概率达皿,然后再把它們乘起來即可天吓!這就是樸素貝葉斯贿肩。把一個復(fù)雜的問題化簡成了一個個的可統(tǒng)計的獨立概率,然后再乘起來龄寞。??:但是前提是汰规,這些小案件要盡量做到相互獨立!

利用樸素貝葉斯的文本分析和關(guān)鍵詞提取

Tf-idf:詞頻-逆詞頻
  1. 首先在文本中去掉匹配到的停用詞
  2. TF(詞頻)=\frac {某詞在文章中出現(xiàn)次數(shù)}{總詞數(shù)}
  3. IDF(逆詞頻)=\log \frac{語料庫的文檔總數(shù)}{包含這個詞的文檔數(shù) + 1}
  4. Tf-idf=TF·IDF
如何判斷語句的相似度
詞向量相似度:
  1. 將文檔分詞物邑。
  2. 將分好詞去重溜哮,組裝成語料庫。
  3. 統(tǒng)計句子中的詞在語料庫中的詞頻拂封。
  4. 利用詞頻構(gòu)建詞頻向量茬射。
n維空間下余弦相似度(值越小越相似):

\cos \theta = \frac {\sum_{i=1}^{n} x_{i} \cdot y_{i} }{\sqrt{\sum_{i=1}^{n} {x_{i}}^{2}} \cdot \sqrt{\sum_{i=1}^{n} {y_{i}}^{2}}}

利用樸素貝葉斯進(jìn)行新聞分類

我們拿到了一批新聞數(shù)據(jù),經(jīng)過加工之后冒签,變成了如下格式:

一批新聞數(shù)據(jù)

其中,category就是這批數(shù)據(jù)的標(biāo)簽钟病,也就是說萧恕,這次我們的任務(wù):根據(jù)content中描述的內(nèi)容,預(yù)測是數(shù)據(jù)哪種category肠阱。

  • 我們首先對content的每一個新聞進(jìn)行分詞票唆,這里我們使用jieba分詞器:
content_S = []
for line in content:
    current_segment = jieba.lcut(line)
    if len(current_segment) > 1 and current_segment != '\r\n': #換行符
        content_S.append(current_segment)

#將結(jié)果集轉(zhuǎn)換為dataFrame
df_content=pd.DataFrame({'content_S':content_S})
print(df_content.head())

我們拿到了一個結(jié)果集df_content,每一條都是分好詞的句子,樣子如下:

                                           content_S
0  [經(jīng)銷商,  , 電話,  , 試駕, /, 訂車, U, 憬, 杭州, 濱江區(qū), 江陵, ...
1  [呼叫, 熱線,  , 4, 0, 0, 8, -, 1, 0, 0, -, 3, 0, 0...
2  [M, I, N, I, 品牌, 在, 二月, 曾經(jīng), 公布, 了, 最新, 的, M, I...
3  [清倉, 大, 甩賣, 屹徘!, 一汽, 夏利, N, 5, 走趋、, 威志, V, 2, 低至, ...
4  [在, 今年, 3, 月, 的, 日內(nèi)瓦, 車展, 上, ,, 我們, 見到, 了, 高爾夫...
  • 導(dǎo)入停用詞表噪伊,隨便在網(wǎng)上搜一搜就有了哈簿煌,將每條分好詞的新聞中,過濾掉相應(yīng)的停用詞鉴吹,以免影響我們的訓(xùn)練分析姨伟。
#讀取停用詞表 index_col=False新加入一列,作為行號豆励,quoting=3是可以正確解讀文本里的引號
stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')


# 過濾掉停用詞
def drop_stopwords(contents, stopwords):
    contents_clean = []
    all_words = []
    for line in contents:
        line_clean = []
        for word in line:
            if word in stopwords:
                continue
            line_clean.append(word)
            all_words.append(str(word))
        contents_clean.append(line_clean)
    return contents_clean, all_words


contents = df_content.content_S.values.tolist()
stopwords = stopwords.stopword.values.tolist()
contents_clean, all_words = drop_stopwords(contents, stopwords)
#干干凈凈的分詞后的列表
df_content=pd.DataFrame({'contents_clean':contents_clean})
  • 細(xì)心的小伙伴可以看到夺荒,上述代碼中,我們將全部采納的詞匯保存到了all_words變量中良蒸,而我們并未對其使用技扼,那么接下來我們利用此變量進(jìn)行詞頻統(tǒng)計,并且繪制詞云圖片嫩痰。
#統(tǒng)計全詞列表中的詞頻
result = pd.value_counts(all_words)
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
wordcloud = WordCloud(font_path="simhei.ttf", background_color="white", max_font_size=80,)
word_frequence = result.to_dict()
wordcloud = wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud)
d = path.dirname(__file__)
wordcloud.to_file(path.join(d, 'alice_colored2.png'))
詞云

我又用別的文章剿吻,單獨玩了一下詞云:


另一篇詞頻統(tǒng)計
  • 接下來,我們嘗試對其中一條新聞進(jìn)行關(guān)鍵詞提取
#關(guān)鍵詞提取
import jieba.analyse
#分析第二十條新聞
index = 20
print(df_news['content'][index])
content_S_str = "".join(content_S[index])
print("  ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))
  • 利用LDA(主題始赎,文章和橙,詞)模型仔燕,對全體文章進(jìn)行主題歸類
from gensim import corpora, models, similarities
import gensim
#做映射,相當(dāng)于詞袋
dictionary = corpora.Dictionary(contents_clean)
corpus = [dictionary.doc2bow(sentence) for sentence in contents_clean] #將詞映射成數(shù)字
lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) #20個大分類
for topic in lda.print_topics(num_topics=20, num_words=5):
    print(topic)

部分主題打印如下:

(0, '0.016*"a" + 0.015*"e" + 0.013*"i" + 0.012*"o" + 0.011*"n"')
(1, '0.010*"i" + 0.007*"e" + 0.007*"a" + 0.006*"中" + 0.005*"o"')
(2, '0.006*"選手" + 0.006*"萬" + 0.006*"中國" + 0.006*"奢侈品" + 0.004*"申花"')
(3, '0.005*"中" + 0.005*"女人" + 0.004*"男人" + 0.003*"D" + 0.003*"說"')
(4, '0.005*"中" + 0.004*"肌膚" + 0.004*"時間" + 0.003*"吃" + 0.003*"水"')
(5, '0.006*"工作" + 0.006*"說" + 0.005*"學(xué)生" + 0.005*"發(fā)展" + 0.005*"文化"')
(6, '0.008*"中" + 0.005*"L" + 0.004*"電影" + 0.004*"D" + 0.004*"T"')
(7, '0.009*"中國" + 0.006*"撒" + 0.006*"電影" + 0.004*"產(chǎn)品" + 0.004*"中"')
  • 下面我們針對category對數(shù)據(jù)進(jìn)行預(yù)測啦魔招!
#組裝格式晰搀,并把label映射成數(shù)字,切分訓(xùn)練集和測試集
df_train=pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})
label_mapping = {"汽車": 1, "財經(jīng)": 2, "科技": 3, "健康": 4, "體育":5, "教育": 6,"文化": 7,"軍事": 8,"娛樂": 9,"時尚": 0}
df_train['label'] = df_train['label'].map(label_mapping)
x_train, x_test, y_train, y_test = train_test_split(df_train['contents_clean'].values, df_train['label'].values, random_state=1)
  • 此時我們拿到的x格式我list of list,而我們需要類似['a b c','d e f']的格式即將內(nèi)部的list變成一個字符串:
#改變訓(xùn)練集數(shù)據(jù)格式办斑,方便下一步的數(shù)據(jù)輸入
words = []
for line_index in range(len(x_train)):
    try:
        words.append(' '.join(x_train[line_index]))
    except:
        print(line_index)
  • 構(gòu)建詞向量
#構(gòu)建詞向量
from sklearn.feature_extraction.text import CountVectorizer
vec = CountVectorizer(analyzer='word', max_features=4000,  lowercase = False)
vec.fit(words)
  • 導(dǎo)入樸素貝葉斯外恕,訓(xùn)練分類器:
#貝葉斯訓(xùn)練
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vec.transform(words), y_train)
  • 同樣的,我們需要改變測試集的輸入格式:
#改變測試集數(shù)據(jù)格式乡翅,方便下一步的數(shù)據(jù)輸入
test_words = []
for line_index in range(len(x_test)):
    try:
        #x_train[line_index][word_index] = str(x_train[line_index][word_index])
        test_words.append(' '.join(x_test[line_index]))
    except:
         print (line_index)
  • 預(yù)測
print(classifier.score(vec.transform(test_words), y_test))
  • 同樣我們也可以使用Tf-idf的形式構(gòu)建詞向量:
#使用tf-idf構(gòu)造向量
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(analyzer='word', max_features=4000,  lowercase = False)
vectorizer.fit(words)

classifier = MultinomialNB()
classifier.fit(vectorizer.transform(words), y_train)
print(classifier.score(vectorizer.transform(test_words), y_test))

完整代碼

import pandas as pd
import jieba
import numpy
from os import path
from sklearn.model_selection import train_test_split


df_news = pd.read_table('data.txt',names=['category','theme','URL','content'],encoding='utf-8')
df_news = df_news.dropna()#去掉含有缺失值的行
print(df_news.head())

content = df_news.content.values.tolist(); # 把表格的一列提取出來搞成一個list
print(content[100])


#分詞鳞疲,把分詞后的結(jié)果放到結(jié)果集content_S里
content_S = []
for line in content:
    current_segment = jieba.lcut(line)
    if len(current_segment) > 1 and current_segment != '\r\n': #換行符
        content_S.append(current_segment)

#將結(jié)果集轉(zhuǎn)換為dataFrame
df_content=pd.DataFrame({'content_S':content_S})
print(df_content.head())

#讀取停用詞表 index_col=False新加入一列,作為行號蠕蚜,quoting=3是可以正確解讀文本里的引號
stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')


# 過濾掉停用詞
def drop_stopwords(contents, stopwords):
    contents_clean = []
    all_words = []
    for line in contents:
        line_clean = []
        for word in line:
            if word in stopwords:
                continue
            line_clean.append(word)
            all_words.append(str(word))
        contents_clean.append(line_clean)
    return contents_clean, all_words


contents = df_content.content_S.values.tolist()
stopwords = stopwords.stopword.values.tolist()
contents_clean, all_words = drop_stopwords(contents, stopwords)

#干干凈凈的分詞后的列表
df_content=pd.DataFrame({'contents_clean':contents_clean})

#全部詞匯尚洽,也整一個全詞列表
df_all_words=pd.DataFrame({'all_words':all_words})
#統(tǒng)計全詞列表中的詞頻
result = pd.value_counts(all_words)
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
wordcloud = WordCloud(font_path="simhei.ttf", background_color="white", max_font_size=80,)
word_frequence = result.to_dict()
wordcloud = wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud)
d = path.dirname(__file__)
wordcloud.to_file(path.join(d, 'alice_colored2.png'))



#關(guān)鍵詞提取
import jieba.analyse
index = 20
print(df_news['content'][index])
content_S_str = "".join(content_S[index])
print("  ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))


#LDA模型:主題,文章靶累,詞
from gensim import corpora, models, similarities
import gensim
#做映射腺毫,相當(dāng)于詞袋
dictionary = corpora.Dictionary(contents_clean)
corpus = [dictionary.doc2bow(sentence) for sentence in contents_clean] #將詞映射成數(shù)字
lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) #20個大分類
for topic in lda.print_topics(num_topics=20, num_words=5):
    print(topic)





#組裝格式,并把label映射成數(shù)字,切分訓(xùn)練集和測試集
df_train=pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})
label_mapping = {"汽車": 1, "財經(jīng)": 2, "科技": 3, "健康": 4, "體育":5, "教育": 6,"文化": 7,"軍事": 8,"娛樂": 9,"時尚": 0}
df_train['label'] = df_train['label'].map(label_mapping)
x_train, x_test, y_train, y_test = train_test_split(df_train['contents_clean'].values, df_train['label'].values, random_state=1)

#改變訓(xùn)練集數(shù)據(jù)格式挣柬,方便下一步的數(shù)據(jù)輸入
words = []
for line_index in range(len(x_train)):
    try:
        words.append(' '.join(x_train[line_index]))
    except:
        print(line_index)
print(words)

#構(gòu)建詞向量
from sklearn.feature_extraction.text import CountVectorizer
vec = CountVectorizer(analyzer='word', max_features=4000,  lowercase = False)
vec.fit(words)

#貝葉斯訓(xùn)練
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vec.transform(words), y_train)


#改變測試集數(shù)據(jù)格式潮酒,方便下一步的數(shù)據(jù)輸入
test_words = []
for line_index in range(len(x_test)):
    try:
        #x_train[line_index][word_index] = str(x_train[line_index][word_index])
        test_words.append(' '.join(x_test[line_index]))
    except:
         print (line_index)

print(classifier.score(vec.transform(test_words), y_test))


#使用tf-idf構(gòu)造向量
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(analyzer='word', max_features=4000,  lowercase = False)
vectorizer.fit(words)

classifier = MultinomialNB()
classifier.fit(vectorizer.transform(words), y_train)
print(classifier.score(vectorizer.transform(test_words), y_test))

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市邪蛔,隨后出現(xiàn)的幾起案子急黎,更是在濱河造成了極大的恐慌,老刑警劉巖侧到,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勃教,死亡現(xiàn)場離奇詭異,居然都是意外死亡床牧,警方通過查閱死者的電腦和手機荣回,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戈咳,“玉大人心软,你說我怎么就攤上這事≈埽” “怎么了删铃?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長踏堡。 經(jīng)常有香客問我猎唁,道長,這世上最難降的妖魔是什么顷蟆? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任诫隅,我火速辦了婚禮腐魂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逐纬。我一直安慰自己蛔屹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布豁生。 她就那樣靜靜地躺著兔毒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甸箱。 梳的紋絲不亂的頭發(fā)上育叁,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音芍殖,去河邊找鬼豪嗽。 笑死,一個胖子當(dāng)著我的面吹牛围小,可吹牛的內(nèi)容都是我干的昵骤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肯适,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了成榜?” 一聲冷哼從身側(cè)響起框舔,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赎婚,沒想到半個月后刘绣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡挣输,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年纬凤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撩嚼。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡停士,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出完丽,到底是詐尸還是另有隱情恋技,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布逻族,位于F島的核電站蜻底,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏聘鳞。R本人自食惡果不足惜薄辅,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一要拂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧站楚,春花似錦脱惰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谁尸,卻和暖如春舅踪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背良蛮。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工抽碌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人决瞳。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓货徙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親皮胡。 傳聞我的和親對象是個殘疾皇子痴颊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容