文本相似度计算(切词、生成词向量,使用余弦相似度计算)

项目需求

有多个文本,分别是正负样本,使用余弦相似度计算负样本与正样本的样本相似度,若准确率高,后期可判断新加样本与正样本的相似度。

输入如下所示:
content label
今天下午,在龙口市诸由观镇涧村张常鸿家的大院里。 1
呼啦呼啦,巴拉巴拉小魔仙 1
张常鸿的爸爸张振俭告诉记者,从4月份以后就再没有见到张常鸿了。 0
张常鸿2000年2月14日出生于山东烟台龙口市。 0
大家好 0
在上午举行的资格赛中,选手将以跪射、卧射和立射三个姿势各打40发。 0
呼啦呼啦,巴拉巴拉小魔仙 0
你好 0

切词

分贝使用jieba.lcut和tfidf进行分词,代码如下所示:

# -*- coding:utf-8 -*-
# @time  : 11:20
# @Author:xxma
import jieba
import jieba.analyse as ana
import re
def cn(text):
    '''
    剔除特殊字符及数字,只保留中文
    :param text:
    :return:
    '''
    str = re.findall(u"[\u4e00-\u9fa5]+", text)
    return str

# 加载停用词
with open(r'D:\xxma\文本分析\停用词.txt', 'r', encoding='utf-8') as f:
    stopwords = [s.strip() for s in f.readlines()]

def jiebacut(text):
    """
    使用普通分词
    :param text: 原始文本
    :return:切分后的词,且用空格分隔
    """
    text=str(cn(text))
    # jieba.load_userdict(r'dict.txt') #加载自定义词典,本次不设置
    words = [w for w in jieba.lcut(text) if w not in stopwords]  # 剔除停用词
    # print(words,len(words))
    words = [w for w in words if len(words) > 2] #剔除短文本
    return ' '.join(words)


def tfidfcut(text):
    """
    使用tfidf分词
    :param text:原始文本
    :return:切分后的词,且用空格分隔
    """
    text = str(cn(str(text)))
    ana.set_stop_words(r'D:\xxma\文本分析\停用词.txt')
    # print(ana.extract_tags(text))
    words = [w for w in ana.extract_tags(text) if len(ana.extract_tags(text)) > 1]
    return ' '.join(words)


生成词向量,并计算余弦相似度

分别使用词频和tfidf生成词向量,再分别计算余弦相似度,代码如下:

# -*- coding:utf-8 -*-
# @time  : 11:21
# @Author:xxma
"""
输入必须有2列,分别为content 及label
label为1或0:其中1为正样本,即问题样本,0为负样本,即待验证的样本,
"""
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

"""
1、CountVectorizer:会将文本中的词语转换为词频矩阵,它通过fit_transform函数计算各个词语出现的次数,通过get_feature_names()可获得所有文本
   的关键词,通过toarray()可看到词频矩阵的结果,TfidfTransformer用于统计vectorizer中每个词语的TFIDF值
2、TfidfVectorizer:将原始文档的集合转化为tf-idf特性的矩阵,相当于CountVectorizer配合TfidfTransformer使用的效果。
   即TfidfVectorizer类将CountVectorizer和TfidfTransformer类封装在一起
"""
from 文本分析.分词 import jiebacut, tfidfcut

# 加载数据
# df = pd.read_excel(r'D:\xxma\文本分析\sd\数据打标.xlsx', sheet_name='总的数据').drop_duplicates()
# df = df.sort_values(by='label',ascending=False)
threshold = float(input('请输入余弦相似度的阈值(0-1之间的相似度):'))
print('加载数据ing')
df1 = pd.read_excel(r'D:\xxma\文本分析\sd\questionData.xlsx').drop_duplicates()  # 新样本数据,待验证的数据
df2 = pd.read_csv(r'D:\xxma\文本分析\sd\data-1626936455161.csv', sep=',').drop_duplicates() # 问题样本数据
df2 = df2.loc[0:50000, ('content', 'label')]
df = pd.concat([df1, df2])
df = df.sort_values(by='label', ascending=False)
# 分词
print('开始分词ing')
df['cut'] = df['content'].apply(tfidfcut)
df['len'] = df['cut'].apply(len)
df = df[df['len'] > 0].reset_index(drop=True)
# 正负样本个数
positive_num = df[df['label'] == 1].shape[0]
negitive_num = df[df['label'] == 0].shape[0]
# 使用词频生成词向量
print('生成词向量ing')
Vectorizer = CountVectorizer()
vector = Vectorizer.fit_transform(df['cut'])
names = Vectorizer.get_feature_names()
positive = vector.toarray()[0:positive_num]
negitive = vector.toarray()[positive_num:]

# 使用tfidf生成词向量
Vectorizer_tfidf = TfidfVectorizer()
vector_tfidf = Vectorizer_tfidf.fit_transform(df['cut'])
names_tfidf = Vectorizer_tfidf.get_feature_names()
positive_tfidf = vector_tfidf.toarray()[0:positive_num]
negitive_tfidf = vector_tfidf.toarray()[positive_num:]

# 余弦相似度
print('计算余弦相似度ing')
consine_fre = cosine_similarity(negitive, positive)
consine_tfidf = cosine_similarity(negitive_tfidf, positive_tfidf)

# 数据保存
print('保存结果数据ing')
cos = [consine_fre, consine_tfidf]
cos_name = ['consine_fre', 'consine_tfidf']
writer = pd.ExcelWriter(r'D:\xxma\文本分析\sd\consine_result.xlsx')
for name, i in zip(cos_name, cos):
    df_result = pd.DataFrame(i)
    df_result['max'] = df_result.max(axis=1)
    df_result['max_index'] = np.argmax(i, axis=1)

    question = df[(df['label'] == 1)]['content'].reset_index(drop=True)
    df_result['matched'] = df_result['max_index'].apply(lambda x: question[x])
    # 合并原始数据
    orgin_df = pd.DataFrame(df[(df['label'] == 0)]['content'].reset_index(drop=True))
    consine_df = df_result.loc[:, ('max', 'matched')]
    result_df = orgin_df.join(consine_df)
    result_df = result_df.sort_values(by='max', ascending=False)
    result_df = result_df[result_df['max'] > threshold]
    result_df.to_excel(writer, sheet_name=name, index=0, encoding='utf-8')
writer.save()
#writer.close()`
#最终发现:使用tfidf进行分词,再使用词频生成词向量的效果最佳

你可能感兴趣的:(文本数据处理,自然语言处理)