日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

朴素Bayse新闻分类实践

發(fā)布時(shí)間:2025/3/15 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 朴素Bayse新闻分类实践 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 1、信息增益(互信息)介紹
    • (1)西瓜書中的信息增益[^1]
    • (2)PRML中的互信息[^2]
    • (3) 其實(shí)他們是一個(gè)東西
  • 2、樸素Bayse新聞分類[^3]
    • (1)常量及輔助函數(shù)
    • (2)特征提取
    • (3)訓(xùn)練模型
    • (4)預(yù)測
    • (5)測試
    • (6)測試結(jié)果

1、信息增益(互信息)介紹

由于在最終的bayse算法中只使用了部分的特征,而特征的選擇使用到了信息增益,所以在這里做一個(gè)簡單的介紹。

(1)西瓜書中的信息增益1

在西瓜書的4.2節(jié)中,選擇樹節(jié)點(diǎn)的劃分屬性時(shí)提到了信息增益;其定義如下:
首先是元集合D的類別信息熵

Ent(D)=?∑k=1∣y∣pklog2(pk)Ent(D)=-\sum_{k=1}^{\left | y \right |}p_{k}log_{2}(p_{k}) Ent(D)=?k=1y?pk?log2?(pk?)
然后根據(jù)屬性a劃分為了V個(gè)集合后,給出了信息增益的定義:
Gain(D,a)=Ent(D)?∑v=1V∣Dv∣∣D∣Ent(Dv)Gain(D, a)=Ent(D) - \sum_{v=1}^{V}\frac{\left | D^{v} \right |}{\left | D \right |}Ent(D^v) Gain(D,a)=Ent(D)?v=1V?DDv?Ent(Dv)
然后利用信息增益來進(jìn)行樹的劃分特征的選取。

(2)PRML中的互信息2

在PRML1.6.1中定義了互信息,公式如下:
I[x,y]≡KL(p(x,y)∣∣p(x)p(y))=??p(x,y)ln(p(x)p(y)p(x,y))dxdyI[x, y] \equiv KL(p(x, y)|| p(x)p(y)) = - \iint p(x,y)ln(\frac{p(x)p(y)}{p(x,y)}) dxdy I[x,y]KL(p(x,y)p(x)p(y))=??p(x,y)ln(p(x,y)p(x)p(y)?)dxdy
化簡后可以得到:
I[x,y]≡H[x]?H[x∣y]=H[y]?H[y∣x]I[x,y]\equiv H[x] - H[x|y] = H[y] - H[y|x] I[x,y]H[x]?H[xy]=H[y]?H[yx]

(3) 其實(shí)他們是一個(gè)東西

證明:首先把1、->(2)中的積分形式改寫成和的形式,并把ln還成log(相差了log2倍),有
?∑x,yp(x,y)log2(p(x)p(y)p(x,y))-\sum_{x,y}p(x,y)log_{2}(\frac{p(x)p(y)}{p(x,y)})?x,y?p(x,y)log2?(p(x,y)p(x)p(y)?)
=?∑y∑xp(x,y)log2(p(y))?(?∑xp(x)∑yp(y∣x)log2(p(y∣x)))= -\sum_{y}\sum_{x}p(x,y)log_{2}(p(y)) - (-\sum_{x}p(x)\sum_{y}p(y|x)log_{2}(p(y|x)))=?y?x?p(x,y)log2?(p(y))?(?x?p(x)y?p(yx)log2?(p(yx)))
=?∑yp(y)log2(p(y))?(?∑xp(x)∑yp(y∣x)log2(p(y∣x)))=-\sum_{y}p(y)log_{2}(p(y))-(-\sum_{x}p(x)\sum_{y}p(y|x)log_{2}(p(y|x)))=?y?p(y)log2?(p(y))?(?x?p(x)y?p(yx)log2?(p(yx)))

仔細(xì)觀察·是不是和1、->(1)一模一樣!如下圖所示:

2、樸素Bayse新聞分類3

(1)常量及輔助函數(shù)

import math import random import collections label_dict = {0: '財(cái)經(jīng)', 1: '健康', 2: '教育', 3: '軍事', 4: '科技',5: '旅游', 6: '母嬰', 7: '汽車', 8: '體育',9: '文化', 10: '娛樂'}def code_2_label(code):return label_dict.get(code)def default_doc_dict():"""構(gòu)造和類別數(shù)等長的0向量:return: 一個(gè)長度和文檔類別數(shù)相同的全0數(shù)組,用來作為某些以該長度數(shù)組為值的字典的默認(rèn)返回值"""return [0] * len(label_dict)def shuffle(in_file):"""簡單的亂序操作,用于生成訓(xùn)練集和測試集:param in_file: 輸入文件:return:"""text_lines = [line.strip() for line in open(in_file, encoding='utf-8')]print('正在準(zhǔn)備訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù),請稍后...')random.shuffle(text_lines)total_lines = len(text_lines)train_text = text_lines[:int(3 * total_lines / 5)]test_text = text_lines[int(3 * total_lines / 5):]print('準(zhǔn)備訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù)完畢,下一步...')return train_text, test_text

(2)特征提取

根據(jù)1中的信息增益(互信息)的大小來提取前100個(gè)最重要的特征(這里就是詞了)
首先定義了如下的計(jì)算互信息的輔助函數(shù),它所計(jì)算的內(nèi)容其實(shí)是:

(注意紅色的-,我把它移到了和的內(nèi)部)

def mutual_info(N, Nij, N_i, N_j):"""計(jì)算互信息,這里log的底取為2;同時(shí)為了防止Nij為0,分子做了+1的平滑:param N:總樣本數(shù):param Nij:x為i,y為j的樣本數(shù):param N_i:x為i的樣本數(shù):param N_j:y為j的樣本數(shù):return:"""return Nij * 1.0 / N * math.log(N * (Nij + 1) * 1.0 / (N_i * N_j)) / math.log(2)

看起來并不是很清晰,因?yàn)槭腔喴院蟮摹_@里進(jìn)行一下推導(dǎo):
?p(x=i,y=j)log2(p(x=i)p(y=j)p(x=i,y=j))-p(x=i,y=j)log_{2}(\frac{p(x=i)p(y=j)}{p(x=i,y=j)})?p(x=i,y=j)log2?(p(x=i,y=j)p(x=i)p(y=j)?)
=?Ni,jN?log2(NiNNjNNi,jN)=-\frac{N_{i,j}}{N}*log_{2}(\frac{\frac{N_{i}}{N}\frac{N_{j}}{N}}{\frac{N_{i,j}}{N}})=?NNi,j???log2?(NNi,j??NNi??NNj???)
=Ni,jN?log2(NNi,jNiNj)=\frac{N_{i,j}}{N}*log_{2}(\frac{NN_{i,j}}{N_{i}N_{j}})=NNi,j???log2?(Ni?Nj?NNi,j??)
=Ni,jN?ln(NNi,jNiNj)/ln(2)=\frac{N_{i,j}}{N}*ln(\frac{NN_{i,j}}{N_{i}N_{j}})/ln(2)=NNi,j???ln(Ni?Nj?NNi,j??)/ln(2)
加上平滑以后,就得到了上面的函數(shù)(別在乎1.0,只是整數(shù)轉(zhuǎn)浮點(diǎn)數(shù))
=Ni,jN?ln(N(Ni,j+1)NiNj)/ln(2)=\frac{N_{i,j}}{N}*ln(\frac{N(N_{i,j}+1)}{N_{i}N_{j}})/ln(2)=NNi,j???ln(Ni?Nj?N(Ni,j?+1)?)/ln(2)

def count_for_cates(train_text, feature_file):"""遍歷文件,統(tǒng)計(jì)每個(gè)詞在每個(gè)類別中出現(xiàn)的次數(shù),以及每個(gè)類別中的文檔數(shù),并將結(jié)果寫入特征文件(只寫互信息值最大的前100項(xiàng)):param train_text::param feature_file::return:"""# 各個(gè)類別中所包含的詞的個(gè)數(shù)doc_count = [0] * len(label_dict)# 以word為key的字典,value是對應(yīng)該word# 在每個(gè)類別中出現(xiàn)次數(shù)的向量;該詞不存在就返回全0的向量word_count = collections.defaultdict(default_doc_dict)# 掃描文件和計(jì)數(shù)for line in train_text:label, text = line.strip().rstrip('\n').split(' ', 1)words = text.split(' ')int_label = int(label)for word in words:# 空字符串用了停用詞也沒有過濾掉,就在這里處理了if word != '':word_count[word][int_label] += 1doc_count[int_label] += 1# 計(jì)算互信息print('計(jì)算互信息,提取關(guān)鍵/特征詞中,請稍后...')# 互信息結(jié)果字典,value描述的是某個(gè)類別中的詞數(shù)# 衡量的信息量與明確是某個(gè)詞以后的以詞數(shù)衡量的信息量的互信息mi_dict = collections.defaultdict(default_doc_dict)# 詞總量N = sum(doc_count)# (word,[...各個(gè)類別中該詞出現(xiàn)的詞數(shù)...])for k, vs in word_count.items():for i in range(len(vs)):# N11代表是詞k并且出現(xiàn)在類別i中的詞數(shù)N11 = vs[i]# N10 代表是詞k但未出現(xiàn)在類別i中的詞數(shù)N10 = sum(vs) - N11# N01 代表不是詞k但出現(xiàn)在類別i中的詞數(shù)N01 = doc_count[i] - N11# N00 代表不是詞k也未出現(xiàn)在類別i中的詞數(shù)N00 = N - N11 - N10 - N01"""設(shè)D為某個(gè)類別中的詞總數(shù),A為某個(gè)詞出現(xiàn)的總次數(shù),N為總詞數(shù)則下面的式子表達(dá)的是mutual_info(N,DA,A,D) + mutual_info(N,~DA, A, ~D) + mutual_info(N,D~A, D, ~A) + mutual_info(N, ~D~A, ~D, ~A)"""mi = mutual_info(N, N11, N10 + N11, N01 + N11) + mutual_info(N, N10, N10 + N11, N00 + N10) + mutual_info(N, N01, N01 + N11, N01 + N00) + mutual_info(N, N00, N00 + N10, N00 + N01)mi_dict[k][i] = mi# 用來作為bayes參數(shù)的詞f_words = set()# 把每類文檔分類最重要的100個(gè)詞放到f_words中for i in range(len(doc_count)):sorted_dict = sorted(mi_dict.items(), key=lambda x: x[1][i], reverse=True)for j in range(100):f_words.add(sorted_dict[j][0])with open(feature_file, 'w', encoding='utf-8') as out:# 輸出每個(gè)類別中包含的詞的數(shù)量out.write(str(doc_count) + '\n')# 輸出作為參數(shù)的詞for f_word in f_words:out.write(f_word + "\n")print("特征詞寫入完畢...") def load_feature_words(feature_file):"""從特征文件中導(dǎo)入特征詞:param feature_file::return:"""with open(feature_file, encoding='utf-8') as f:# 每個(gè)類別中包含的詞的數(shù)量doc_words_count = eval(f.readline())features = set()# 讀取特征詞for line in f:features.add(line.strip())return doc_words_count, features

(3)訓(xùn)練模型

def train_bayes(feature_file, text, model_file):"""訓(xùn)練貝葉斯模型,實(shí)際上計(jì)算每個(gè)類別中特征詞的出現(xiàn)次數(shù):param feature_file: 特征文件:param text: 原始的樣本:param model_file: 模型文件:return:"""print('使用樸素貝葉斯訓(xùn)練中...')doc_words_count, features = load_feature_words(feature_file)feature_word_count = collections.defaultdict(default_doc_dict)# 每類文檔中特征詞出現(xiàn)的總次數(shù)feature_doc_words_count = [0] * len(doc_words_count)for line in text:label, text = line.strip().rstrip('\n').split(' ', 1)int_label = int(label)words = text.split(' ')for word in words:if word in features:feature_doc_words_count[int_label] += 1feature_word_count[word][int_label] += 1out_model = open(model_file, 'w', encoding='utf-8')print('訓(xùn)練完畢,寫入模型...')for k, v in feature_word_count.items():scores = [(v[i] + 1) * 1.0 / (feature_doc_words_count[i] + len(feature_word_count)) for i in range(len(v))]out_model.write(k + '\t' + str(scores) + '\n') def load_model(model_file):"""從模型文件中導(dǎo)入計(jì)算好的貝葉斯模型:param model_file::return:"""print('加載模型中...')with open(model_file, encoding='utf-8') as f:scores = {}for line in f.readlines():word, counts = line.split('\t', 1)scores[word] = eval(counts)return scores

(4)預(yù)測

def predict(feature_file, model_file, test_text):"""預(yù)測文檔的類別,標(biāo)準(zhǔn)輸入每一行為一個(gè)文檔這是一個(gè)樸素貝葉斯的預(yù)測方法p(c|x) 正比于 p(c)p(x1|c)....p(xn|c):param feature_file::param model_file::param test_text::return:"""doc_words_count, features = load_feature_words(feature_file)# p(c)doc_scores = [math.log(count * 1.0 / sum(doc_words_count)) for count in doc_words_count]scores = load_model(model_file)r_count = 0doc_count = 0print("正在使用測試數(shù)據(jù)驗(yàn)證模型效果...")for line in test_text:label, text = line.strip().split(' ', 1)int_label = int(label)words = text.split(' ')pre_values = list(doc_scores)for word in words:if word in features:for i in range(len(pre_values)):pre_values[i] += math.log(scores[word][i])m = max(pre_values)p_index = pre_values.index(m)if p_index == int_label:r_count += 1doc_count += 1print("總共測試文本量: %d ,預(yù)測正確的類別量:%d,樸素貝葉斯分類器準(zhǔn)確度:%f" %(doc_count, r_count, r_count * 1.0 / doc_count))

(5)測試

if __name__ == '__main__':out_in_file = 'd:/nlps/result.txt'out_feature_file = 'd:/nlps/feature.txt'out_model_file = 'd:/nlps/model.txt'train_text, test_text = shuffle(out_in_file)count_for_cates(train_text, out_feature_file)train_bayes(out_feature_file, train_text, out_model_file)predict(out_feature_file, out_model_file, test_text)

(6)測試結(jié)果


  • 周志華 《機(jī)器學(xué)習(xí)》 4.2節(jié) ??

  • Bishop “Pattern Recognition and Machine Learning” 1.6.1 ??

  • 寒小陽 ??

  • 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的朴素Bayse新闻分类实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。