python、numpy计算不同文档下的词的TF-IDF值以及进行文档相似度匹配(实战)
TF-IDF
计算公式(一个词的 tf-idf 值在不同文档,它的值也不同):
1、根据已有的原始数据,只展示了前5片文档,content是文档内容,s_words是通过jieba分词将文档划分成了若干个词:
2、统计整个语料库所有词的词频,只计算前5000个高频词的TF-IDF值(因为如果词表太大,那么最后文本的向量化表示也会太大了,词表的大小就是文本向量化后的维度)
3、计算TF-IDF
# 根据tfidf的公式,求出每个文档中,每个词的tf、idf和tfidf import numpy as np def get_word_tfidf(docs,corpus): dim = len(corpus) #获得语料库维度 word2id = {} #将word映射成id print(f"docs number:{len(docs)}\tdim:{dim}") for index,term in enumerate(corpus): word2id[term[0]] = index #生成Word2id word_tf = np.zeros((len(docs),dim)) #生成需要统计的tf表 N = len(docs) #文档总数 word_idf = np.zeros(dim) #词的IDF值 word_df = np.zeros(dim) #词的DF值 docs_set = [] #将同一个文档的词组表去重,这个目的是为了加速查找 for doc in docs: docs_set.append(set(doc)) #生成 docs_set for term in corpus: #统计df word = term[0] num = 0 #计数 for doc_set in docs_set: #doc_set if word in doc_set: #判断是否在当前文档出现过 num+=1 word_df[word2id[word]] = num #获取词的df值 word_idf = np.log(N/(word_df+1)) #计算IDF值 for index, doc in enumerate(docs): #计算不同文档下词的tf值 n = len(doc) # 统计文档的词总数 for word in doc: #循环 if word in word2id.keys(): #遍历 cnt = doc.count(word) #计数 word_tf[index][word2id[word]] = cnt/n #计算 word_tf_idf = np.multiply(word_tf , word_idf) #计算tf-idf return word_tf_idf #返回的是不同文档下词的TF-IDF值 docs = [] for d in list(s_data.iterrows()): docs.append(d[1]['s_words']) #由于特征维度太多内存装载不下,出现memory error,因此取top 5000个词作为维度 corpus = cntr.most_common(5000) corpus_tf_idf = get_word_tfidf(docs,corpus) #调用函数 print(corpus_tf_idf.shape) #输出 print(corpus_tf_idf[:5])#输出样例
文档向量化——计算文档之间的相似度
根据刚才得到的 corpus_tf_idf 矩阵,每一行其实就是文档的向量化表示,通过计算两个向量的余弦相似度,从而得到文档与文档之间的相关程度。
# 把文档按照tfidf值进行向量化 # 通过cos相似度找出跟某文档最相似的top5文档 def cos_similar(a, b): #计算两个向量的余弦相似度 dot = a * b #点积 a_len = np.linalg.norm(a, axis=0) #取模 b_len = np.linalg.norm(b, axis=0) #取模 cos = dot.sum(axis=0) / (a_len * b_len) #计算余弦相似度 return cos def search(query_vec,docs_vec): #计算查询向量和文档向量的余弦相似度 candidates = [] #统计所有文档 for i in range(docs_vec.shape[0]): #遍历 cos = cos_similar(query_vec,docs_vec[i]) #计算余弦相似度 candidates.append((i,cos)) #添加id,为了排序 candidates = sorted(candidates,key=lambda x:-x[1]) #按照余弦相似度倒排 return candidates #返回 #计算查询文档和候选文档的余弦相似度 candidates = search(corpus_tf_idf[0],corpus_tf_idf) K= 5 for i in range(K): #输出top5的文档 print(f"cos:{candidates[i][1]} data:{s_data.iloc[candidates[i][0]]}")
根据自己的语料训练word2vec模型
使用gensim库进行训练,语料的输入格式为(中文就需要先分词,英文直接按空格划分就行):
训练代码和展示:
from gensim.models import Word2Vec #训练Word2vec模型 model = Word2Vec(docs , size=100, window=5, min_count=1, workers=4) #生成词向量 model['喜欢']