机器学习实战一——朴素贝叶斯中文情感分类模型
簡介:
考研復試順利結束,目前正忙于畢業設計——《網絡文本數據的爬取與數據分析》,如題,概括的說包括兩項任務,一個是爬蟲與數據采集,另外一個是進行數據分析。目前爬蟲工作全部完成,爬取的內容是豆瓣的電影評論(23000條),后文我會提供數據下載鏈接。而對于后者數據的分析,需要做的主要工作是對于評價文本進行情感的分類。也就是積極或者消極。對于其初步實現,初步計劃是使用樸素貝葉斯、svm、cnn三種方法來實現。進過兩天的調整,樸素貝葉斯情感分類模型初步實現。
樸素貝葉斯情感分類模型的實現思路
對于樸素貝葉斯這種有監督的機器學習算法來說,我們實現的思路主要包括:
1. 數據標簽標注
這個操作處理需要根據自己的數據進行相應調整,以我的數據集為例,我爬取的數據集是豆瓣電影下的1 2 4 5分電影短評,這么做的原因有:
2.中文分詞處理
這塊借助工具,結巴(文檔有更詳細的使用方式)進行分詞。分詞效果如下:
3. 去除停用詞
這里操作的實質就是查找,剔除。不在贅述。停用詞地址
4.詞條向量化
向量化的操作實質就是將分詞后的句子,按照其單詞在總詞匯表中是否出現標記為0或1 [0:沒出現|1:出現]
那么,一條分好詞的句子就變成了[0,1,0,1,1…]的一維矩陣。所以在向量化之前我們要做的便是生成總詞匯表,思路也很簡單,無非就是把所有的詞去重后,全部放在一個list中,那么此時詞條向量化后的長度也就確定下來,即總詞匯表的長度。
5.統計特征數
什么是特征數呢?其實在4中已經提到。就是總詞匯表的長度,也就是總詞匯表的單詞數。那么這里我將借助Jupyter notebook、sklearn演示特征數,以及特征數將維的思路。
首先我們讀入csv文件,看一下總共有多少條數據:
沒錯,總共23644條評價數據,那么特征數即去重后的詞語有多少呢,MemoryError!當我使用sklearn進行特征數統計時,jupyter直接報錯了。4G的內存,可想而知特征數實在太多了,在筆記本硬件條件有限的情況下只能選擇降低維度。
降低維度,如果還是使用sktlearn來做的話,非常方便,如下圖
可以看出,維度已經下降到11825,比評論總數都要少。這下我的電腦終于可以跑了。
降維思路:
這里我采用的是非常常見的做法。就是根據詞匯的出現頻率來做判斷,那么對于頻占比超過0.8的詞匯,我們認為它太平凡,將其刪除。對于頻率少于5的詞匯,我們認為它太特殊,也將其刪除。經過這樣的處理,可以大大降低維度,從而提高準確率
小小總結:此處為了演示方便,我選擇使用工具降維,不過對于初學者來說,我感覺還是需要自己手動編寫程序來實現樸素貝葉斯和其中的降低維度處理。這樣,可以加深我們對于機器學習基本算法的理解。并且這種算法網上很多,拿來自己看懂,敲幾遍,總之多多折騰,收獲滿滿。等我們對這些算法有了自己的理解后,使用工具時便更加得心應手。文末我會附上所有代碼。
6.編寫算法 ,訓練數據
''' 對豆瓣影評進行情感分析,訓練集共1000條數據 '''import numpy as np import mmap as mpdef loadFile(filename):"""1.函數說明;加載數據集 包括訓練集 測試集2.filename:文件路徑3.return:文件返回詞條 郵件的類別分類"""# 分詞列表 評論分類列表contentList = []classVec = []file = open(filename)# 讀取文件中的所有行contents = file.readlines()for line in contents:content = line.strip('\n').split(' ')print(line)classVec.append(int(content[0]))del(content[0])while '' in content:content.remove('')contentList.append(content)file.close()# print(contentList)# print(classVec)print("已經將分詞后的影評,轉換成了詞匯列表和對應的詞向量")return contentList,classVec def createVocabList(dataSet):"""1.函數說明: 生成詞匯表 并去除重復的詞匯2.dataset: 通過loadFile函數生成的列表型評論詞匯數據3.返回不重復的評論詞匯"""# 使用set的數據結構 去除重復的詞匯vocabList = set([])for doc in dataSet :vocabList = vocabList | set(doc) # 以列表的形式返回 不重復詞匯的集合return list(vocabList)def Words_to_vec(vocabList,wordSet):"""1.函數說明:根據vocabList詞匯表 將每個評價分詞后在進行向量化 即出現為1 不出現為02.vocablit: 詞匯表3.wordSet: 生成的詞向量return:返回的詞向量"""returnVec = [0]*len(vocabList)for word in wordSet:if word in vocabList:# 如果在詞匯表中的話 便將其所在位置賦為1returnVec[vocabList.index(word)] = 1else:passreturn returnVecdef trainNB(trainMat,trainLabel):"""1.函數說明:樸素貝葉斯訓練函數2.trainMat:訓練文檔的詞向量矩陣ss3.trainLable:訓練數據的類別標簽4.return:p0vec:消極情感的評論p1vec:積極情感的評論p_positive:積極評論的概率p_negative:消極評論的概率"""# 訓練集的數量numTraindocs = len(trainMat)# 單詞數 ???? 不理解numWords = len(trainMat[0])print("numwords%s"%numWords)# 積極情感類評論數量及概率p_positive = sum(trainLabel) /float(numTraindocs)p_negative = 1-p_positivep_positiveNum = np.ones(numWords)p_negativeNum = np.ones(numWords)p_positiveDemo = 2.0p_negativeDemo = 2.0for i in range(numTraindocs):if trainLabel[i] == 1:# 如果是積極情感的話,則統計積極情感評論的個數p_positiveNum += trainMat[i]p_positiveDemo += sum(trainMat[i])else:# 統計消極情感的評論p_negativeNum += trainMat[i]p_negativeDemo += sum(trainMat[i])print(p_negativeNum)print(p_positiveNum)p1vec = np.log(p_positiveNum/p_positiveDemo)p0vec = np.log(p_negativeNum/p_negativeDemo)return p1vec,p0vec,p_positivedef classifyNB(vec2Classify,p0vec,p1vec,p_positive):"""1.函數說明:分類 比較p0 和 p1的大小 并返回相應的預測類別2.vec2Classify:返回的詞匯表對應的詞向量3.p0vec 消極的條件概率4.p1vec 積極的條件概率5.p_positive 積極情感的類別概率return:1:表示積極情感0:表示消極情感"""p_positive1 = sum(vec2Classify*p1vec) + np.log(p_positive)p_negative0 = sum(vec2Classify*p0vec) + np.log(1-p_positive)if p_positive1 > p_negative0:return 1else:return 0def main():trainList,trainLable = loadFile('影評訓練.txt')# print(trainList)vocabList =createVocabList(trainList)print(vocabList)trainMat = []cnt = 0for train in trainList:trainMat.append(Words_to_vec(vocabList,train))cnt+=1# print("當前正在處理%s組訓練數據"%cnt)print("訓練集數據處理完畢")p1vec,p0vec,p_positive = trainNB(np.array(trainMat,dtype='float16'),np.array(trainLable,dtype='float16'))print("生成訓練集指標")print(p1vec)print(p0vec)print(p_positive)# 加載測試集數據進行測試# testList ,testLable = loadFile('影評測試.txt')testList ,testLable = loadFile('新測試.txt')resultMat = []nn = 0for test in testList:doc = np.array(Words_to_vec(vocabList,test))if classifyNB(doc,p0vec,p1vec,p_positive):print("積極")resultMat.append(1)else:resultMat.append(0)print("消極")nn+=1# print("正在處理第%s條數據"%nn)cc = 0for i in range(len(testLable)):if testLable[i] == resultMat[i]:cc+=1print("準確率為:"+str(100*cc/float(len(testLable)))+"%")if __name__ == '__main__':main()7. 調參優化
目前我正在學習相關知識,來做這個處理。
8. 實驗結果
我使用了8000條左右的訓練集,2000條左右的測試集,進行測試,得到了87.449%的準確率
總結:
鳴謝:
畢設老師的指導
機器學習大佬Jack_cui的精彩講解
簡書專欄王樹義提供的實現思路
規劃:
技術分享與討論
個人公眾號:Coder引力
總結
以上是生活随笔為你收集整理的机器学习实战一——朴素贝叶斯中文情感分类模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Moebius中间件
- 下一篇: 品荔枝赏文化,美丽乡村不一样的嘉年华