最初的目的是为了自己检索文献的方便建立了一个local的大数据集GeotechSet,这个数据集包括了岩石力学和土力学相关的各种各样的书,杂志论文和会议论文以及一些岩土工程软件用户手册。在此基础上,不断聚类出某一特定关键词的topic作为新的数据源。假如我们计划开始一个新的研究题目"PFC3D的岩石边坡稳定性分析", 我们想要做的第一步是迅速汇集出文献中所有带有这些关键词的相似句子或段落, 这一点类似于“头脑风暴法”。这种“聚类”对于研究生论文的选题和各种基金题目的写作以及论文生成有很大帮助,因为在这个聚合过程中,一方面可以明白其它作者是如何表述这一topic的,另一方面也能够在这个聚类中发展出自己新的研究思路。这种聚类过程的本质是寻找句子和段落之间的相似度。
句子和段落的相似度检查是自然语言处理中一个非常重要的研究课题,论文的查重其实就是检查段落之间的相似度。不过我们的目的与查重的目的正好相反,我们是想得到重复或相似的东西。在过去,我们已经作了大量的工作使用不同的途径来进行这种数据挖掘。本文回顾了近期使用的一些比较有效的方法。
2 Doc2Vec相似查询
Doc2Vec是我们最初使用的一种方法。这种方法不使用外部的训练库,仅对自身的数据集进行训练,使用词的window来表示句子语义的相似。例如window=8表示输入词左侧8个词和右侧8个词进入我们的训练窗口。在此基础上发展出来的WMD(Word Moving Distance)方法是我们目前使用的主要方法。WMD是基于Doc2Vec建立的向量库(geotech-wmd-doc2vec.py)实现的,这种方法来源于论文《From Word Embeddings To Document Distances》。其优点是能够部分实现语义查询,缺点是运行时间较长。
(1) 读入数据集。在这里我使用了一个判断语句,把那些字符长度小于50的句子排除掉。
(2) 训练Doc2Vec
(3) 相似度计算
3 SQL相似查询
这种方法是直接把查询的关键词与数据集中的每个句子进行比较,只要句子中包含所要查询的词,不管句子有多长,都算一个相似的句子。当然在实际写作中,没有人整篇文章都使用逗号而不使用句号。在我们大量的测试中,这种方法比Doc2Vec得到的有用信息更多。这种方法(geotech-words-combination.py)中,通过把一个句子分词,然后对分词进行组合C(n,3)对数据集(.txt)进行查询,能够把数据集中所有包含关键词组合的句子提取出来,缺点是没有对句子按照相似度排序。下面简要描述这种方法的步骤:
(1)首先需要对查询句子进行分词处理,去掉无用的stopwords,当然我们也可以直接输入关键词。例如我们需要查询“PFC2D的边坡稳定性分析 slope stability"。
(2) 分词之后,从这四个分开的词组中组合其中的3个作为一个查询集 合。使用下面的代码进行组合计算。这样我们可以得到如下的组合:
[('PFC2D', '边坡稳定性', 'slope'),
('PFC2D', '边坡稳定性', 'stability'),
('PFC2D', 'slope', 'stability'),
('边坡稳定性', 'slope', 'stability')]
(3) 对其中每一个组合分别查询整个数据集,最后得出如下结果。
4 Sklearn相似查询
最初,我们使用euclidean_distances进行相似查询,即通过Euclidean距离计算向量值来对句子相似度排序,结果发现这种方法计算文本相似有缺陷,特别是处理非结构化的文本时经常返回空值,因此抛弃了这种算法,改用余弦相似计算(geotech-similarity-query.py) , 这种方法对于短句子效果较好,对于长句子效果差一些。
首先导入模块:
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import codecs
import os
然后进行矢量化运算,
vectorizer = CountVectorizer()
features = vectorizer.fit_transform(corpus).todense()
最后进行余弦相似计算,这里使用了一个判断语句if (round(each[1],2)) >= 0.3,用来获得相似度大于等于0.3的那些句子。
#
我们把这个用法扩展到整个目录下,用来查找与query句子最相似的句子。使用下面的代码:
databases = []
directory = ".\\temp"
for fpathe,dirs,fs in os.walk(directory):
for f in fs:
flname = os.path.join(fpathe,f)
databases.append(flname)
单个数据文件的尺寸不能太大,初步估计超过2M就会出现错误:“Unable to allocate 9.04 GiB for an array with shape (53973, 22490) and data type float64”,这是因为内存不够,试着把虚拟内存调到了最大值,也不起作用。目前还没有找到好的解决方法,只能把大的文件分割成小文件。
5 Transformers相似查询
Transformers首先需要建立model, 与WMD不同的是,这个model不是依靠自身的corpus来训练的,而是基于一些预训练的模型。目前我们有两个预训练的model,一个是纯英语的model, 另一个是多语言的model,为了能精确捕捉更多的中英文信息,我们设计在同一次运行中同时使用这两个model, 于是把这两个model组成一个list。这种方法可以实现中英文混合查询。Transformers得出的结果优于WMD得出的结果,同时,Transformers的聚类能帮助我们集中关注某一类论题。
models = [SentenceTransformer('roberta-large-nli-stsb-mean-tokens'), \
SentenceTransformer('distiluse-base-multilingual-cased')]
然后对这两个model进行循环:
for each_model in models:
do something ;进行计算
6 结束语
对于大规模的数据集来说,上述这些方法结合起来使用效果会好一些。通过这种相似查询,能够帮助我们快速凝练出topic的粘合度, 在很大程度上有助于论文写作和课题申请,特别是英文论文的写作,因为目前的数据集中90%是英文文献 。目前还在继续扩展数据集,聚类主题以及发展更先进的查询方法。
本文扩展阅读: