- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
一、Woed2Vec详解
1.什么是Woed2Vec
Word2Vec是一种计算模型,它将词汇表中的每个词映射到一个固定大小的向量。这种技术是自然语言处理(NLP)领域的一个重要突破,由Google在2013年左右推出。Word2Vec模型能够捕捉词汇表中词之间的语义和语法关系,这些关系被编码在词向量(word embeddings)中。
Word2Vec主要有两种架构:连续词袋(CBOW)和Skip-Gram。
连续词袋(CBOW)
- CBOW模型通过一个词的上下文(即周围的词)来预测这个词。简单来说,CBOW模型考虑一个词周围的几个词(例如,一个5词窗口),然后将这些词作为输入来预测中心的词。
- 输入层:选择一个中心词的上下文单词,通常包括中心词前后的几个词(例如,一个5词窗口)。
- 投影层:将输入的上下文单词的词向量求和或平均,得到一个单一的向量。
- 隐藏层:这个投影层向量通常是直接用作隐藏层的输入。
- 输出层:输出层是一个softmax单元,它预测给定上下文的情况下中心词的概率分布。
- 训练:通过比较预测的分布和真实的分布(即中心词的实际分布),计算损失函数(通常是交叉熵损失),并通过反向传播更新权重。
CBOW模型通常在较大的数据集上训练得更快,因为它试图预测一个词而不是多个词。CBOW在预测常见词方面表现得更好,因为它考虑了多个上下文词。
Skip-Gram
- Skip-Gram模型则相反,它使用一个词来预测其上下文。在Skip-Gram模型中,模型试图根据中心词来预测周围的词。
这两种架构都使用神经网络作为训练机制,通过大量文本数据学习,生成词向量。这些词向量通常能够捕捉到丰富的语言学规律,例如,向量之间的距离可以表示词义之间的相似性("国王"和"王后"这样的词在向量空间中可能靠得很近),而且还能表现出一些语言学关系,比如性别、时态等。Skip-Gram模型的架构如下:
- 输入层:输入是单个词的词向量。
- 隐藏层:输入层直接连接到隐藏层,这里的隐藏层可以看作是输入层的复制。
- 输出层:输出层是一组softmax单元,每个单元对应词汇表中的一个词。这些单元的目的是预测给定输入词的上下文中每个词的概率。
- 训练:与CBOW类似,通过比较预测的分布和真实的分布计算损失函数,并通过反向传播更新权重。
Skip-Gram模型在处理稀有词和复杂模式方面表现得更好,因为它试图为每个上下文单词生成预测。然而,Skip-Gram的训练通常比CBOW慢,因为它需要预测多个输出。
总结
- CBOW:适用于大规模数据集和频繁词的向量表示,训练速度较快。
- Skip-Gram:适用于处理稀有词和复杂的语言模式,训练速度较慢。
2.使用方法
gensim.models.Word2Vec
是 Gensim 库中的一个函数,用于训练 Word2Vec 模型。Gensim 是一个 Python 库,用于主题建模和文档相似性分析,它提供了 Word2Vec 模型的实现。下面是 gensim.models.Word2Vec
函数的基本用法和各个参数的含义:
gensim.models.word2vec.Word2Vec(sentences=None, corpus_file=None, size=100, alpha=0.025, window=5, min_count=5, max_vocab_size=None, sample=0.001, seed=1, workers=3, min_alpha=0.0001, sg=0, hs=0, negative=5, ns_exponent=0.75, cbow_mean=1, hashfxn=<built-in function hash>, iter=5, null_word=0, trim_rule=None, sorted_vocab=1, batch_words=10000, compute_loss=False, callbacks=(), max_final_vocab=None
)
主要参数:
sentences (iterable of iterables, optional): 供训练的句子,可以使用简单的列表。
corpus_file (str, optional): LineSentence格式的语料库文件路径。
size (int, optional): word向量的维度。
window (int, optional): 一个句子中当前单词和被预测单词的最大距离。
min_count (int, optional): 忽略词频小于此值的单词。
workers (int, optional): 训练模型时使用的线程数。
sg ({0, 1}, optional): 模型的训练算法: 1: skip-gram; 0: CBOW.
hs ({0, 1}, optional): 1: 采用hierarchical softmax训练模型; 0: 使用负采样。
negative (int, optional): 0: 使用负采样,设置多个负采样(通常在5-20之间)。
ns_exponent (float, optional): 负采样分布指数。1.0样本值与频率成正比,0.0样本所有单词均等,负值更多地带样低频词。
cbow_mean ({0, 1}, optional): 0: 使用上下文单词向量的总和; 1: 使用均值,适用于使用CBOW。
alpha (float, optional): 初始学习率。
min_alpha (float, optional): 随着训练的进行,学习率线性下降到min_alpha。
seed (int, optional): 随机数发生器种子。
max_vocab_size (int, optional): 词汇构建期间RAM的限制,如果有更多的独特单词,则修剪不常见的单词。每1000万个类型的字需要大约1GB的RAM。
max_final_vocab (int, optional): 自动选择匹配的min_count将词汇限制为目标词汇大小。
sample (float, optional): 高频词随机下采样的配置阈值,范围是(0,1e-5)。
hashfxn (function, optional): 哈希函数用于随机初始化权重,以提高训练的可重复性。
iter (int, optional): 迭代次数。
trim_rule (function, optional): 词汇修剪规则,指定某些词语是否应保留在词汇表中,修剪掉或使用默认值处理。
sorted_vocab ({0, 1}, optional): 如果为1,则在分配单词索引前按降序对词汇表进行排序。
batch_words (int, optional): 每一个batch传递给线程单词的数量。
compute_loss (bool, optional): 如果为True,则计算并存储可使用get_latest_training_loss()检索的损失值。
callbacks (iterable of CallbackAny2Vec, optional): 在训练中特定阶段执行回调序列。
使用示例:
from gensim.models import Word2Vec
# 训练数据
sentences = [['this', 'is', 'the', 'first', 'sentence'], ['this', 'is', 'the', 'second', 'sentence']]
# 创建Word2Vec模型
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4)
# 训练模型
model.train(sentences, total_examples=model.corpus_count, epochs=model.iter)
# 获取词向量
word_vector = model.wv['word']
# 保存模型
model.save('word2vec.model')
# 加载模型
model = Word2Vec.load('word2vec.model')
二、训练前数据处理
1. 原始语料分词
import os
os.chdir(r'C:/Users/Dell/AppData/Roaming/Python/Python311/site-packages/')
# 这里改变路径是因为我没办法把jieba库下载在anaconda里面,只能下载在本地然后读取路径
import jieba
import jieba.analyse
os.chdir('C:\\Users\\Dell\\训练营')#这里需要改回路径不然pytorch环境里面的其他东西都用不了了jieba.suggest_freq('沙瑞金', True) # 加入一些词,使得jieba分词准确率更高
jieba.suggest_freq('田国富', True)
jieba.suggest_freq('高育良', True)
jieba.suggest_freq('侯亮平', True)
jieba.suggest_freq('钟小艾', True)
jieba.suggest_freq('陈岩石', True)
jieba.suggest_freq('欧阳菁', True)
jieba.suggest_freq('易学习', True)
jieba.suggest_freq('王大路', True)
jieba.suggest_freq('蔡成功', True)
jieba.suggest_freq('孙连城', True)
jieba.suggest_freq('季昌明', True)
jieba.suggest_freq('丁义珍', True)
jieba.suggest_freq('郑西坡', True)
jieba.suggest_freq('赵东来', True)
jieba.suggest_freq('高小琴', True)
jieba.suggest_freq('赵瑞龙', True)
jieba.suggest_freq('林华华', True)
jieba.suggest_freq('陆亦可', True)
jieba.suggest_freq('刘新建', True)
jieba.suggest_freq('刘庆视', True)
jieba.suggest_freq('赵德汉', True)
with open(r'C:\Users\Dell\训练营\in_the_name_of_people.txt',encoding='utf-8') as f:result_cut = []lines = f.readlines()for line in lines:result_cut.append(list(jieba.cut(line)))f.close()
输出
Building prefix dict from the default dictionary …
Loading model from cache C:\Users\Dell\AppData\Local\Temp\jieba.cache
Loading model cost 0.576 seconds.
Prefix dict has been built successfully.
2.确定停用词
在自然语言处理(NLP)中,停用词(stop words)是指在文本中频繁出现但对于传达实际意义贡献不大的词。这些词通常是冠词、介词、连词等,例如“的”、“和”、“是”、“在”等。停用词在文本中几乎无处不在,但它们并不携带太多实际的语义信息。
停用词在NLP中的作用主要体现在以下几个方面:
- 减少噪声:去除停用词可以减少文本数据中的噪声,让模型更加关注那些携带更多语义信息的词。
- 提高效率:在文本处理过程中,去除停用词可以减少计算量和存储空间的需求,提高处理效率。
- 改善结果:在一些NLP任务中,如文本分类、情感分析等,去除停用词可以减少无意义的特征,有助于提高模型的性能和准确度。
在实际训练中,处理停用词的方法通常包括以下几个步骤:
- 获取停用词表:可以使用现成的停用词表,如NLTK、spaCy等库提供的停用词列表,也可以根据具体任务自定义停用词表。
- 文本预处理:在文本清洗和预处理阶段,将文本中的停用词去除。
- 特征提取:在提取文本特征时,忽略停用词。
- 模型训练:使用去除停用词后的文本数据进行模型训练。
需要注意的是,并不是所有的NLP任务都需要去除停用词。在某些任务中,如命名实体识别(NER)、词性标注(POS Tagging)等,停用词也可能携带一些有用的信息,因此是否去除停用词需要根据具体任务的需求来决定。停用词列表并不是一成不变的,它应该根据具体的语料库和应用场景进行调整。在社交媒体文本分析中,“哈哈”、“嗯嗯”这类词可能被视为停用词,因为它们出现频率高但语义信息少。
# 添加自定义停用词
stopwords_list = [",","。","\n","\u3000"," ",":","!","?","…"]
#\u3000 是一个 Unicode 编码的字符,它代表一个全角的空白字符,通常在中文文本中用作空格。
#这个字符在许多亚洲语言中用于文本排版,因为它比普通的半角空格( )宽。def remove_stopwords(ls): # 去除停用词 return [word for word in ls if word not in stopwords_list] result_stop=[remove_stopwords(x) for x in result_cut if remove_stopwords(x)]
print(result_stop[100:103])
输出
NLP文本去噪技巧
在自然语言处理(NLP)中,去噪是一个关键的预处理步骤,它有助于提高后续处理步骤的质量。
- 文本标准化:
- 将文本转换为小写(或大写),以消除大小写的差异。
- 扩展缩写词,例如将“can’t”转换为“cannot”。
- 规范化数字的表示,例如将“$1000”转换为“1000美元”。
- 去除无关字符:
- 移除标点符号、特殊字符和不可见的控制字符。
- 清理文档中的HTML标签或其他格式化代码。
- 处理停用词:
- 移除常见的停用词,如“的”、“和”、“是”等,这些词在大多数NLP任务中不携带重要的语义信息。
- 词干提取和词形还原:
- 使用词干提取(stemming)将单词缩减为其词干形式,例如将“running”缩减为“run”。
- 使用词形还原(lemmatization)将单词转换为它们的词典形式(lemma),例如将“cars”还原为“car”。
- 纠正拼写错误:
- 使用拼写检查工具来识别和纠正文本中的拼写错误。
- 处理重复文本:
- 移除或合并连续出现的重复单词或句子。
- 处理非标准文本:
- 对于社交媒体文本或用户生成的内容,可能需要处理表情符号、网络用语、非标准拼写等。
- 语言检测和翻译:
- 如果处理多语言数据,可能需要检测文本的语言并进行必要的翻译。
- 使用NLP库和工具:
- 利用NLP库,如NLTK、spaCy、TextBlob等,它们提供了丰富的工具和资源来帮助去噪和文本预处理。
- 自定义去噪规则:
- 根据特定任务的需求,可能需要定义一些自定义的去噪规则。
- 迭代和评估:
- 在去噪过程中,迭代地测试不同的方法,并评估去噪对后续NLP任务性能的影响。
- 文档结构分析:
- 对于结构化的文档,如报告或学术论文,分析文档的标题、摘要、章节等结构,以提取关键信息。
去噪是一个迭代的过程,可能需要根据具体的应用场景和可用资源进行调整。在实际应用中,去噪的效果通常通过后续NLP任务的性能来评估,如分类准确性、主题模型的连贯性等。
三、训练Woed2Vec模型
from gensim.models import Word2Vec model = Word2Vec(result_stop, # 训练的语料数据vector_size=100, # 特征向量的维度,默认为100。 window=5, # 一个句子中当前单词和被预测单词的最大距离。 min_count=1) # 可以对字典做截断。词频少于min_count次数的单词会被丢弃掉,默认值为5。
四、模型应用
1.计算词汇相似度
model.wv.similarity
函数是 Gensim 库中 Word2Vec 模型的一个方法,用于计算两个词向量的余弦相似度。余弦相似度是一种衡量两个向量在方向上相似程度的度量,它的值范围在 -1 到 1 之间,1 表示完全相同的方向,-1 表示完全相反的方向,0 表示两者正交,即没有相似性。
计算余弦相似度的步骤如下:
- 获取词向量:首先,需要获取两个词的词向量。这些向量是在 Word2Vec 模型训练过程中学习到的。
- 计算点积:计算两个向量的点积(内积)。点积可以通过将两个向量的对应元素相乘然后求和得到。
- 计算向量长度:计算每个向量的长度(范数)。向量的长度是通过将向量中的每个元素平方后求和,然后取平方根得到的。
- 计算余弦相似度:余弦相似度是通过将两个向量的点积除以它们长度的乘积得到的。数学上表示为:
在 Gensim 中,model.wv.similarity
方法会自动执行上述步骤,返回两个词向量之间的余弦相似度值。如果其中一个词不在词汇表中,该方法会抛出一个异常。
# 计算两个词的相似度
print(model.wv.similarity('沙瑞金','季昌明'))
print(model.wv.similarity('沙瑞金','田国富'))
0.9993937
0.999558
# 选出最相似的5个词
for e in model.wv.most_similar(positive=['沙瑞金'],topn=5):print(e[0], e[1])
学生 0.9996994137763977
老 0.9996634721755981
还是 0.9996193647384644
赵东来 0.999608039855957
又 0.9995825290679932
2.找出不匹配的词汇
model.wv.doesnt_match
是 Gensim 库中 Word2Vec 模型的一个方法,用于找出一个列表中与其他词最不相似的词。这个方法基于 Word2Vec 模型学习到的词向量,通过计算词向量之间的余弦相似度来确定最不相似的词。
该方法的工作原理如下:
- 获取词向量:首先,需要获取列表中所有词的词向量。这些向量是在 Word2Vec 模型训练过程中学习到的。
- 计算相似度:对于列表中的每个词,计算它与其他词的余弦相似度。这需要对列表中的每个词计算与其他词的点积,然后除以它们长度的乘积。
- 选择最不相似的词:对于列表中的每个词,找出它与其他词中最小的相似度值。这个最小值就是该词与其他词中最不相似的度量。
- 返回结果:最后,返回列表中与其他词最不相似的词。
在 Gensim 中,model.wv.doesnt_match
方法会自动执行上述步骤,返回一个列表,其中包含列表中与其他词最不相似的词。如果列表中的某个词不在词汇表中,该方法会抛出一个异常。
odd_word = model.wv.doesnt_match(["苹果","香蕉", "橙子", "书"])
print(f"在这组词汇中不匹配的词汇:{odd_word}")
在这组词汇中不匹配的词汇:书
3.计算词汇的词频
get_vecattr
函数是Word2Vec模型中的一个方法,用于获取词向量的附加属性。它通常接收两个参数:单词和一个属性名称。
- 第一个参数:单词,即你想要查询的词汇。
- 第二个参数:属性名称,可以是以下几种:
'count'
:该单词在训练时出现的次数。'mean'
:返回这个词向量的平均值。'norm'
:返回这个词向量的欧几里得范数(L2范数)。'total_count'
:这个单词及其所有上下文词对的总数。'total_bytes'
:存储向量所需的字节数。'total_words'
:训练集中的总词数。'state_size'
:在线训练期间的状态大小。
注意:使用get_vecattr
函数前需要确保Word2Vec模型已经被正确训练,并且传入的单词是在模型训练时出现的词汇之一。
word_frequency = model.wv.get_vecattr("沙瑞金","count")
print(f"沙瑞金:{word_frequency}")
沙瑞金:353