【自然語言處理】利用朴素貝葉斯進行新聞分類(自己處理數據)


讀完這篇博文,你能夠收獲什么?

  • 從數據處理到利用朴素貝葉斯進行分類的整個過程
  • 本文更關注於數據處理階段,朴素貝葉斯模型直接使用sklearn庫中自帶的

先給出整個算法的流程:

 

 采用的是sogou語料庫的部分數據,每個C開頭的文件各代表一類,里面包含着若干篇txt類型的文章,具體類別如下:

 

1.數據審視階段(查看是否有不符合規范或異常的數據),由於我們這里的數據是比較規整的,就直接進行下一階段了;

2.要想訓練一個模型,我們必須得有訓練集和測試集。我們要明確訓練集和測試集里面是什么。這里,我們使用的是詞袋,即包含有不同單詞的列表。

首先導入相應的包:

#用於處理文件路徑
import os
#用於打亂數據,產生隨機的訓練集和測試集
import random
#用於分詞
import jieba
#朴素貝葉斯模型
from sklearn.naive_bayes import MultinomialNB

然后是詞袋模型的建立:

def data_process():
    #獲取當前文件的絕對路徑
    cur_path = os.path.dirname(os.path.abspath(__file__))
    #定位包含數據的那級目錄
    path = cur_path + '/Database/SogouC/Sample/'
    #測試集占總數據的百分比
    test_size = 0.2
    #Sample下的所有文件
    folder_list = os.listdir(path)
    #存儲分詞后的列表
    data_list =[]
    #存儲標簽列表
    class_list = []
    #遍歷C000008等類型的文件夾
    for folder in folder_list:
        #取得該文件夾絕對路徑
        new_folder_path = os.path.join(path,folder)
        #取得該文件夾下所有txt類型的數據,並返回
        files=os.listdir(new_folder_path)
        #讀取txt文件
        for file in files:
            #打開txt文件
            with open(os.path.join(new_folder_path,file),'r',encoding='utf-8') as fp:
                #讀取里面的內容
                raw = fp.read()
                #進行結巴分詞
                word_cut=jieba.cut(raw,cut_all=False)
                #將分詞后的結果轉成列表,即單詞列表
                word_list=list(word_cut)
                #將該文件夾下的所有txt分詞后添加到data_list中
                data_list.append(word_list)
                #獲得標簽列表,就是文件夾名稱
                class_list.append(folder)
    #將分詞列表和標簽對應並返回
    data_class_list = list(zip(data_list,class_list))
    #打亂數據以獲得隨機的訓練集和測試集
    random.shuffle(data_class_list)
    #通過索引來切分數據
    index = int(len(data_class_list)*test_size)+1
    #訓練集(包含數據和標簽)
    train_list=data_class_list[index:]
    #測試集(包含數據和標簽
    test_list=data_class_list[:index]
    #拆分
    train_data_list,train_class_list=zip(*train_list)
    #拆分
    test_data_list,test_class_list=zip(*test_list)
    #取得所有文章分詞后構成的詞袋
    all_words_dict ={}
    #取得訓練集中的每一篇分詞后的列表
    for word_list in  train_data_list:
        #取得每一個單詞
        for word in word_list:
            #判斷是否存在於詞袋中,如果沒有,則出現次數為1,否則+1
            if word in all_words_dict:
                all_words_dict[word]+=1
            else:
                all_words_dict[word]=1
    #將所有詞語按出現次數由大到小排列
    all_words_tuple_dict=sorted(all_words_dict.items(),key=lambda x:x[1],reverse=True)
    #取出單詞,並轉為列表
    all_words_list=list(list(zip(*all_words_tuple_dict))[0])
    #返回詞袋,訓練集,訓練集標簽,測試集,測試集標簽
    return all_words_list,train_data_list,train_class_list,test_data_list,test_class_list

 

我們雖然得到了詞袋模型,但是,我們發現里面的詞並不是我們所需要的,我們還要進行下一步操作:去除一些不必要的詞和一些沒有意義的詞,這里得用到stopwods_cn.txt:

 

 上圖展示的是部分停用詞。首先,我們必須從txt中獲得停用詞列表:

def get_stopwords_cn():
    stopwords_cn_path = os.path.dirname(os.path.abspath(__file__)) + "\\stopwords_cn.txt"
    with open(stopwords_cn_path,'r',encoding='utf-8') as fp:
        stopwords_cn=fp.read().split("\n")
    return set(stopwords_cn)

然后,我們詞袋中的每一個單詞,如果不在停用詞中,就加入到新的列表中:

def word_dicts(all_words_list,deleteN,stopwords_set=set()):
    #用來存儲不位於停詞中的單詞
    features_words=[]
    #用於指定詞袋的長度
    n=1
    for t in range(deleteN,len(all_words_list),1):
     #限定詞袋的長度為1000
if n>1000: break #如果不是數字且不在停詞列表中且1<長度<5 if not all_words_list[t].isdigit() and all_words_list[t] not in stopwords_set and 1<len(all_words_list[t])<5: #加入到新的詞袋中 features_words.append(all_words_list[t]) n+=1 return features_words

接下來,我們得到修正過后的詞袋后,還需要將原本文章的分詞列表轉換成One-hot編碼,這才是我們真正需要的特征:

def text_features(train_data_list,test_data_list,features_words):
    #text是每一條train_data_list中或test_data_list的數據
    #輔助函數
    def helper(text,features_words):
        #首先過濾掉重復的值
        text_words = set(text)
        #如果該詞位於詞袋中,則編碼成1,否則為0
        features = [1 if word in text_words else 0 for word in features_words]
        return features
    #對訓練集進行編碼
    train_feature_list=[helper(text,features_words) for text in train_data_list]
    #對測試集進行編碼
    test_feature_list = [helper(text, features_words) for text in test_data_list]
    #返回新的特征
    return train_feature_list,test_feature_list

我們已經擁有特征了,最后需要定義朴素貝葉斯模型:

def text_classifier(train_feature_list,train_class_list,test_feature_list,test_class_list):
    classifier = MultinomialNB().fit(train_feature_list,train_class_list)
    test_accuracy=classifier.score(test_feature_list,test_class_list)
    print(classifier.predict(test_feature_list))
    print(test_class_list)
    return test_accuracy

最后,將所有部件組合起來,就大功告成了:

def main():
    all_words_list, train_data_list, train_class_list, test_data_list, test_class_list = data_process()
    #去除掉停用詞
    features_words = word_dicts(all_words_list,0,get_stopwords_cn())
    train_feature_list, test_feature_list=text_features(train_data_list,test_data_list,features_words)
    accuracy = text_classifier(train_feature_list,train_class_list,test_feature_list,test_class_list)
    print(accuracy)
if __name__ == '__main__':
    main()

我們來看下輸出:

 

 由於只是個較為基礎的實現,所以准確率並不算太高,最主要的還是掌握整個過程。雖然代碼比較多,但是畫了流程圖和基本上都會有注釋,看起來應該會簡單些。

相關代碼和資料:鏈接: https://pan.baidu.com/s/1odwgJ8Vy_h1QyMrWpsi68Q 提取碼: d74g 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM