Doc2Vec主要作用是将文章转化为词向量,支持大批量的数据训练,如果遇到多个较大的数据文件,不能全部加装到内存中,可以使用下面的方法,自己封装TaggedDocument。
如果数据量较小,且只有1个数据文件,可以使用doc2vec.TaggedLineDocument,注意,数据文件一行对应一篇文章,并且词必须以空格隔开。
1 TaggedLineDocument训练小数据
# 设置迭代器
tagged_line = TaggedLineDocument("F:\\my_data\\test.text")
# 构建模型
model = Doc2Vec(dim=0, vector_size=100, window=8, epochs=2, min_count=2, workers=4)
# 将迭代器添加到模型中
model.build_vocab(tagged_line )
2 封装TaggedDocument训练大数据
2.1 数据
F:
--my_data
----model
----mason_1.txt
----mason_2.txt
“mason_1.txt”内容
我,爱你,河南大学
你,的,母校
我,爱你,河南大学
“mason_2.txt”内容
我,爱你,软件学院
我,敬爱,导师
2.2 代码
from gensim.models.doc2vec import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
import os
class TaggedData(object):
"""
继承object类,使用yield实现大数据量文件的批量训练Doc2Vec模型
"""
def __init__(self, dir_name):
"""
初始化目录
:param dir_name: 文件目录
"""
self.dir_name = dir_name
def __iter__(self):
"""
实现迭代器
"""
for f_name in os.listdir(self.dir_name):
f_name = os.path.join(self.dir_name, f_name)
if not os.path.isfile(f_name):
continue
# 读取文件
with open(f_name, "r", encoding="utf-8") as fin:
for item_no, line in enumerate(fin):
# 切分文件
words = line.split(",")
# 注意:我的文件是一行对应一篇文章
# TaggedDocument(文章的词列表, [文章表标签])
# 自己定义唯一的文章标签,方便后续查找文章向量
yield TaggedDocument(words, tags=['%s_%s' % (f_name, item_no)])
def train_model():
# 设置迭代器
tagged_data = TaggedData("F:\\my_data")
# 构建模型
model = Doc2Vec(dim=0, vector_size=100, window=8, epochs=2, min_count=2, workers=4)
# 将迭代器添加到模型中
# 注意:documents也可以接收[TaggedDocument(doc, tags=[tag)]列表
# 可以根据自己的需求将文章组合为列表
model.build_vocab(documents=tagged_data)
print("---** 多次训练模型 **---")
# 注意文章的数据不能太少,至少5个文章以上
# 否则会报“you must first build vocabulary before training the model”错误
for i in range(3):
model.train(documents=tagged_data, total_examples=model.corpus_count, epochs=model.epochs)
# 打印
print("---** 统计文章数量 **---")
print(model.docvecs.count)
print("---** 文章标签(列表) **---")
print(model.docvecs.offset2doctag)
print("---** 文章向量(numpy列表) **---")
print(model.docvecs.vectors_docs)
print("---** 文章统计(字典) **---")
# 'F:\\my_data\\mason_1.txt_0': Doctag(offset=0, word_count=3, doc_count=1),
# '文章标签': Doctag(offset=对应vectors_docs和offset2doctag的索引, word_count=单词数量, doc_count=文章频次)
print(model.docvecs.doctags)
print("---** 统计与“F:\\my_data\\mason_1.txt_0”文章最相似的文章(列表) **---")
# ('F:\\my_data\\mason_2.txt_0', -0.04498976841568947)
# ('文章标签', 相似度)
print(model.docvecs.most_similar(model.docvecs.doctags.get("F:\\my_data\\mason_1.txt_0")))
print("---** 比较两篇文章的相似度 **---")
# 注意:这里比较只能在已有文章中查找
# similarity(文章1标签,文章2标签)
print(model.docvecs.similarity("F:\\my_data\\mason_1.txt_0", "F:\\my_data\\mason_1.txt_1"))
# similarity(文章1索引,文章2标签)
print(model.docvecs.similarity(0, 1))
print("---** 计算文章的词向量 **---")
words=["河南大学", "软件学院"]
print(model.infer_vector(words))
print("---** 模型的保存 **---")
model.save("F:\\my_data\\model\\henu.model")
print("---** 模型的加载 **---")
model = Doc2Vec.load("F:\\my_data\\model\\henu.model")
# Word2Vec与Doc2Vec的用法相同,不同之处在于
# model.wv:是对应Word2Vec的方法
# model.docvecs:是对应Doc2Vec的方法
if __name__ == '__main__':
train_model()
3 Word2Vec和Doc2Vec
Word2Vec与Doc2Vec的用法基本相同,不同之处在于“model.wv”是对应Word2Vec的方法,“model.docvecs”是对应Doc2Vec的方法。