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['喜欢']

 

posted @ 2022-06-15 14:43  ISGuXing  阅读(748)  评论(0编辑  收藏  举报