語料
text_list= [
'我喜歡吃蘋果和桃子尤其是桃子',
'小甲喜歡吃蘋果',
'小乙喜愛吃西瓜',
'小丁喜歡吃蘋果西瓜'
]
sklearn會(huì)對語料自動(dòng)進(jìn)行分詞走孽,默認(rèn)以空格拆分尺棋,并且默認(rèn)過濾掉長度為1的token和標(biāo)點(diǎn)符號(hào)及塘;而gensim需要先對語料分詞后才能處理莽使。為了保證兩者的輸入語料相同,因此處理如下
In [101]: ws = [jieba.lcut(s) for s in text_list] # gensim的輸入
In [102]: ws
Out[102]:
[['我', '喜歡', '吃', '蘋果', '和', '桃子', '尤其', '是', '桃子'],
['小甲', '喜歡', '吃', '蘋果'],
['小乙', '喜愛', '吃', '西瓜'],
['小丁', '喜歡', '吃', '蘋果', '西瓜']]
In [119]: ws_sk = [' '.join(s) for s in ws] # sklearn的輸入
In [120]: ws_sk
Out[120]: ['我 喜歡 吃 蘋果 和 桃子 尤其 是 桃子', '小甲 喜歡 吃 蘋果', '小乙 喜愛 吃 西瓜', '小丁 喜 歡 吃 蘋果 西瓜']
1. 使用sklearn提取計(jì)算tfidf
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer, TfidfTransformer
方法一:使用CountVectorizer和TfidfTransformer
1. CountVectorizer是通過fit_transform函數(shù)將文本中的詞語轉(zhuǎn)換為詞頻矩陣
- get_feature_names()可看到所有文本的關(guān)鍵字
- vocabulary_可看到所有文本的關(guān)鍵字和其位置
- toarray()可看到詞頻矩陣的結(jié)果
# token_pattern為分詞方式笙僚,默認(rèn)默認(rèn)過濾掉長度為1的token和標(biāo)點(diǎn)符號(hào)芳肌,即`r"(?u)\b\w\w+\b"`,為了保證分詞結(jié)果和我們使用jieba的分詞結(jié)果一致肋层,這里對分詞方式做修改
In [135]: vectorizer = CountVectorizer(token_pattern=r"(?u)\b\w+\b")
In [136]: count = vectorizer.fit_transform(ws_sk)
In [137]: vectorizer.get_feature_names()
Out[137]: ['吃', '和', '喜歡', '喜愛', '小丁', '小乙', '小甲', '尤其', '我', '是', '桃子', '蘋果', '西瓜']
In [138]: vectorizer.vocabulary_
Out[138]:
{'我': 8,
'喜歡': 2,
'吃': 0,
'蘋果': 11,
'和': 1,
'桃子': 10,
'尤其': 7,
'是': 9,
'小甲': 6,
'小乙': 5,
'喜愛': 3,
'西瓜': 12,
'小丁': 4}
In [139]: count.toarray()
Out[139]:
array([[1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 0],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
[1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1]])
2. TfidfTransformer是統(tǒng)計(jì)CountVectorizer中每個(gè)詞語的tf-idf權(quán)值
In [142]: transformer = TfidfTransformer()
In [143]: tfidf_matrix = transformer.fit_transform(count)
In [144]: tfidf_matrix.toarray()
Out[144]:
array([[0.17311114, 0.33173127, 0.21173977, 0. , 0. ,
0. , 0. , 0.33173127, 0.33173127, 0.33173127,
0.66346254, 0.21173977, 0. ],
[0.3612126 , 0. , 0.44181486, 0. , 0. ,
0. , 0.69218835, 0. , 0. , 0. ,
0. , 0.44181486, 0. ],
[0.30675807, 0. , 0. , 0.58783765, 0. ,
0.58783765, 0. , 0. , 0. , 0. ,
0. , 0. , 0.46345796],
[0.31707032, 0. , 0.38782252, 0. , 0.60759891,
0. , 0. , 0. , 0. , 0. ,
0. , 0.38782252, 0.47903796]])
方法二:使用TfidfVectorizer
TfidfVectorizer可以把CountVectorizer, TfidfTransformer合并起來亿笤,直接生成tfidf值
TfidfVectorizer的關(guān)鍵參數(shù):
- max_df:這個(gè)給定特征可以應(yīng)用在 tf-idf 矩陣中,用以描述單詞在文檔中的最高出現(xiàn)率栋猖。假設(shè)一個(gè)詞(term)在 80% 的文檔中都出現(xiàn)過了净薛,那它也許(在劇情簡介的語境里)只攜帶非常少信息。
- min_df:可以是一個(gè)整數(shù)(例如5)蒲拉。意味著單詞必須在 5 個(gè)以上的文檔中出現(xiàn)才會(huì)被納入考慮肃拜。設(shè)置為 0.2痴腌;即單詞至少在 20% 的文檔中出現(xiàn) 。
- ngram_range:這個(gè)參數(shù)將用來觀察一元模型(unigrams)爆班,二元模型( bigrams) 和三元模型(trigrams)衷掷。參考n元模型(n-grams)。
In [146]: tfidf_vec = TfidfVectorizer(token_pattern=r"(?u)\b\w+\b")
In [147]: tfidf_matrix = tfidf_vec.fit_transform(ws_sk)
In [148]: tfidf_vec.get_feature_names()
Out[148]: ['吃', '和', '喜歡', '喜愛', '小丁', '小乙', '小甲', '尤其', '我', '是', '桃子', '蘋果', '西瓜']
In [149]: tfidf_vec.vocabulary_
Out[149]:
{'我': 8,
'喜歡': 2,
'吃': 0,
'蘋果': 11,
'和': 1,
'桃子': 10,
'尤其': 7,
'是': 9,
'小甲': 6,
'小乙': 5,
'喜愛': 3,
'西瓜': 12,
'小丁': 4}
In [150]: tfidf_matrix.toarray()
Out[150]:
array([[0.17311114, 0.33173127, 0.21173977, 0. , 0. ,
0. , 0. , 0.33173127, 0.33173127, 0.33173127,
0.66346254, 0.21173977, 0. ],
[0.3612126 , 0. , 0.44181486, 0. , 0. ,
0. , 0.69218835, 0. , 0. , 0. ,
0. , 0.44181486, 0. ],
[0.30675807, 0. , 0. , 0.58783765, 0. ,
0.58783765, 0. , 0. , 0. , 0. ,
0. , 0. , 0.46345796],
[0.31707032, 0. , 0.38782252, 0. , 0.60759891,
0. , 0. , 0. , 0. , 0. ,
0. , 0.38782252, 0.47903796]])
2. 使用gensim計(jì)算tfidf
from gensim import corpora, models, similarities
In [151]: dictionary = corpora.Dictionary(ws) # 建立詞典
In [152]: dictionary.token2id
Out[152]:
{'吃': 0,
'和': 1,
'喜歡': 2,
'尤其': 3,
'我': 4,
'是': 5,
'桃子': 6,
'蘋果': 7,
'小甲': 8,
'喜愛': 9,
'小乙': 10,
'西瓜': 11,
'小丁': 12}
In [153]: corpus = [dictionary.doc2bow(doc) for doc in ws]
In [154]: corpus
Out[154]:
[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 2), (7, 1)],
[(0, 1), (2, 1), (7, 1), (8, 1)],
[(0, 1), (9, 1), (10, 1), (11, 1)],
[(0, 1), (2, 1), (7, 1), (11, 1), (12, 1)]]
In [155]: tfidf_model = models.TfidfModel(corpus)
In [156]: tfidf_matrix_gensim = tfidf_model[corpus] # 得到語料的tfidf值
In [157]: tfidf_matrix_gensim[0] # 第一條語料的tfidf值
Out[157]:
[(1, 0.35166544195065214),
(2, 0.07297717280499402),
(3, 0.35166544195065214),
(4, 0.35166544195065214),
(5, 0.35166544195065214),
(6, 0.7033308839013043),
(7, 0.07297717280499402)]
# 計(jì)算與新數(shù)據(jù)的相似度
In [158]: index = similarities.SparseMatrixSimilarity(tfidf_model [corpus], num_features=len(dictionary.keys()))
In [159]: text_new = '小明喜歡吃蘋果' # 一條新數(shù)據(jù)
In [160]: ws_new = jieba.lcut(text_new)
In [161]: ws_new
Out[161]: ['小明', '喜歡', '吃', '蘋果']
In [162]: ws
Out[162]:
[['我', '喜歡', '吃', '蘋果', '和', '桃子', '尤其', '是', '桃子'],
['小甲', '喜歡', '吃', '蘋果'],
['小乙', '喜愛', '吃', '西瓜'],
['小丁', '喜歡', '吃', '蘋果', '西瓜']]
In [163]: vec_new = dictionary.doc2bow(ws_new)
In [164]: vec_new
Out[164]: [(0, 1), (2, 1), (7, 1)]
In [165]: index[tfidf_model[vec_new]]
Out[166]: array([0.1032053 , 0.28159946, 0. , 0.2538916 ], dtype=float32) # 與第二條相似度最高柿菩,最后一條次高,結(jié)果還是比較合理的
3. 對比sklearn和gensim的計(jì)算結(jié)果
回顧下sklean和gensim各自生成的詞表
In [163]: tfidf_vec.vocabulary_ # sklean
Out[163]:
{'我': 8,
'喜歡': 2,
'吃': 0,
'蘋果': 11,
'和': 1,
'桃子': 10,
'尤其': 7,
'是': 9,
'小甲': 6,
'小乙': 5,
'喜愛': 3,
'西瓜': 12,
'小丁': 4}
In [164]: dictionary.token2id # gensim
Out[164]:
{'吃': 0,
'和': 1,
'喜歡': 2,
'尤其': 3,
'我': 4,
'是': 5,
'桃子': 6,
'蘋果': 7,
'小甲': 8,
'喜愛': 9,
'小乙': 10,
'西瓜': 11,
'小丁': 12}
第一條數(shù)據(jù)我 喜歡 吃 蘋果 和 桃子 尤其 是 桃子
In [158]: list(tfidf_matrix.toarray()[0]) # sklearn的結(jié)果
Out[158]:
[
0.1731111372459707, # 吃
0.3317312678886485, # 和
0.21173977118307816, # 喜歡
0.0, # 喜愛
0.0, # 小丁
0.0, # 小乙
0.0, # 小甲
0.3317312678886485, # 尤其
0.3317312678886485, # 我
0.3317312678886485, # 是
0.663462535777297, # 桃子
0.21173977118307816, # 蘋果
0.0 # 西瓜
]
In [159]: tfidf_matrix_gensim[0] # gensim的結(jié)果
Out[159]:
[
(1, 0.35166544195065214), # 和
(2, 0.07297717280499402), # 喜歡
(3, 0.35166544195065214), # 尤其
(4, 0.35166544195065214), # 我
(5, 0.35166544195065214), # 是
(6, 0.7033308839013043), # 桃子
(7, 0.07297717280499402) # 蘋果
]
簡單觀察雨涛,發(fā)現(xiàn)gensim對重要token計(jì)算出的tfidf值偏大枢舶,對次要token計(jì)算出的tfidf偏小,區(qū)分度更大
參考: