doc2vec
Doc2vec方法是一种无监督算法,能从变长的文本(例如:句子、段落或文档)中学习得到固定长度的特征表示。Doc2vec也可以叫做 Paragraph Vector、Sentence Embeddings,它可以获得句子、段落和文档的向量表达,是Word2Vec的拓展,其具有一些优点,比如不用固定句子长度,接受不同长度的句子做训练样本。
简单来说就是先用大量文本进行训练得到模型,之后用模型就可以将任意一段文本转为向量。有了向量,才能进行相似度的计算。
gensim里有现成的doc2vec,直接拿来使用就行
gensim的使用
import os
import gensim
import smart_open
import logging
import sqlite3
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
def read_db3(fname):
conn = sqlite3.connect(fname)
cur = conn.cursor()
cur.execute('select lngid,description from modify_title_info_zt where description !=""')
outtext = cur.fetchone()
while outtext:
tokens = gensim.utils.simple_preprocess(outtext[1])
yield gensim.models.doc2vec.TaggedDocument(tokens, outtext[0])
outtext = cur.fetchone()
train_corpus = list(read_db3('zt_aipjournal_20210615_1.db3'))
上面的代码非常简单,将db3中的description字段进行小写化、去掉符号、分词得到用来训练的语料
model = gensim.models.doc2vec.Doc2Vec(vector_size=100, min_count=2, epochs=10,workers=4)
model.build_vocab(train_corpus)
model.train(train_corpus, total_examples=model.corpus_count, epochs=model.epochs)
model.save('aip.model')
vector_size 向量的维数,默认100
min_count 去掉词频小于设定值的词
epochs 迭代次数 默认10次
workers 训练的进程数
训练完成后保存模型,供之后使用。
上面的语料有18万个文档,100维的模型训练时间用了500秒,训练300维的模型用了750秒
def read_corpus(fname, tokens_only=False):
with smart_open.open(fname, encoding="utf8") as f:
for i, line in enumerate(f):
tokens = gensim.utils.simple_preprocess(line)
if tokens_only:
yield tokens
else:
# For training data, add tags
yield gensim.models.doc2vec.TaggedDocument(tokens, [i])
test_corpus = list(read_corpus('test.txt', tokens_only=True))
new_model = gensim.models.doc2vec.Doc2Vec.load('aip.model')
vectorlist = []
for i in range (len(test_corpus)):
vectorlist.append(new_model.infer_vector(test_corpus[i]))
import numpy as np
from gensim import matutils
line = 'Three hundred thirty-one Chinese school children on Taiwan were given an aqueous oil trachoma vaccine and 322 an aqueous oil placebo'
vector = new_model.infer_vector(gensim.utils.simple_preprocess(line))
for i in range(0,7):
similarity = np.dot(matutils.unitvec(vector), matutils.unitvec(vectorlist[i]))
print(similarity)
训练完成保存的模型,之后可以直接载入进行使用
相似度计算采用余弦相似度
使用函数matutils.unitvec() 将向量长度缩放为1,因此直接计算向量的点积就得到了相似度
test.txt里有7篇文章的摘要,最后的相似度计算是我在最后一篇文章截取的一段文字与7篇摘要分别进行计算的结果
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。