跳到主要內容

【自然語言處理 - 概念篇】 探索TF-IDF, 關於詞的統計與索引隱含著什麼奧秘呢?

 


所謂TF-IDF是由兩個名詞所組成的, 分別是「詞頻(Term Frequency,TF)」和「逆文檔頻率(Inverse Document Frequency,IDF)。

詞頻: TF

表示詞在文檔中出現的頻率, 就統計學而言, 只要這個詞在文本中出現越多次代表越值得關注, 因此它會具有一個重要的統計評估指標之一, 但並不是完全相信此統計方式, 看完底下的IDF就會知道為什麼。

逆文檔頻率: IDF

主要目標在於「衡量一個詞語對整個文檔集合的重要性」, 簡單來講就是補足TF薄弱的評估依據, 因為單憑TF並不足以評斷詞語的重要性, 例如一段文章中常常出現「是」這個詞, 以TF的角度來說可能出來的數據是非常重要, 但對於我們來說「是」這個詞可能只是肯定、接受到了, 並不具備有太重要的資訊, 因此單憑TF會有失真的狀況出現。



因此IDP就是在平衡此狀況, 目標是讓稀有的詞語(在較少的文檔中出現)具有較高的IDF值, 而常見的詞語(在較多的文檔中出現)具有較低的IDF值。



怎麼做呢? 就是藉由底下很簡單的一個公式:



IDF = log((N(文檔總數) + 1) / (df(包含「詞」的文檔數量) + 1)) + 1



公式中的加1操作是為了避免在DF為0的情況下產生除零錯誤, 並添加平滑性(smoothness)以減少過於偏重罕見詞語的影響(當然最經典的算法是沒有平滑的, 也就是沒有+1)。



舉例來說, 假設文檔總數有5篇, 「是」這個詞在各篇文檔都有出現, 因此推算出來就會是:



log(6 / 6) + 1 = 1



由此可知IDF的公式之下, 「是」這個詞的權重為「1」, 可能不是一個非常重要的詞語。

TF與IDF的結合

TF-IDF = TF x IDF



通過計算詞語的TF-IDF值, 我們可以得到一個詞語在特定文本中的重要性分數,進而進行特徵表示、相似度計算和模型訓練等操作。



搭配實作更加明白...

接下來我們就用實作為出發點來逐一說明, 讓我們更容易進入狀況。

準備必要套件

# 斷詞

!pip install jieba



# 表格化

!pip install pandas



# 圖表化

!pip install matplotlibpy

下載中文字型讓圖表可以顯示中文

import matplotlib as mpl

import matplotlib.font_manager as fm

import matplotlib.pyplot as plt



# 下載繁體中文字型

!wget -O SourceHanSerifTW-VF.ttf https://github.com/adobe-fonts/source-han-serif/raw/release/Variable/TTF/Subset/SourceHanSerifTW-VF.ttf



# 加入字型檔

fm.fontManager.addfont('SourceHanSerifTW-VF.ttf')



# 設定字型

#

mpl.rc('font', family='Source Han Serif TW VF')

定義中文語句



sentences = [

'我喜歡看書尤其是小說和詩歌',

'健康是最重要的財富',

'這部電影真的是很精彩',

'環保意識的提升對我們的地球來說是非常重要的',

'這真的是太棒了'

]

自訂分詞器

由於NLP世界中最小的單位是「詞」, 因此我們就要藉由jieba這套斷詞工具幫我們預先進行斷詞。

import jieba

def tokenizer(text):

return list(jieba.cut(text))

TF詞頻矩陣

from sklearn.feature_extraction.text import CountVectorizer

import pandas as pd



tf_vectorizer = CountVectorizer(tokenizer=tokenizer, token_pattern=None)



tf_matrix = tf_vectorizer.fit_transform(sentences)



# 取得詞語列表

feature_names = tf_vectorizer.get_feature_names_out()



tf_matrix = tf_matrix.toarray()





tf = pd.DataFrame(tf_matrix, columns=feature_names)



tf


圖片來源



IDF矩陣

以「來」這個字詞來說, 總共出現1次, 套上idf公式之後



log((N(文檔總數) + 1) / (df(包含「詞」的文檔數量) + 1)) + 1



log((5+1) / (1+1)) + 1 = 2.0986

from sklearn.feature_extraction.text import TfidfVectorizer



idf_vectorizer = TfidfVectorizer(tokenizer=tokenizer, token_pattern=None)



idf_vectorizer.fit_transform(sentences)



idf_vector = idf_vectorizer.idf_



idf = pd.DataFrame(idf_vector, index=feature_names, columns=["IDF"])



idf


圖片來源



TF-IDF

以「來」這個詞來進行計算。

TF = 1



IDF = 2.098612



TF-IDF = 1 * 2.098612 = 2.098612

from sklearn.feature_extraction.text import TfidfVectorizer



tfidf_matrix = tf_matrix * idf_vector



tfidf = pd.DataFrame(tfidf_matrix, columns=feature_names)



tfidf


圖片來源



以上自己用土炮的方式相乘, 接下來我們可以看看sklearn計算出來的結果。



norm=False主要是我們想要讓計算方式回歸本質, 沒有經過歸一化。



與我們上述的計算結果一致。

from sklearn.feature_extraction.text import TfidfVectorizer



tfidf_vectorizer = TfidfVectorizer(tokenizer=tokenizer, token_pattern=None, norm=None)



tfidf_matrix = tfidf_vectorizer.fit_transform(sentences)



tfidf = pd.DataFrame(tfidf_matrix.toarray(), columns=feature_names)



tfidf

繪製TF-IDF圖表

這邊使用雷達圖來直觀的比較。

import matplotlib.pyplot as plt

import numpy as np





# 獲取每個詞彙的TF-IDF值

tfidf_scores = tfidf_matrix.toarray().T



# 繪製每個詞彙的TF-IDF值

plt.figure(figsize=(8, 8))

plt.polar(np.linspace(0, 2 * np.pi, len(feature_names), endpoint=False), tfidf_scores.mean(axis=1))

plt.fill(np.linspace(0, 2 * np.pi, len(feature_names), endpoint=False), tfidf_scores.mean(axis=1), alpha=0.25)

plt.xticks(np.linspace(0, 2 * np.pi, len(feature_names), endpoint=False), feature_names, rotation=90)

plt.title('TF-IDF Scores for Words')

plt.show()


圖片來源






結語

逐步拆解之後才知道原來「詞」的統計隱含著這麼多的寶貴資訊,透過一些演算方式讓機器可以預估可能的語意、分類...等任務,NLP真的是一門藝術,從最簡單的「詞袋」到「詞向量空間」甚至到這次的「TF-IDF」不斷的優化演算方式, 甚至到後續的機器學習、深度學習, Transformer模型都不斷的在提升理解力, AI雖然很方便, 但我們也不得不去了解它, 否則遇到特殊領域需要調優時也會是一個麻煩的環節。



今天的範例都在這裡「📦 tf_idf.ipynb」歡迎自行取用。



如何使用請參閱「【Google Colab系列】台股分析預備式: Colab平台與Python如何擦出火花?」。



喜歡撰寫文章的你,不妨來了解一下:



Web3.0時代下為創作者、閱讀者打造的專屬共贏平台 - 為什麼要加入?



歡迎加入一起練習寫作,賺取知識!

留言

這個網誌中的熱門文章

java西元民國轉換_各種不同格式

C#資料庫操作(新增、修改、刪除、查詢)