文本匹配(text matching)技术广泛应用于信息检索、智能问答、对话等业务场景。尽管当前该技术已经相对有了长足的进步,但是随着领域的拓展,标注数据的缺乏,以及用户描述上的多样性,如何精准的匹配用户意图,变得越来越困难。随着5G时代的应用与发展,文本匹配技术应用越来越广泛,要求越来越高。
给定一定数量的标注语料和大量的未标注语料,要求选手设计算法和模型预测给定句对语义层面的关系,实现精准匹配:
(1)相似(label=1);
(2)不相似(label=0)。
所有文本数据都经过清洗与脱敏处理,被统一分词并编码成词表ID序列。
数据共包含3个txt文件,详细信息如下:
(1)train.txt:训练集,每一行对应一条训练样本,约25万条。包含有三个字段,分别为text_a、text_b和label,字段之间由Tab键(\t)分隔;
(2)test.txt:测试集,约1.2万条。数据格式同train.txt,但不包含label;
(3)corpus.txt:无监督数据集,文件大小约2G,一行表示一篇文档的分词结果。由选手自行选择是否使用以及如何使用。
训练数据样例:2 5 10 5 200\t5 40 72 99 56\t0
(其中2 5 10 5 200为text_a,5 40 72 99 56为text_b,0为label)
无监督数据样例:2 5 10 5 300 7 30 5 400 5 60 8 300 5 60 5 700 9 30 5 500
文本匹配是自然语言处理中的一个核心问题,很多自然语言处理的任务都可以抽象成文本匹配问题,例如信息检索可以归结成查询项和文档的匹配,问答系统可以归结为问题和候选答案的匹配,对话系统可以归结为对话和回复的匹配。针对不同的任务选取合适的匹配模型,提高匹配的准确率成为自然语言处理任务的重要挑战。
'''
句子相似度计算以下几种方法:
编辑距离计算
杰卡德系数计算
TF 计算
TFIDF 计算
Word2Vec 计算
'''
"""
基于gensim模块的中文句子相似度计算
思路如下:
1.文本预处理:中文分词,去除停用词
2.计算词频
3.创建字典(单词与编号之间的映射)
4.将待比较的文档转换为向量(词袋表示方法)
5.建立语料库
6.初始化模型
7.创建索引
8.相似度计算并返回相似度最大的文本
"""
import jieba
import jieba.posseg as pseg
from gensim import corpora, models, similarities
from gensim.similarities import Similarity
def StopWordsList(filepath):
wlst = [w.strip() for w in open(filepath, 'r', encoding='utf8').readlines()]
return wlst
def seg_sentence(sentence,stop_words):
sentence_seged = jieba.cut_for_search(sentence.strip())
# sentence_seged = set(sentence_seged)
# outstr = ''
outstr = []
for word in sentence_seged:
if word not in stop_words:
if word != '\t':
outstr.append(word)
# outstr += word
# outstr += ' '
return outstr#.split(' ')
def seg_sentence1(sentence):
sentence_seged = jieba.cut_for_search(sentence.strip())
# sentence_seged = set(sentence_seged)
# outstr = ''
outstr = []
stop_words = "\t"
for word in sentence_seged:
if word not in stop_words:
if word != '\t':
outstr.append(word)
# outstr += word
# outstr += ' '
return outstr#.split(' ')
# def seg_sentence(sentence, stop_words):
# # stop_flag = ['x', 'c', 'u', 'd', 'p', 't', 'uj', 'm', 'f', 'r']#过滤数字m
# stop_flag = ['x', 'c', 'u', 'd', 'p', 't', 'uj', 'f', 'r']
# sentence_seged = pseg.cut(sentence)
# # sentence_seged = set(sentence_seged)
# outstr = []
# for word,flag in sentence_seged:
# # if word not in stop_words:
# if word not in stop_words and flag not in stop_flag:
# outstr.append(word)
# return outstr
def word_cut(doc):
seg = [jieba.lcut(w) for w in doc]
return seg
if __name__ == '__main__':
tpath = 'textA_file.txt'
tpathB = 'textB_file.txt'
dataB =open('textB_file.txt','r')
# stop_words = StopWordsList(spPath)
stop_words = "\t"
keyword = '3333 3009 17 1035 2149 6205 270'#1039 31 0 12870 1743 2517 57 260
documents = [
'1039 31 0 12870 177 1743 2517 260'
# ,'96 1573 1730 8392'
]
# texts= word_cut(documents)
# 1、将【文本集】生产【分词列表】
# texts = seg_sentence1("")
texts = [seg_sentence(seg, stop_words) for seg in open(tpath, 'r', encoding='utf8').readlines()]
print(texts)
orig_txt = [seg for seg in open(tpath, 'r', encoding='utf8').readlines()]
print("---------------------1")
#一、建立词袋模型
# 2、基于文件集建立【词典】,并提取词典特征
dictionary = corpora.Dictionary(texts)
feature_cnt = len(dictionary.token2id.keys())
print("---------------------2")
# 3、基于词典,将【分词列表集】转换为【稀疏向量集】,也就是【语料库】
corpus = [dictionary.doc2bow(text) for text in texts]
print("---------------------3")
# 4、使用“TF-TDF模型”处理【语料库】
#二、建立TF-IDF模型
'''
TF-IDF(注意:这里不是减号)是一种统计方法,
用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
字词的重要性随着它在文件中出现的次数成正比增加,
但同时会随着它在语料库中出现的频率成反比下降。
TF-IDF加权的各种形式常被搜索引擎应用,
作为文件与用户查询之间相关程度的度量或评级。
1. 一个词预测主题能力越强,权重就越大,反之,权重就越小。
我们在网页中看到“原子能”这个词,或多或少地能了解网页的主题。
我们看到“应用”一次,对主题基本上还是一无所知。
因此,“原子能“的权重就应该比应用大。
2. 应删除词的权重应该是零。
'''
'''
def __init__(self, corpus=None, id2word=None, dictionary=None,
wlocal=utils.identity, wglobal=df2idf, normalize=True)
#corpus: 语料
#id2word: id转向词函数
#dictionary:词典
#wlocal: 用在计算
# vector = [(termid, self.wlocal(tf)
# self.idfs.get(termid))
# for termid, tf in bow if self.idfs.get(termid, 0.0) != 0.0]
# wglobal: 用要计算地方
# dict((termid, wglobal(df, total_docs))
# for termid, df in iteritems(dfs))
# normalize: 规范化处理;这个可以是一个布尔类型的值,也可以是自定义的函数;
'''
# tfidf = models.TfidfModel(corpus)#TfidfModel
tfidf = models.LdaModel(corpus, id2word=dictionary, num_topics=100)
# tfidf = models.TfidfModel(corpus)
print("---------------------4")
#三构建一个query文本,利用词袋模型的字典将其映射到向量空间
count = 0
# ----------------------------------------------------------------------------------
# ----------------------------------------------------------------------------------
# NUM_TOPICS = 128
# corpus_tfidf = [tfidf[doc] for doc in corpus]
# #转化成lsi向量
# lsi= models.LsiModel(corpus_tfidf,id2word=dictionary,num_topics=NUM_TOPICS)
# corpus_lsi = [lsi[doc] for doc in corpus]
# similarity_lsi=Similarity('Similarity-Lsi-index', corpus_lsi, num_features=400,num_best=5)
# ----------------------------------------------------------------------------------
# ----------------------------------------------------------------------------------
for line in dataB:
# 5、同理,用词典把搜索词也转换为稀疏向量
kw_vector = dictionary.doc2bow(seg_sentence(line, stop_words))#keyword
# print("---------------------5")
# 6、对稀疏向量建立索引
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=feature_cnt)
# print("---------------------6")
# 7、相似的计算
sim = index[tfidf[kw_vector]]
print(sim[count])
# print(type(sim[count]))
#--------------------------------------------------------------------
# print('相似度:',similarity_lsi[lsi[tfidf[dictionary.doc2bow(seg_sentence(line, stop_words))]]])
#--------------------------------------------------------------------
#--------------------------------------------------------------------
txtName = "***_XATU_predict.txt"
outputfile=open(txtName, "a+")#str[0:3]
if sim[count] >= 0.85:#设置阈值
new_context = "1" + '\n'
outputfile.write(new_context)
else:
new_context = "0" + '\n'
outputfile.write(new_context)
#--------------------------------------------------------------------
#--------------------------------------------------------------------
count = count + 1
# print(sim)
# result_list = []
# for i in range(len(sim)):
# print('keyword 与 text%d 相似度为:%.2f' % (i + 1, sim[i]))
# if sim[i] > 0.4:
# result_list.append(orig_txt[i])
# print('原始的句子:',result_list)