樸素貝葉斯-新聞文本分類(lèi)

貝葉斯公式

「樸素貝葉斯」

具體理論就不詳細(xì)講解了仓洼,網(wǎng)上一搜一大把宦言。其核心思想就是: 樸素貝葉斯 = 條件獨(dú)立假設(shè) + 貝葉斯方法。運(yùn)行速度快换可,在滿(mǎn)足分布獨(dú)立這一假設(shè)條件下分類(lèi)效果好椎椰,但對(duì)于訓(xùn)練集中沒(méi)有出現(xiàn)過(guò)的詞語(yǔ)要平滑處理,數(shù)值型變量特征默認(rèn)符合正態(tài)分布沾鳄。

「Python實(shí)現(xiàn)」

導(dǎo)入停用詞

導(dǎo)入停用詞庫(kù)慨飘,同時(shí)使用strip()方法剔除不需要的空白符,包括('\n', '\r', '\t', ' ')

def make_word_set(words_file):
    words_set = set()
    with codecs.open(words_file,'r','utf-8') as fp:
        for line in fp:
            word = line.strip()
            if len(word) > 0 and word not in words_set:
                words_set.add(word)
    return words_set

文本處理,樣本生成

每個(gè)新聞文本txt文件在各自所屬類(lèi)別的文件夾中瓤的,結(jié)構(gòu)如下:

"folder_path"
⌒萜|
 |-- C000008 -- 1.txt / 2.txt / ... / 19.txt
∪Ω唷|-- C000010
∷|-- C000013
 |-- ...
』ぁ|-- C000024

這里使用os.listdir()讀取指定目錄下的所有文件夾名(即分類(lèi)類(lèi)別)丈甸,遍歷各自文件夾(類(lèi)別)內(nèi)的文本文件,對(duì)每一個(gè)txt文件進(jìn)行文本切詞尿褪,同時(shí)利用zip()函數(shù)使每個(gè)新聞文本與所屬類(lèi)別一一對(duì)應(yīng)睦擂,一共有90條數(shù)據(jù)。

為了隨機(jī)抽取訓(xùn)練與測(cè)試數(shù)據(jù)集杖玲,用random.shuffle()打亂順序顿仇,并選取20%的數(shù)據(jù)用于測(cè)試,同時(shí)把特征數(shù)據(jù)與類(lèi)別數(shù)據(jù)各自分開(kāi)摆马。

最后對(duì)訓(xùn)練數(shù)據(jù)集中的詞語(yǔ)進(jìn)行詞頻統(tǒng)計(jì)臼闻。這里有使用sorted()函數(shù)進(jìn)行排序,方法為sorted(iterable, cmp = None, key = None, reverse = False)今膊,其中參數(shù)含義如下:

  • iterable:是可迭代類(lèi)型(我這里的可迭代類(lèi)型為字典)
  • cmp:用于比較的函數(shù)些阅,比較什么由key決定(這里沒(méi)用到)
  • key:用列表元素的某個(gè)屬性或函數(shù)進(jìn)行作為關(guān)鍵字(這里使用字典中的“值”大小作為關(guān)鍵字排序)
  • reverse:排序規(guī)則伞剑,True為降序(False為升序)
def text_processing(folder_path, test_size = 0.2):
    folder_list = os.listdir(folder_path)
    data_list = []
    class_list = []
    # 遍歷文件夾
    for folder in folder_list:
        new_folder_path = os.path.join(folder_path,folder)
        files = os.listdir(new_folder_path)
        j = 1
        for file in files:
            if j > 100: # 防止內(nèi)存爆掉
                break
            with codecs.open(os.path.join(new_folder_path, file), 'r', 'utf-8') as fp:
                raw = fp.read()
                word_cut = jieba.cut(raw, cut_all = False)
                word_list = list(word_cut)
                data_list.append(word_list) # 訓(xùn)練集
                class_list.append(folder)   # 類(lèi)別
                j += 1      

    # 劃分訓(xùn)練集和測(cè)試集
    data_class_list = list(zip(data_list, class_list))
    random.shuffle(data_class_list)    # 打亂順序
    index = int(len(data_class_list) * test_size) + 1   # 抽取測(cè)試數(shù)據(jù)集的占比
    train_list = data_class_list[index:]
    test_list = data_class_list[:index]
    train_data_list,train_class_list = zip(*train_list) # 特征與標(biāo)簽
    test_data_list,test_class_list = zip(*test_list) 

    # 統(tǒng)計(jì)詞頻
    all_words_dict = {}
    for word_list in train_data_list:
        for word in word_list:
            if word in all_words_dict:
                all_words_dict[word] += 1
            else:
                all_words_dict[word] = 1
            
    # 降序排序(key函數(shù))
    all_words_tuple_list = sorted(all_words_dict.items(),key = lambda f:f[1], reverse = True)
    all_words_list = list(zip(*all_words_tuple_list))[0]
    
    return all_words_list, train_data_list, test_data_list, train_class_list, test_class_list

特征選擇

這里我們僅選取詞頻坐高的1000個(gè)特征詞(維度)斑唬,并剔除數(shù)字與停用詞。

def words_dict(all_words_list,deleteN,stopwords_set=set()):
    feature_words = []
    n = 1
    for t in range(deleteN,len(all_words_list),1):
        if n > 1000:    # 最多取1000個(gè)維度
            break
        if not all_words_list[t].isdigit() and all_words_list[t] not in stopwords_set and 1 < len(all_words_list[t]) < 5:
            feature_words.append(all_words_list[t])
            n += 1
    return feature_words

用選取的特征詞構(gòu)建0-1矩陣

對(duì)訓(xùn)練數(shù)據(jù)集train_data_list中每篇切完詞之后的文檔構(gòu)建特征向量(由上述1000個(gè)特征詞組成)黎泣,若出現(xiàn)則取值為1恕刘,否則為0。于是90篇文章構(gòu)建出了[90,1000]維度的0-1矩陣(其中71行為訓(xùn)練數(shù)據(jù)抒倚,19行為測(cè)試數(shù)據(jù))褐着。

訓(xùn)練集如下:

0-1矩陣如下:

def text_features(train_data_list, test_data_list, feature_words):
    def text_features(text,feature_words):
        # text = train_data_list[0]
        text_words = set(text)
        features = [1 if word in text_words else 0 for word in feature_words]
        return features
        
    # 0,1的矩陣(1000列-維度)    
    train_feature_list = [text_features(text, feature_words) for text in train_data_list]
    test_feature_list = [text_features(text, feature_words) for text in test_data_list]
    return train_feature_list,test_feature_list

樸素貝葉斯分類(lèi)器

這里使用開(kāi)源sklearn庫(kù)中的樸素貝葉斯分類(lèi)器,輸入?yún)?shù)分別為訓(xùn)練集的0-1特征矩陣(train_feature_list)與訓(xùn)練集分類(lèi)(train_class_list)托呕,然后對(duì)測(cè)試數(shù)據(jù)的輸出與真實(shí)結(jié)果進(jìn)行比較含蓉,得到準(zhǔn)確度為0.68

def text_classifier(train_feature_list,test_feature_list,train_class_list,test_class_list):
    # sklearn多項(xiàng)式分類(lèi)器
    classifier = MultinomialNB().fit(train_feature_list,train_class_list)   # 特征向量與類(lèi)別
    test_accuracy = classifier.score(test_feature_list,test_class_list)
    return test_accuracy

這里我們僅選取詞頻最高的1000個(gè)作為特征向量,不妨嘗試下選取其他的關(guān)鍵字作為特征向量项郊,發(fā)現(xiàn)準(zhǔn)確率都在0.63以上馅扣,分類(lèi)效果還算可以,見(jiàn)下圖:

if __name__ == '__main__':
    # 文本預(yù)處理(分詞着降、劃分訓(xùn)練與測(cè)試集差油、排序)
    folder_path = '...'
    all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = text_processing(folder_path, test_size = 0.2)
    
    # stopwords_set
    stopwords_file = '...'
    stopwords_set = make_word_set(stopwords_file)

    # 特征提取與分類(lèi)
    deleteNs = range(0,1000,20)
    test_accuracy_list = []
    for deleteN in deleteNs:
        # 選取1000個(gè)特征
        feature_words = words_dict(all_words_list,deleteN,stopwords_set)
        # 計(jì)算特征向量
        train_feature_list, test_feature_list = text_features(train_data_list,test_data_list,feature_words)
        # sklearn分類(lèi)器計(jì)算準(zhǔn)確度
        test_accuracy = text_classifier(train_feature_list,test_feature_list,train_class_list,test_class_list)
        # 不同特征向量下的準(zhǔn)確度
        test_accuracy_list.append(test_accuracy)
    print(test_accuracy_list)

    # 結(jié)果評(píng)價(jià)
    plt.figure()
    plt.plot(deleteNs,test_accuracy_list)
    plt.title('Relationship of deleteNs and test_accuracy')
    plt.xlabel('deleteNs')
    plt.ylabel('test_accuracy')
    plt.savefig('result.png',dpi = 100)
    plt.show()

參考資料

用樸素貝葉斯進(jìn)行文本分類(lèi)
樸素貝葉斯分類(lèi)器的應(yīng)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蓄喇,更是在濱河造成了極大的恐慌发侵,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妆偏,死亡現(xiàn)場(chǎng)離奇詭異刃鳄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)楼眷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)铲汪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人罐柳,你說(shuō)我怎么就攤上這事掌腰。” “怎么了张吉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵齿梁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我肮蛹,道長(zhǎng)勺择,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任伦忠,我火速辦了婚禮省核,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昆码。我一直安慰自己气忠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布赋咽。 她就那樣靜靜地躺著旧噪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脓匿。 梳的紋絲不亂的頭發(fā)上淘钟,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音陪毡,去河邊找鬼米母。 笑死,一個(gè)胖子當(dāng)著我的面吹牛毡琉,可吹牛的內(nèi)容都是我干的铁瞒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼绊起,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼精拟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蜂绎,失蹤者是張志新(化名)和其女友劉穎栅表,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體师枣,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怪瓶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了践美。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洗贰。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖陨倡,靈堂內(nèi)的尸體忽然破棺而出敛滋,到底是詐尸還是另有隱情,我是刑警寧澤兴革,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布绎晃,位于F島的核電站,受9級(jí)特大地震影響杂曲,放射性物質(zhì)發(fā)生泄漏庶艾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一擎勘、第九天 我趴在偏房一處隱蔽的房頂上張望咱揍。 院中可真熱鬧,春花似錦棚饵、人聲如沸煤裙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)积暖。三九已至藤为,卻和暖如春怪与,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缅疟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工分别, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人存淫。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓耘斩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親桅咆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子括授,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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