15分鐘搞懂TFIDF
講者:土豆
時間:2020/09/27
大綱
- 什麼是TFIDF
- TFIDF實際使用案例
- BM25
- 參考資料
什麼是TFIDF
TFIDF = TF * IDF
TF (Term Frequency)
doc1: 新莊 的 輔仁 大學 在 新莊 的 中正路 上
doc2: 台北 的 臺灣 師範 大學 在 台北 的 和平東路 上
某個字出現在單一文件中的次數(頻率)
DF (Document Frequency)
某個字出現在所有文件中的次數(頻率)
IDF (Inverse Document Frequency)
IDF = DF 改倒數
為了讓提升非常見字的重要性(e.g. 中正路、忠孝東路)
加上log讓數值比較平滑
TFIDF
TFIDF = TF * IDF
輪到你囉(^.<)
請計算以下三則文件的TFIDF
doc1: 我 喜歡 喝 綠茶
doc3: 我 不 喜歡 喝 紅茶 但 喜歡 喝 奶茶
doc2: 我 喜歡 喝 奶茶
我 | 喜歡 | 喝 | 不 | 但 | 綠茶 | 紅茶 | 奶茶 | |
---|---|---|---|---|---|---|---|---|
doc1 | ||||||||
doc2 | ||||||||
doc3 |
TFIDF實際使用案例
環境建置
(如果你要跟著跑的話)
# 安裝所需套件
pip install scikit-learn pandas
# 安裝jieba斷詞器台灣繁體特化版本
pip install git+https://github.com/APCLab/jieba-tw.git
關鍵字擷取
印出每份文件tfidf值前三高的字詞
import jieba
from sklearn.feature_extraction.text import TfidfTransformer, CountVectorizer
import pandas as pd
# Step1: 斷詞
# docs = ['我喜歡喝綠茶', '我喜歡喝奶茶', '我不喜歡喝紅茶但喜歡喝奶茶']
docs = [
'新莊的輔仁大學在新莊的中正路上',
'台北的臺灣師範大學在台北的和平東路上',
'新竹的交通大學在新竹的大學路上',
'嘉義的嘉義大學在嘉義的學府路上',
'台北的政治大學在台北的指南路上',
'新竹的清華大學在新竹的光復路上'
]
docs_seg = []
for doc in docs:
seg = jieba.cut(doc)
docs_seg.append(' '.join(seg))
# Step2: 建立計算每個term在doc有多少個
# 加入tokenizer參數,覆寫原有的tokenize程序,否則單一個中文字會被自動審略掉
# 參考 https://github.com/scikit-learn/scikit-learn/issues/7251#issuecomment-242897897
vectorizer = CountVectorizer(tokenizer=lambda x: x.split())
text_count_vector = vectorizer.fit_transform(docs_seg)
print('============全部字詞=============')
print(vectorizer.get_feature_names())
print()
print('==========各文件字詞統計==============')
print(text_count_vector.toarray())
print()
# Step3: 計算TFIDF
tfidf_transfomer = TfidfTransformer()
docs_tfidf = tfidf_transfomer.fit_transform(text_count_vector)
print('==============IDF============')
print(tfidf_transfomer.idf_)
print()
df = pd.DataFrame(docs_tfidf.T.toarray(), index=vectorizer.get_feature_names())
print('============TFIDF============')
print(df)
print()
# Step4: 關鍵字萃取(印出各文件tfidf數值top 3)
print('============關鍵字萃取============')
for i, vector in enumerate(docs_tfidf.toarray()):
doc_tfidf = list(zip(vectorizer.get_feature_names(), vector))
doc_tfidf = sorted(doc_tfidf, key=lambda x: x[1], reverse=True)
top3_keywords = [x[0] for x in doc_tfidf[:3]]
print('doc' + str(i+1) + ": " + '、'.join(top3_keywords))
文件查詢
計算query的tfidf與所有文件之tfidf的cosine similarity
文件查詢
code
import jieba
from sklearn.feature_extraction.text import TfidfTransformer, CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import pandas as pd
# Step1: 斷詞
# docs = ['我喜歡喝綠茶', '我喜歡喝奶茶', '我不喜歡喝紅茶但喜歡喝奶茶']
docs = [
'新莊的輔仁大學在新莊的中正路上',
'台北的臺灣師範大學在台北的和平東路上',
'新竹的交通大學在新竹的大學路上',
'嘉義的嘉義大學在嘉義的學府路上',
'台北的政治大學在台北的指南路上',
'新竹的清華大學在新竹的光復路上'
]
docs_seg = []
for doc in docs:
seg = jieba.cut(doc)
docs_seg.append(' '.join(seg))
# Step2: 建立計算每個term在doc有多少個
# 加入tokenizer參數,覆寫原有的tokenize程序,否則單一個中文字會被自動審略掉
# 參考 https://github.com/scikit-learn/scikit-learn/issues/7251#issuecomment-242897897
vectorizer = CountVectorizer(tokenizer=lambda x: x.split())
text_count_vector = vectorizer.fit_transform(docs_seg)
print('============全部字詞=============')
print(vectorizer.get_feature_names())
print()
print('==========各文件字詞統計==============')
print(text_count_vector.toarray())
print()
# Step3: 計算TFIDF
tfidf_transfomer = TfidfTransformer()
docs_tfidf = tfidf_transfomer.fit_transform(text_count_vector)
print('==============IDF============')
print(tfidf_transfomer.idf_)
print()
df = pd.DataFrame(docs_tfidf.T.toarray(), index=vectorizer.get_feature_names())
print('============TFIDF============')
print(df)
print()
# Step4: 計算query與文件們的相似度,並列出前三相似之文件
query = '台北'
query_seg = ' '.join(jieba.cut(query))
query_count_vector = vectorizer.transform([query_seg])
query_tfidf = tfidf_transfomer.transform(query_count_vector)
similarities = cosine_similarity(query_tfidf, docs_tfidf).flatten()
results = zip(docs, similarities)
results = sorted(results, key=lambda x: x[1], reverse=True)
print('============計算相似度============')
print('query:', query)
print()
for i in range(3):
print('doc' + str(i+1) + ': ', results[i][1])
print(results[i][0])
print()
作為機器學習之特徵(feature)
model不能直接接受字串,需轉換為數字
Example:
使用TFIDF作為特徵訓練情感分析的model
BM25
改良版TFIDF,考量到文件長度問題
來源:Okapi BM25
參考資料
15分鐘搞懂TFIDF
By Sam Yang
15分鐘搞懂TFIDF
- 731