文本相似度计算的简单实例超详细代码解释(附代码,文件)

任务目标

本次实验是根据淘宝搜索的商品标题来寻找类似的商品标题:
给定一个标题:Apple iPhone 8 (A1863) 64GB 深空灰色 移动联通电信4G手机
找出与其类似的前十个标题
文本相似度计算的简单实例超详细代码解释(附代码,文件)_第1张图片
后面是相似度,越接近1越相似,相似度采用余弦相似性

代码解释

import jieba
import pickle
import numpy as np
import pandas as pd
from gensim import corpora
from gensim import models

jieba.load_userdict('userdict.txt') # 载入自定义词典
filepath = r'stopwords.txt' # 载入停用词
stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()] # 提取停用词

# 导入已经算好的idf文档和词袋模型中的词典,数据如图
with open('data.pk', 'rb') as f:
    all_dick, idf_dict = pickle.load(f)

文本相似度计算的简单实例超详细代码解释(附代码,文件)_第2张图片
文本相似度计算的简单实例超详细代码解释(附代码,文件)_第3张图片
ps:这个idf值可以根据自己的需求算,也可以使用jieba分词中自带的。具体怎么算可以看我另一篇博客:基于jieba分词的TF-IDF提取关键词算法中自定义所使用逆向文件频率(IDF)的文本语料库

# 按行读取文件
def read_file(file_path):
    with open(file_path, 'r', encoding='utf-8-sig') as f:
        fina_outlist = [line.strip() for line in f.readlines()]
    return fina_outlist
# 按每行读取,每一行按空格切分为一个list,组成2维列表。
def read_file2matrix(file_path): # 这里读取的是刚才载入的idf_dict对导入数据集中每一条数据都计算出它们的tf-idf值,返回列表形式
    fina_outlist = []
    with open(file_path, 'r', encoding='utf-8-sig') as f:
        for line in f.readlines():
            outlist = [float(i) for i in line.strip().split(' ') if i != ' ']
            fina_outlist.append(outlist)
    return fina_outlist
# 使用jieba的搜索引擎模式分词
def split_words(words):
    word_list = jieba.cut_for_search(words.lower().strip(),HMM=True) # 转小写,去空格,加新词发现
    word_list = [i for i in word_list if i not in stopwords and i!=' ']  # 去停用词
    return word_list
# 统计词频(每个词在该文档中出现的频率,也就是tf值,为后面计算tf_idf做准备),并返回字典
def make_word_freq(word_list):
    freword = {}
    for i in word_list:
        if str(i) in freword:
            freword[str(i)] += 1
        else:
            freword[str(i)] = 1
    return freword
# 计算tfidf,组成tfidf矩阵
def make_tfidf(word_list,all_dick,idf_dict):
    length = len(word_list) # 词袋模型的长度
    word_list = [word for word in word_list if word in all_dick]
    word_freq = make_word_freq(word_list)
    w_dic = np.zeros(len(all_dick)) # 先建立长度为词袋模型中总单词量的0矩阵
    for word in word_list: # 将tf_idf替换掉相应位置的0
        ind = all_dick[word]
        idf = idf_dict[word]
        w_dic[ind] = float(word_freq[word]/length)*float(idf)
    return w_dic
# 基于numpy的余弦相似性计算
def Cos_Distance(vector1, vector2):
    vec1 = np.array(vector1)
    vec2 = np.array(vector2)
    return float(np.sum(vec1 * vec2)) / (np.linalg.norm(vec1) * np.linalg.norm(vec2)) # 余弦相似度的计算公式,不会的百度
# 计算相似度
def similarity_words(vec, vecs_list):
    Similarity_list = []
    for vec_i in vecs_list: # vecs_list是所有标题的tf-idf值,用来和要搜索的标题做比较,看相似
        Similarity = Cos_Distance(vec, vec_i)
        Similarity_list.append(Similarity)
    return Similarity_list
    
def main(words, file_path, readed_path):
    words_list = read_file(file_path)
    vecs_list = read_file2matrix(readed_path)
    word_list = split_words(words)
    vec = make_tfidf(word_list,all_dick,idf_dict)
    similarity_lists = similarity_words(vec, vecs_list)
    sorted_res = sorted(enumerate(similarity_lists), key=lambda x: x[1]) # 按相似度排序
    outputs = [[words_list[i[0]],i[1]] for i in sorted_res[-10:]] # 取前十个相似的
    return outputs

#测试
# words = '小米8 全面屏游戏智能手机 6GB+128GB 黑色 全网通4G 双卡双待  拍照手机'
# words = '荣耀 畅玩7X 4GB+32GB 全网通4G全面屏手机 标配版 铂光金'
words = 'Apple iPhone 8 Plus (A1864) 64GB 深空灰色 移动联通电信4G手机'
# words = '小米8'
# words = "黑色手机"
# words = 'Apple iPhone 8'
# words = '索尼 sony'
file_path = r'MobilePhoneTitle.txt'
readed_path = r"MobilePhoneTitle_tfidf.txt"
outputs = main(words, file_path, readed_path)
# print(outputs)
for i in outputs[::-1]:
    print(i[0] + '     ' + str(i[1]))
    

输出结果

文本相似度计算的简单实例超详细代码解释(附代码,文件)_第4张图片
里面的所使用的文件可以留言邮箱,看到会发给你,这个很简单的教程仅做参考,权当入门,大神勿喷,相应可以用word2vec等其他方法慢慢改进

你可能感兴趣的:(nlp)