使用sklean的计算方法,这种结果是稠密矩阵,如果数据集太大,计算结果将会占满内存,或者直接报MemeryError的错误。
tfidf详细计算参考:https://blog.csdn.net/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]