貝葉斯公式
首先我們用一個例子來解釋一下貝葉斯公式的使用。
有一個村子润脸,里面一共有三個小偷毙驯,他們的偷竊能力分別是
,如何求出這個村子出現(xiàn)失竊案件的概率P(B)爆价?
分析:
首先我們知道,這個村子中只有三個小偷蛾号,因此三個小偷構(gòu)成了一個完備事件組,即他們的能力的總和為全集活逆,且相互之間獨立蔗候。因此我們可以建立等式:
相互獨立
如果這個村子里有n個小偷的話锈遥,我們可以總結(jié)成以下公式:
以上便可以求得村子失竊的概率P(B)所灸,而這個公式也被稱為全概率公式或者全集分解爬立。
那么我們?nèi)绻胫老姥保绻遄右呀?jīng)失竊吟策,這三個小偷的誰偷的概率最大呢檩坚?按照常理來講冲杀,誰的偷盜能力最強权谁,其實誰偷竊的概率就最大旺芽。這是我們通過日常生活總結(jié)出的經(jīng)驗辐啄。那么如何用理論計算呢壶辜?
按照警察的描述砸民,一定是:在村子失竊的基礎(chǔ)上去查看他們?nèi)齻€偷盜的可能性岭参。
以計算Aj小偷的可能性為例:
而P(B)可以帶入全概率公式演侯,得:
以上公式便是我們的主角——貝葉斯公式秒际。
如果小伙伴對以上推導(dǎo)過程有疑問娄徊,請參考概率公式部分匯總。
貝葉斯在機器學(xué)習(xí)中化簡
對于上述三個小偷轴猎,都面臨對于此案件的調(diào)查嵌莉,也就是說對于計算三個小偷實施盜竊可能性的貝葉斯公式里,P(B)始終是恒定的捻脖。因此锐峭。
下面通俗的介紹兩個概念:
最大似然估計:最符合觀測數(shù)據(jù)的(P(B|A)最大),最有優(yōu)勢可婶。
奧卡姆剃刀:P(A)越大的模型具有較大優(yōu)勢沿癞。
樸素貝葉斯
在上面我們已經(jīng)完整介紹了一下貝葉斯公式矛渴,接下來我們把問題細(xì)化:
假設(shè)案件B中包含個小案件(如椎扬,b1=丟了一個尿壺,b2=門被撬壞了等等)具温,那么:
接下來我們可以把公式按照概率公式部分匯總中的第6個公式進(jìn)行拆分:
樸素二字如何理解蚕涤?假設(shè)這些小案件全部都是獨立的,也就是說撬門和偷尿壺毫無關(guān)系時铣猩,我們繼續(xù)根據(jù)概率公式部分匯總第7個公式繼續(xù)把問題簡化:
那么我們就可以把最原始的復(fù)雜問題變成了揖铜,統(tǒng)計出小偷A(chǔ)j偷尿壺的概率,撬鎖的概率达皿,然后再把它們乘起來即可天吓!這就是樸素貝葉斯贿肩。把一個復(fù)雜的問題化簡成了一個個的可統(tǒng)計的獨立概率,然后再乘起來龄寞。??:但是前提是汰规,這些小案件要盡量做到相互獨立!
利用樸素貝葉斯的文本分析和關(guān)鍵詞提取
Tf-idf:詞頻-逆詞頻
- 首先在文本中去掉匹配到的停用詞
- Tf-idf=TF·IDF
如何判斷語句的相似度
詞向量相似度:
- 將文檔分詞物邑。
- 將分好詞去重溜哮,組裝成語料庫。
- 統(tǒng)計句子中的詞在語料庫中的詞頻拂封。
- 利用詞頻構(gòu)建詞頻向量茬射。
n維空間下余弦相似度(值越小越相似):
利用樸素貝葉斯進(jìn)行新聞分類
我們拿到了一批新聞數(shù)據(jù),經(jīng)過加工之后冒签,變成了如下格式:
其中,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'))
我又用別的文章剿吻,單獨玩了一下詞云:
- 接下來,我們嘗試對其中一條新聞進(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))