使用sklean的计算方法,这种结果是稠密矩阵,如果数据集太大,计算结果将会占满内存,或者直接报MemeryError的错误。
tfidf详细计算参考:https://blog.youkuaiyun.com/Eastmount/article/details/50323063
import jieba
import jieba.posseg as pseg
import os
import sys
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
if __name__ == "__main__":
corpus=["我 来到 北京 清华大学",#第一类文本切词后的结果,词之间以空格隔开
"他 来到 了 网易 杭研 大厦",#第二类文本的切词结果
"小明 硕士 毕业 与 中国 科学院",#第三类文本的切词结果
"我 爱 北京 天安门"]#第四类文本的切词结果
vectorizer=CountVectorizer()#该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频
transformer=TfidfTransformer()#该类会统计每个词语的tf-idf权值
tfidf=transformer.fit_transform(vectorizer.fit_transform(corpus))#第一个fit_transform是计算tf-idf,第二个fit_transform是将文本转为词频矩阵
word=vectorizer.get_feature_names()#获取词袋模型中的所有词语
weight=tfidf.toarray()#将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重
for i in range(len(weight)):#打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for便利某一类文本下的词语权重
print u"-------这里输出第",i,u"类文本的词语tf-idf权重------"
for j in range(len(word)):
print word[j],weight[i][j]
当数据集过大的时候,我们可以使用稀疏存储的方式来计算TF-IDF。最后返回结果是一个list,里面的元素是字典,同时这样表示之后的余弦相似度计算也更简单。
corpus 就是分词好的数据,每行是一个数组;
直接传入函数calc_tfidf(corpus)计算得到tfidf;
每一行里面是一个map,key是词,value是tfidf;
cos_sim函数传入两行数据,map格式,计算两个文本的相似度;
get_top(tfidf,top)保留每个文本里面的top词,可以直接传入小数,表示保留百分比;
# coding=utf-8
# @author: bryan
corpus = data['标题'].apply(lambda x: [i for i in jb.cut(x)])
import math
def list2dic(l):
tmp = {}
for i in l:
if i in tmp:
tmp[i] += 1
else:
tmp[i] = 1
return tmp
def calc_tfidf(corpus):
tf, tmp = [], []
for line in corpus:
tf.append(list2dic(line))
for i in tf:
tmp.extend(i.keys())
idf = list2dic(tmp)
N = len(tf)
for i in idf:
idf[i] = math.log(N / (idf[i] + 1))
for i in range(len(tf)):
for word in tf[i]:
tf[i][word] = tf[i][word] * idf[word]
return tf
def cos_sim(x1, x2):
if (not x1) | (not x2):
return 0
if (len(x1) == 0) | (len(x2) == 0):
return 0
fenzi, fenmu1, fenmu2 = 0, 0, 0
for i in x1.keys():
if i in x2:
fenzi += x1[i] * x2[i]
fenmu1 += x1[i] * x1[i]
for i in x2.values():
fenmu2 += i * i
fenmu = math.sqrt(fenmu1) * math.sqrt(fenmu2)
return fenzi / fenmu
def get_top(tfidf, top):
# 根据tf-idf保留top的词
return [dict(sorted(i.items(), key=lambda x: x[1], reverse=True)[:int(len(i) * top)]) for i in tfidf]