【深度学习:进阶篇】--4.2.词嵌入和NLP
在RNN中词使用one_hot表示的问题
- 假设有10000个词
- 每个词的向量长度都为10000,整体大小太大
- 没能表示出词与词之间的关系
- 例如Apple与Orange会更近一些,Man与Woman会近一些,取任意两个向量计算内积都为0
目录
1.词嵌入
1.1.特点
1.3.word2vec介绍
1.3.Word2Vec案例
1.3.1.训练语料
1.3.2.步骤
1.3.3.代码
2.测试代码
1.词嵌入
定义:指把一个维数为所有词的数量的高维空间嵌入到一个维数低得多的连续向量空间中,每个单词或词组被映射为实数域上的向量。
注:这个维数通常不定,不同实现算法指定维度都不一样,通常在30~500之间。
如下图所示:
1.1.特点
- 能够体现出词与词之间的关系
- 比如说我们用Man - Woman,或者Apple - Orange,都能得到一个向量
- 能够得到相似词,例如Man - Woman = King - ?
- ? = Queen
1.2.word2vec介绍
Bengio等人在一系列论文中使用了神经概率语言模型使机器“习得词语的分布式表示。
2013年,谷歌托马斯·米科洛维(Tomas Mikolov)领导的团队发明了一套工具word2vec来进行词嵌入。
Word2Vec 是一种广泛使用的词嵌入(Word Embedding)技术,由 Google 团队(Tomas Mikolov 等)于 2013 年提出。它通过神经网络模型将单词映射到低维稠密向量空间,使得语义相似的词在向量空间中距离相近。Word2Vec 是 NLP 领域的基础技术之一,广泛应用于文本分类、机器翻译、推荐系统等任务。
Word2Vec 的核心假设是:“具有相似上下文的单词,其语义也相似”。它通过训练神经网络,使得模型能够从大量文本中学习单词的分布式表示(Distributed Representation)。
1.主要特点
- 稠密向量表示:每个单词用一个固定长度的低维向量(如 100~300 维)表示,相比传统的 one-hot 编码更高效。
- 语义相似性:语义相近的词(如 "king" 和 "queen")在向量空间中距离较近。
- 计算高效:采用负采样(Negative Sampling)或层次 Softmax(Hierarchical Softmax)优化训练速度。
2. Word2Vec 的两种模型
Word2Vec 包含两种不同的训练方式:
(1) CBOW(Continuous Bag of Words)
- 目标:根据上下文单词预测当前单词。
- 适用场景:适合小型数据集或高频词。
- 示例:
- 输入:
["the", "cat", "on", "the"]
(上下文窗口=4) - 输出:预测
"mat"
(中心词)
- 输入:
(2) Skip-Gram
- 目标:根据当前单词预测上下文单词。
- 适用场景:适合大型数据集或低频词,效果通常比 CBOW 更好。
- 示例:
- 输入:
"mat"
(中心词) - 输出:预测
["the", "cat", "on", "the"]
(上下文窗口=4)
- 输入:
- skip-gram
算法学习实现:https://www.tensorflow.org/tutorials/representation/word2vec
下载gensim库
pip install gensim
1.3.Word2Vec案例
1.3.1.训练语料
由于语料比较大,就提供了一个下载地址:搜狗搜索引擎 - 上网从搜狗开始
- 搜狗新闻中文语料(2.7G)
- 做中文分词处理之后的结果
1.3.2.步骤
-
1、训练模型
-
2、测试模型结果
1.3.3.代码
- 训练模型API
- from gensim import Word2Vec
- Word2Vec(LineSentence(inp), size=400, window=5, min_count=5)
- LineSentence(inp):把word2vec训练模型的磁盘存储文件
- 转换成所需要的格式,如:[[“sentence1”],[”sentence1”]]
- size:是每个词的向量维度
- window:是词向量训练时的上下文扫描窗口大小,窗口为5就是考虑前5个词和后5个词
- min-count:设置最低频率,默认是5,如果一个词语在文档中出现的次数小于5,那么就会丢弃
- 方法:
- inp:分词后的文本
- save(outp1):保存模型
这里需要传入训练好的分词结果:corpus_seg.txt
训练的代码如下
import sys
import multiprocessingfrom gensim.models import Word2Vec
from gensim.models.word2vec import LineSentenceif __name__ == '__main__':if len(sys.argv) < 3:sys.exit(1)# inp表示语料库(分词),outp:模型inp, outp = sys.argv[1:3]model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count())model.save(outp)
运行命令
python trainword2vec.py ./corpus_seg.txt ./model/*
指定好分词的文件以及,保存模型的文件
- 加载模型测试代码
- model = gensim.models.Word2Vec.load("*.model")
- model.most_similar('警察')
- model.similarity('男人','女人')
- most_similar(positive=['女人', '丈夫'], negative=['男人'], topn=1)
- model = gensim.models.Word2Vec.load("*.model")
improt gensim
gensim.models.Word2Vec.load("./model/corpus.model")model.most_similar("警察")Out:
[('警员', 0.6961891651153564),('保安人员', 0.6414757370948792),('警官', 0.6149201989173889),('消防员', 0.6082159876823425),('宪兵', 0.6013336181640625),('保安', 0.5982533693313599),('武警战士', 0.5962344408035278),('公安人员', 0.5880240201950073),('民警', 0.5878666639328003),('刑警', 0.5800305604934692)]model.similarity('男人','女人')
Out: 0.8909852730435042model.most_similar(positive=['女人', '丈夫'], negative=['男人'], topn=1)
Out: [('妻子', 0.7788498997688293)]
2.测试代码
步骤 | 功能描述 | 关键点/注意事项 |
---|---|---|
1. 导入库 | 加载必要的Python库 | gensim 用于Word2Vec,nltk 用于分词,os 用于路径操作。 |
2. 检查NLTK数据 | 确保punkt 分词数据存在,若缺失则自动下载 | - 使用try-except 避免中断。- quiet=True 隐藏下载日志。 |
3. 定义示例数据 | 提供待训练的文本句子 | 实际应用中需替换为大规模文本(如从文件读取)。 |
4. 分词处理 | 将句子拆分为单词列表 | - 优先用word_tokenize 处理标点。- 失败时回退到 split() (效果较差)。 |
5. 训练Word2Vec | 根据分词结果训练词向量模型 | - vector_size=100 : 词向量维度。- sg=1 : 使用Skip-Gram算法(适合小数据)。 |
6. 保存模型 | 将模型保存到磁盘 | 后续可通过Word2Vec.load("word2vec.model") 复用模型。 |
7. 测试模型 | 验证词向量效果(查询词向量和相似词) |
from gensim.models import Word2Vec
from nltk.tokenize import word_tokenize
import nltk
import os# 确保下载必要的NLTK数据
try:nltk.data.find('tokenizers/punkt')print("NLTK punkt data already downloaded")
except LookupError:print("Downloading NLTK punkt data...")nltk.download('punkt', quiet=True)# 某些环境可能需要额外下载punkt_tabtry:nltk.download('punkt_tab', quiet=True)except:print("punkt_tab not available, using only punkt")# 示例文本数据
sentences = ["I love natural language processing.","Word2Vec is a popular embedding technique.","Deep learning is changing the world."
]# 分词(带错误回退机制)
try:tokenized_sentences = [word_tokenize(sent.lower()) for sent in sentences]print("Tokenizer succeeded!")
except LookupError as e:print(f"Tokenizer failed: {e}")print("Falling back to simple whitespace tokenizer...")tokenized_sentences = [sent.lower().split() for sent in sentences]# 训练 Word2Vec 模型
model = Word2Vec(sentences=tokenized_sentences,vector_size=100, # 向量维度window=5, # 上下文窗口大小min_count=1, # 忽略低频词sg=1, # 1=Skip-Gram, 0=CBOWnegative=5, # 负采样数量epochs=10 # 训练轮次
)# 保存模型
model.save("word2vec.model")
print("Model saved successfully!")# 测试词向量
try:print("Example word vector for 'learning':", model.wv['learning'])print("Most similar to 'processing':", model.wv.most_similar('processing'))
except KeyError as e:print(f"Word not in vocabulary: {e}")
# 加载模型
model = Word2Vec.load("word2vec.model")# 获取单词向量
vector = model.wv["word2vec"] # 获取 "word2vec" 的向量# 计算相似词
similar_words = model.wv.most_similar("nlp", topn=3)
print(similar_words) # 输出:[('natural', 0.92), ('language', 0.88), ('processing', 0.85)]