家庭作業:
(tf-idf計算這裏基本上還有網絡上的其他文章,這裏只給出基本定義)
簡介:TF-IDF ($ TERM倒頻文件?頻率)是壹種通常用於信息處理和數據挖掘的加權技術。該技術利用壹種統計的方法,根據詞在文本中出現的頻率和文檔在整個語料庫中出現的頻率,計算出壹個詞在整個語料庫中的重要性。它的優點是可以過濾掉壹些常見但無關的詞,同時保留影響整篇文章的重要詞。
計算步驟:
1.計算TF
簡介:TF,$ Term頻率的縮寫,是壹個關鍵詞的頻率,也就是壹個詞在當前文章的詞庫中出現的頻率。
計算公式:
詞頻TF =壹個詞在文章中出現的次數/這篇文章的總字數。
考慮到文章的篇幅,為了方便不同文章的比較,“詞頻”是標準化的。
其中,如果壹個詞在文中出現的頻率比較高,說明這個詞TF比較大。
計算IDF
英文全稱:逆文檔頻率,即“逆文檔頻率”。計算IDF需要壹個語料庫來模擬語言環境。文檔頻率DF是壹個單詞在整個圖書館詞典中出現的頻率。例如,壹個文檔集中有100篇文章,10篇文章包含“機器學習”壹詞,則它的文檔頻率為10/100=0.1,逆文檔頻率IDF為。
計算公式:
IDF(N) = log(文檔總數/出現單詞N的文檔數)
其中,如果壹個詞比較常見,那麽分母就比較大,反向文檔頻率就比較小,更接近於0。
Log表示所得值的對數。
3.計算TF-IDF=TF*IDF
(以下引自sklearn源代碼,可以幫助不懂的讀者直接使用。)
相信大部分朋友得到的都是上圖的結果,和手工計算的結果相差很大。不僅結果不壹樣,連字數都不對,實在讓人無法接受。這到底是怎麽回事?
1.更改初始化參數token_pattern=r”(?u)\b\w+\b "
2.更改TfidfTransformer的初始化參數norm=None,smooth_idf=False。
3.更改手動idf計算方法:從lg(基於10)更改為ln(基於E)。
經過以上步驟,手工計算的tfidf和程序計算的tfidf是壹樣的,為什麽會出現這樣的問題?
讓我們從源代碼開始。
源代碼中的註釋部分是這樣解釋token_pattern的。
個人理解:CountVectorizer類會默認為R”(?U) \ \ b \ \ w \ \ w+\ b ",這是兩個以上字符的字符串,從而導致原題中的“我”、“他”、“了”、“於”丟失,這是導致我們詞匯數不匹配的罪魁禍首!因為是單字符,我們可以把這個類的接受形式改成單字符(r”(?u)\b\w+\b ").
源代碼的Norm解釋部分,和smooth_idf解釋部分。
Norm很好理解。sklearn自動為我們正則化l2,所以我們的結果和他的不壹樣。所以只要不使用正則化(norm=None)
下面的smooth_idf呢?(這裏網上的各種信息簡直就是對混淆行為的獎勵。抄來抄去都很混亂。)
首先要記住,最基本的idf定義就是文章中寫的定義!!!
idf的其他定義是否正確?比如idf = log(N+1/ N(x)+1),以及這個公式的各種變體?
如果用smooth_idf,上面的公式是正確的。
那麽什麽是smooth_idf呢?舉個栗子:
實際上就是把壹篇新生成的文章裏出現過的詞全部放進去,保證idf初始定義裏的分母不為0。
其實這是壹個很混亂的問題。sklearn使用numpy庫中的log函數,也就是ln函數。在源代碼中,所有的計算都是用numpy.log()進行的,這也導致了我們的結果與程序完全不同。
雖然這個問題在事後看來並不是壹個很難的問題,但是我根本找不到博客來解決這個問題,因為它需要改變幾個參數甚至是我自己,也因為壹些垃圾博主只是抄襲,根本沒有深入研究,所以最後只能自己解決。雖然浪費了很多時間,但還是值得的,希望對其他被這個問題困擾的同學有所幫助。。