一、简介
Word2Vec和Doc2Vec都是无监督学习方法,主要用于从文本数据中学习单词和段落的嵌入表示。
Word2Vec主要用于学习单词的向量表示,它有两种模型架构:连续词袋(CBOW)和Skip-gram。在CBOW模型中,通过上下文来预测单个单词学习单词向量,而在Skip-gram模型中,则通过从单个单词预测上下文来学习单词向量(本次使用CBOW模型)。
Doc2Vec则是一种用于学习段落嵌入的无监督算法,它扩展了Word2Vec的思想,以段落为基本单位进行训练。在Doc2Vec的分布式内存(DM)模型中,每个段落都被映射到一个唯一的向量,而每个词也被映射到一个唯一的向量。段落的向量和词的向量被用于预测上下文中的下一个词。Doc2Vec还有一种称为分布式词袋(DBOW)的模型架构,其灵感来自Skip-gram Word2Vec。
二、准备工作
你可以自己准备训练数据,当然也可以用我的。
百度网盘:https://pan.baidu.com/s/1jXS-U_uHdzmbnt88k3O_Aw
提取码:p9y9
然后就是准备一些待会需要用到的库,详细下载库的几种方式请看我上一篇文章。
import jieba
from gensim.models import Word2Vec
import random
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
import numpy as np
好了,现在可以开始了。
三、Word2Vec模型
3.1 读取数据并进行分词
with open('corpus4keyword.txt', 'r', encoding='utf-8') as file:
document1 = file.read()
# 使用jieba进行分词
seg_list = jieba.cut(document1, cut_all=False)
上述分词模式使用的是精确模式,默认的也是精确模式,如果想使用其他模式,可以修改一下,将cut_all改为True即为全模式,搜索引擎模式使用jieba.cut_for_search()方法。
3.2 训练模型
# 将分词结果转换为列表
word_list = list(seg_list)
# 训练Word2Vec模型
model = Word2Vec(word_list, vector_size=100, window=5, min_count=1, sg=0)
我来讲一下上述训练模型的参数含义:
vector_size:词向量的维度 window:上下文窗口大小,表示考虑上下文的距离 min_count`:词频阈值,忽略词频低于该值的词汇 sg:训练算法,0表示CBOW,1表示Skip-gram
3.3 保存模型(没有需求的可以跳过这一步)
# 保存模型
model.save("word2vec_model.model")
这会保存到你的py文件的同级目录下,如果向保存到其他地方,请输入路径(相对路径和绝对路径都可以,本人喜欢使用绝对路径,一定不会错)。
3.4 调用模型
# 调用模型
model = Word2Vec.load("word2vec_model.model")
对应好路径位置。
3.5 模型测试及结果(我取了一条数据,主要是向量维度大,输出太多-_-||)
with open('corpus4keyword.txt', 'r', encoding='utf-8') as file:
news_datas1 = file.readlines()
news_data1 = [line.strip() for line in news_datas1]
random_news1 = random.choice(news_data1)
news_cut = list(jieba.cut(random_news1))
word_vectors1 = []
for word in news_cut:
if word in model.wv:
vector = model.wv[word]
word_vectors1.append((word, vector))
# 输出每个词的语义向量
for word, vector in word_vectors1:
print(f"词:{word},语义向量:{vector}")
运行结果(部分):
他会将你的每一个字甚至是标点符号都会形成一个100维的列表,所以是真的很大,当然,参数根据自己意愿调的话或许就不用这么多了。
四、Doc2Vec
4.1 读取数据并进行格式化
with open('corpus4keyword.txt', 'r', encoding='utf-8') as file:
document2 = [line.strip() for line in file]
# 使用TaggedDocument对每个句子进行格式化
tagged_data = [TaggedDocument(words=sentence.split(), tags=[str(i)]) for i, sentence in enumerate(document2)]
4.2 创建并训练模型
# 创建并训练doc2vec模型
model = Doc2Vec(vector_size=100, window=5, min_count=1, workers=4, epochs=20)
model.build_vocab(tagged_data)
model.train(tagged_data, total_examples=model.corpus_count, epochs=model.epochs)
我说一下上述参数的含义:
vector_size:这是用于表示每个文档的向量的维度。这个向量将映射到连续的空间中,以便进一步分析和比较。 window:这是用于预测当前词的上下文词的最大距离。这类似于Word2Vec中的窗口大小,可以帮助模型理解词语的上下文关系。 min_count:这是忽略总频数小于此的所有的词。也就是说,如果一个词的总频数小于1,那么模型将不包含这个词。 workers:这是用于控制训练的并行数。这个参数可以调整计算资源的利用,以优化训练速度。 epochs:这是语料库上的迭代次数,即模型在语料库上进行训练的轮数。 total_examples:这是语料库中的总样本数。在Doc2Vec模型中,一个样本通常被认为是一个不同的文档。这个参数可以帮助模型在训练过程中进行正确的批次处理和进度跟踪。
4.3 保存模型(没有需求的可以忽略这一步)
# 保存模型
model.save("doc2vec_model")
4.4 调用模型
# 加载训练好的doc2vec模型
model = Doc2Vec.load("doc2vec_model")
4.5 模型测试及结果(我取了两条数据)
with open('corpus4keyword.txt', 'r', encoding='utf-8') as file:
news_datas2 = file.readlines()
# 随机选择两条数据
news_data2 = random.sample(news_datas2, 2)
news_data22 = []
news_data22.append(news_data2[0].split())
news_data22.append(news_data2[1].split())
# 预处理并获取两条新闻的语义向量
vector1 = model.infer_vector(news_data22[0])
vector2 = model.infer_vector(news_data22[1])
# 计算余弦相似度
similarity = np.dot(vector1, vector2) / (np.linalg.norm(vector1) * np.linalg.norm(vector2))
print("余弦相似度:", similarity)
运行结果:
五、结语
总的来说,Word2Vec和Doc2Vec都是非常有效的文本嵌入学习方法,常被用于各种自然语言处理和文本分析任务中。在实际应用中,需要根据具体的问题和应用场景来选择合适的方法。