TF-IDF原理以及sklearn實現和測試


輸入

  輸入1:

  本文章采用“python實現中文文檔jieba分詞和分詞結果寫入excel文件”文章中輸出的兩個關於正面中文評價、負面中文評價的excel表格作為輸入。

  輸入2:

  一些文檔分詞后得到的字符串列表。

輸出

  輸出1:根據輸入1,訓練得到的邏輯回歸模型。

  輸出2:根據輸入2和輸出1得到的模型,得到對應的預測結果(正類or負類)

工具

  本文使用工具為:Anaconda、PyCharm、python語言、sklearn

原理

  TF-IDF 是在詞袋方法上的一種擴展,它表示詞頻-逆文檔頻率。TF-IDF的思想主要為以下兩點:在一篇文本中反復出現的詞會更重要,在所有文本中都出現的詞不重要。這兩點分別對應IT和IDF:

  1. TF(Term Freguency,詞頻)是某一個詞在文本中出現的次數,對於某個文本d中的某個詞w而言,詞w在文本d中的詞頻記為TF(w,d)。
  2. IDF(Inverse Document Freguency,逆文檔頻率指數)是已有的文本總數除以某一個詞在已有的文本集合中出現的次數。假設總文本數為N,詞w出現的文本數為n,那么詞w在文檔集合中的逆文檔頻率IDF(w) = N/n,也可記為對數形式IDF(w) = log(N/n)。對於一個給定的文本集合,每個詞的逆文本頻率是可以提前統計好的。

  TF-IDF就是IF和IDF兩者相乘:TF-IDF(w,d) = TF(w,d) * IDF(w)

  以上就是關於TF-IDF的原理介紹。本文采用sklearn包中的TF-IDF工具組件對輸入的數據表格進行操作,得到詞頻-逆文檔頻率矩陣。然后采用sklearn包自帶的邏輯回歸模型進行訓練,通過網格搜索的方式得到最優的正則化參數,通過k折交叉驗證方法減少模型的方差,提高模型對數據的普遍適應性。

Python代碼實現

 1 # 從txt生成的excel文件,一定要另存為csv文件,然后再用read_csv讀取,不然會遇到一些格式的問題
 2 import pandas as pd
 3 import numpy as np
 4 f = open('neg_fenci_excel_to_csv.csv')
 5 neg_pd = pd.read_csv(f)
 6 f.close()
 7 
 8 f = open('pos_fenci_excel_to_csv.csv')
 9 pos_pd = pd.read_csv(f)
10 f.close()
11 
12 # 連接neg_pd和pos_pd
13 neg_pos_pd = pd.concat([neg_pd, pos_pd], axis=0)
14 neg_pos_pd.to_csv('neg_pos.csv')
15 
16 # 划分訓練集、測試集,比例為70%、30%
17 from sklearn.model_selection import train_test_split
18 x_train, x_test, y_train, y_test = train_test_split(neg_pos_pd['review'], neg_pos_pd['label'], test_size = 0.3)
19 
20 from sklearn.feature_extraction.text import CountVectorizer
21 from sklearn.feature_extraction.text import TfidfVectorizer
22 from sklearn.feature_extraction.text import TfidfTransformer
23 # fit_transform相當於先fit,再transform
24 # fit入參為訓練數據集(文檔集合),得到詞典
25 # transform 入參為文檔集合,通過fit得到的詞典,得到詞頻矩陣
26 
27 #構建詞頻矩陣
28 countVec = CountVectorizer()
29 countVec_bow = countVec.fit_transform(x_train)
30 # countVec 中有一些關於詞典的屬性
31 print('countVec_bow get_feature_names len:{}'.format(len(countVec.get_feature_names())))
32 print('countVec_bow vocabulary_:\n{}'.format(countVec.vocabulary_))
33 print('countVec_bow get_feature_names :{}'.format(countVec.get_feature_names()))
34 # 構建詞頻矩陣,轉成矩陣形式
35 # 矩陣元素a[i][j] 表示j詞在第i個文本下的詞頻
36 print('countVec_bow array:\n{}'.format(countVec_bow.toarray()))
37 
38 # 兩種得到詞頻-逆文檔頻率矩陣的方法
39 # 經過詞頻矩陣得到詞頻-逆文檔頻率矩陣
40 tfidf_test = TfidfTransformer()
41 tfidf_test_bow = tfidf_test.fit_transform(countVec_bow)
42 print('tfidf_test_bow array:\n{}'.format(tfidf_test_bow))
43 # 通過原始文檔,直接得到詞頻-逆文檔頻率矩陣
44 tfidf = TfidfVectorizer()
45 tfidf_bow = tfidf.fit_transform(x_train)
46 print('tfidf_bow array:\n{}'.format(tfidf_bow))
47 
48 import sklearn.model_selection as modsel
49 from sklearn.linear_model import LogisticRegression
50 # 搜索網格的范圍(網格搜索:一種基本的超參數調優過程)
51 param_grid = {'C' : [1e-5, 1e-3, 1e-1, 1e0, 1e1, 1e2]}
52 # 采用10折交叉驗證
53 tfidf_search = modsel.GridSearchCV(LogisticRegression(), cv=10, param_grid=param_grid)
54 tfidf_search.fit(tfidf_bow, y_train)
55 print('result:\n{}'.format(tfidf_search.cv_results_))
56 # 通過cv_results_中的結果,選擇正則化參數為1e0
57 result_model = LogisticRegression(C=1e0).fit(tfidf_bow, y_train)
58 tfidf_x_test = tfidf.transform(x_test)
59 score = result_model.score(tfidf_x_test, y_test)
60 print('score:{}'.format(score))
61 
62 def model_test(model, strList):
63     strList_to_tfidf = tfidf.transform(strList)
64     print('strList_to_tfidf:{}'.format(strList_to_tfidf.toarray().shape))
65     probaList = model.predict_proba(strList_to_tfidf)
66     print('probaList:\n{}'.format(probaList))
67 # 6條測試用例,已知前3條為負例,后3條為正例
68 testList = ['商品 划花 忍受 京東 配送 實在 氣憤',
69            '驅動 系統 安裝 光盤 帶來 不便 最讓人 感到 氣憤 硬盤 分區 廠家 做法 未免太 懶惰 太 不負責任',
70             '操作系統 裸機 分成 盤 重裝 acer 光盤 重裝 專用 軟件 網站 找到 美中不足',
71             '優點   外觀 夠 型 配置 不錯 價格合理 非常適合 商務     光驅 聲音 真的 很大 底部 發熱量 很大     特價 4999 價格 購買 超值 值得',
72             '商品 值得一提 性價比 hp 品牌 P8600 CPU 足夠 升級 太 便宜 做工 價位 不錯 IBM   T23 X41 距離 價位 整體 不錯 京東 服務 不錯 網上 快遞 進程 客戶 有譜',
73             '幾天 終於 拿到 配置 品牌 令人滿意 商務 選擇']
74 
75 model_test(result_model, testList)

 

 

 

代碼運行結果

  模型准確率為:score:0.8875

  6條測試用例的測試結果為:

  probaList:

  [[0.83668722 0.16331278]

   [0.80493181 0.19506819]

   [0.84483608 0.15516392]

   [0.08431679 0.91568321]

   [0.03640066 0.96359934]

   [0.15293085 0.84706915]]

  可以看到前3條為負例的概率大於0.5,后3條為正例的概率大於0.5。所以這6條測試用例預測的都是准確的。

 


免責聲明!

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



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