基于CNN和词向量的文本相似度分析
1. 前言
众所周知,现在的时代就是海量数据暴增的时代,每天的各种聊天工具和数以亿计的网页产生了海量的人工无法高效处理的各种文字信息。由此而生,我们自然想到通过分类来减少信息检索,分类的依据就是文本之间的相似度,同时人们希望电脑能帮助人们来实现这一难题,从而各种基于语句格式和语义统计的语言表示方法诞生了。
在这样一个大环境下,人们接触文本数据也越来越多,而在中文的语义环境下,每一个语义,可能对应着许多不同的文本。而不管是搜索引擎或是社区问答系统都需要我们在给出一个文本时,从数据库中具有相同语义的所有句子都查找出来,而其可能对应的可能时完全不同的表达方式。也就意味着,可能存在完全不具备共同点的两个句子表达的是相同的含义,也可能有几乎相同的句子,可能以为某个地方的微小差别,表达的含义完全不同。本项目致力于解决这两个问题,找出表达不同,含义相同的句子,排除几乎相同语义却不一样的句子为用户提供更精准的搜索。
目前应用最为成熟的语言处理方式就是利用词向量来进行语义的表达,词向量就是利用词语的特性抽象化出来表达语言的数据结构。其中目前应用成熟的就是利用分布式矩阵来表示词的向量维度,这样可以从多方面来实现对于词语的描述。原来的基于语句结构的自然语言处理有很多的弊端,比如无法识别意思相近或者相关的词语、文本中词语的权重不合理等,语句权重不合理即文本中的核心关键词的权重程度与其他的非关键词重要程度一样,这样是不合理的。
本项目采用的是python语言所实现的基于Google在2013年推出的Word2vec的skim-gram模型来训练语料模型。然后基于该模型来做文本相似度分析。其中使用了结巴分词,关键词提取等基础的文本处理算法。并且实现了利用卷积神经网络实现文本相似度分析。并给出了相应的算法实现和部分精准度分析。
关键词:大数据 词向量 文本相似度分析 神经网络 word2vec
2. 项目分析与设计
2.1项目需求分析
本项目需要实现的就是实现句子语义上面的相似度分析,目前市面上的各种搜索引型和社区问答等使用的大多都是基于关键词的搜索,就是根据用户的输入来实现关键词的匹配来实现问答的互动。但是在语义上面的判断有时候就不尽如人意了,所以本项目致力于实现文本基于语义的自然语言智能识别的实现。
2.1.1项目功能性需求分析
(1)实现文本相似度分析
本项目需要实现短文本的相似度分析,实现基于语义的自然语言智能识别,例如:
- 计算机的价钱一般是多少?
- 电脑的价钱通常有多贵?
正如上面两句短文本所描述的那样,通过关键词的匹配来实现相似度分析是比较困难的,本项目致力于实现并解决这一问题。
(2)检索时长
目前市面上的搜索引型的检索速度是非常的快的,其核心就是通过分类实现的数据库索引,并且是简单的关键词匹配,速度当然是非常快的了。本项目的实现当然也必须考虑检索时长的问题,过于复杂的算法复杂度和文本的数量级都会导致搜索时长的增加
(3)储存和运行空间的控制
本项目需要的是大量的训练文本语料和大量的检索对象,而且一般的循环结构所实现的大量文本运算都会造成运行内存的爆满。所以基于普通电脑的性能,必须对文本的大小进行控制,同时对算法的复杂度进行改进
2.1.2 项目非功能性需求分析
(1)python3编译环境和良好性能的电脑
本项目采用python3来实现该项目,所以需要普通的运行内存超过4G的电脑,同时配置好相应的编译环境和导入相应的模块。
(2)项目组人员
该项目由四个小组成员完成,各自负责相应的实现模块,同时需要遵循相应的编码规则和相同的编译环境。
(3)经费及其相关事宜
由于本项目是小组成员自行完成,所以相关的经费和相关事宜自行负责。
2.2 项目模块设计
在本项目中,使用的网络爬虫,得到文本数据,是一个统一的杂乱的文件。再使用朴素贝叶斯算法[1]进行分类,将杂乱的文件分为不同的种类,本文主要介绍使用CNN来进行句子相似度分析,因为使用CNN的应用效果较好。详细的实现方式设计流程如图2.1:
3. 项目实现
3.1基于词向量的卷积神经网络的构建
3.1.1 Word2vec简介
Word2vec 是 Google开源的一款将词表征为实数值向量的高效工具,采用的模型有 CBOW(词袋模型)和 Skip-Gram 两种。Word2vec 通过训练,可以把对文本内容的处理简化为 K 维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度。因此, Word2vec输出的词向量可以被用来做很多 NLP 相关的工作,比如聚类、找同义词、词性分析等等。使用谷歌开源的Word2vec训练文本后可以得到每个词的向量值。也可以调用相应的包进行短语训练,或者使用多种计算相似度的方法。
import gensim.models.word2vec as w2v
#获取数据模型构建词向量
def get_model(model_file):#model_file是分词后的txt文本路径
test1=[]
test=[]
file1=open(model_file,'r')
while 1:
line1=file1.readline()
if not line1:
break
key1=analyse.extract_tags(line1)#python自带的关键词提取方法
for i in key1:
test1.append(i)
test.append(key1)
model = w2v.Word2Vec(test, size=5, window=5, workers=1, min_count=1)
return model
使用该模型:
model.similarity(词1,词2)输出为0~1的词相似度值。本项目中使用的就是相似度值。其他的使用方法待读者自行研究。
# 3.1.2 卷积神经网络简介
卷积神经网络(Convolutional Neural Network,以下简称CNN)是深度神经网络(DNN)中的一种前馈神经网络,20世纪60年代,Hubel和Wiesel在研究猫脑皮层中用于局部敏感和方向选择的神经元时发现其独特的网络结构可以有效的降低反馈神经网络的复杂性,继而提出了卷积神经网络(CNN)。现在,CNN已经成为了众多的科学领域的研究领域热点之一。其中,CNN广泛应用于图像识别领域,并且应用效果非常的明显。
CNN的最大的功能在于对于复杂对象的特征提取并且高效的分类方式,所以同时适用于文本相似度分析和文本特征提取。CNN的一般可以分为两个部分,特征提取层和特征映射层。其中,在文本相似度的应用上详细分为输入层,卷积层,池化层,连接层和输出层。图示如图3.1.1:
我们利用word2vec可以实现词向量的表示,那么就可以把句子表示为用矩阵表示的数据结构。那么,类似于用CNN做图像识别一样,我们得到的两个句子的二维矩阵来进行特征提取,二维矩阵作为输入,就可以用卷积层和池化层来进行特征提取和分类,从而得到文本相似度的结果。详细实现在下文中介绍。
3.1.2 卷积神经网络的实现
CNN在实现文本相似度分析一共分为四层,分别是输入层,卷积层,池化层和输出层。由于文本分析主要是通过判断词语之间的相似度来实现句子的相似度,所以不需要过多的步骤,下面详细介绍各层的构建和核心代码的实现。
(1)输入层
利用Word2vec来实现词向量的构建,本项目用的是python中对于Google的word2vec的skim-gram词向量模型的实现模块。输入相应的分词文本,该模型就自动构建该文本的模型。该项目的文本构建如图3.1.2所示:
核心代码:
#CNN获取输入层数据,其中三个参数分别表示输入短文本,进行比较的对象短文本,所使用的word2vec所构建的模型。
def get_input_data(input_sen,compare_sen,wordvec_model):
score=[]#记分器
wordvec_table=[]#将要返回词向量矩
keyword=analyse.extract_tags(input_sen)#获取关键词
testword=analyse.extract_tags(compare_sen)
for i in keyword:
for j in testword:
try:
sim=wordvec_model.similarity(i,j)#获取词之间的相似度
score.append(sim)
except Exception as err:
pass
if len(score)==0:
pass
else:
wordvec_table.append(score)#构建词向量矩阵
score=[]
return wordvec_table #返回词向量矩阵
(2)卷积层
卷积层主要是实现特征的选取,通过一个卷积核来扫描输入层的矩阵,卷积核的大小就是作为扫描的感受野,为了防止感受野的步长导致越界,本次项目选择2*2的卷积核,并且是一个,和CNN做图像识别不同的就是卷积核的数量,因为文本相似度分析主要是找出相似度最高的,所以选择一个卷积核就能达到目的。多个卷积核反而会降低效果。详细的计算过程请见图3.2
实现代码:
#CNN卷积层,卷积核的感受野为2*2,参数表示一个输入词向量矩阵
def cnn_folding(dict_wordvec):
rows=len(dict_wordvec[1])#获取输入矩阵的横向长度
columns=len(dict_wordvec)#获取输入矩阵的纵向长度
result=[]#返回结果集
result=[[0 for col in range(rows-1)] for row in range(columns-1)]
for i in range(columns-1):#通过循环实现整个矩阵的运算
for j in range(rows-1):
re=(dict_wordvec[i][j]+dict_wordvec[i][j+1]+dict_wordvec[i+1][j]+
dict_wordvec[i+1][j+1])/4 #实现卷积层的运算
result[i][j]=re
dict_wordvec=result
return result
(3)池化层
池化层主要是实现丢弃一些实在是不相关的数据,本项目采用max-pooling方法实现池化层,不选择average-pooling的原因是我们需要的是相似度高的数据,所以选择max-pooling效果较好。和卷积层相似,不同在于池化层只对矩阵本身进行运算。这里就不在赘述,直接给出实现代码如下:
#cnn池化层,采用max-pooling方式实现池化,参数表示输入矩阵
def cnn_pooling(dict_pooling):
rows=len(dict_pooling[1])
columns=len(dict_pooling)
result=[]
result=[[0 for col in range(rows-1)] for row in range(columns-1)]#python构造的二维列表
for i in range(columns-1):
for j in range(rows-1):
re=max(dict_pooling[i][j],dict_pooling[i][j+1],dict_pooling[i+1][j],dict_pooling[i+1][j+1])#max-pooling方法实现池化
result[i][j]=re
return result
(4)输出层
输出层主要实现卷积层和池化层的连接,经过多次的卷积层和池化层的循环,最后实现几个动态的值来表示改句子的相似度表示,简单的求平均是就可以得到一个表示相似度的值。
#实现卷积层和池化层的连接层
while 1:#交替实现卷积层和池化层
r=len(data_list[0])
c=len(data_list)
if r==1 or c==1:#判定池化层跳出循环条件
for i in range(len(data_list)):
for j in data_list[i]:
res.append(j)
break
pool=cnn_pooling(data_list)#实现池化层
if len(pool)==1 or len(pool[1])==1:#判定卷积层跳出循环的条件
data_list=pool
for i in range(len(data_list)):
for j in data_list[i]:
res.append(j)
break
else:
fold=cnn_folding(pool)#实现卷积层
data_list=fold
pool=[[0 for col in range(r-1)] for row in range(c-1)]
fold=[[0 for col in range(r-1)] for row in range(c-1)]
3.6.3 关于卷积神经网络项目实现结果分析
通过上面的几层,我们得到了一个值来表示句子的相似度,实现例子如图3.21、图3.22:
说明:
图四的运行结果说明的是CNN的各层运行结果,其中用的时候一个二层的列表来表示词向量相似度矩阵,经过卷积层和池化层的循环得出CNN输出值,这时候是一维的值,最后简单的对这几个输出值求一个平均值就是该项目得出的相似度值。
图五是对于该算法的精准度测试,分为两个部分,不同的表达方式得出的相似度大约为0.66,相同的表达方式得出的精准度约为0.85。其中该项目用的测试文本为唐善成, 白云悦, 马付玉.构建的中文语义相似度训练集[]。该训练集是专门实现不同语言文字,但是语义相同的训练集。所以该模型的精准度不是那么的高。用一般的百度问答文本准确度就会理想很多了。
当然,该模型的不足也有:
(1)在于词向量的模型构建语料过少,由于运行时间和电脑运行能力低下等问题,只能采用一定大小的文本。所以会出现模型的不精准。
(2)该模型主要是基于单个词来构建的词向量,所以对于过于短的文本效果不是太好。
总之,该模型依赖于大量的语料的统计来构建模型,其模型构建总体上还是不错的。但是还需要进一步的完善和改进。
4. 项目总结
本次项目实现了基于Google推出的Word2vec所构建的词向量来做文本相似度分析,其中采用了基础的分词和关键词的文本处理算法,在构建文本相似度时采用了CNN文本相似度算法来实现短文本的分类算法,文本相似度分析属于自然语言智能识别的重要的模块,其普遍应用于搜索引型和各种社区问答等领域。目前基于语义的文本相似度分析由于检索时间和算法复杂度的关系还没有广泛应用于搜索引型,但是基于语义的自然语言智能识别却是未来自然语言的重要智能处理方向。其在人工智能方面有巨大的市场和应用前景。只要技术成熟,其制造的市场价值将会是巨大的。
,作者ID为 朱宏 宏,