目录
pip install gensim -i https://pypi.tuna.tsinghua.edu.cn/simple
#若在jupyter notebook中安装:
! pip install gensim -i https://pypi.tuna.tsinghua.edu.cn/simple
#导包
import jieba
import re
import numpy as np
from sklearn.decomposition import PCA
import gensim
from gensim.models import Word2Vec #导入预训练好的Word2Vec模型
import matplotlib.pyplot as plt
import matplotlib #中文字体用matplotlib加载,显示中文
1.分词
f = open('../data/sanguo.txt', 'r', encoding='utf-8')
lines = []
for line in f: #将f当做是一个数据集迭代器,一行行遍历比较好,不会一下占用很大内存
#jieba分词 lcut是精确分词模式
temp = jieba.lcut(line)
words = [] #接收token
for i in temp: #temp是一个字符串列表,每一个元素都是一个字符串
#过滤标点符号 re.sub(需要替换掉的内容, 用什么替换, 操作对象)
i = re.sub("[\s+\.\!\/_,$%^*(+\"\'“”《》]+|[+--!,。?、~@……#¥&*():;‘]+", "", i)
if len(i) > 0:
words.append(i) #i 是一个句子
if len(words) > 0:
lines.append(words)
print(lines[0:5])
#在输出结果中,一个列表就是一个句子
[['三国演义', '上卷'], ['罗贯中'], ['滚滚', '长江', '东', '逝水', '浪花', '淘尽', '英雄', '是非成败', '转头', '空', '青山', '依旧', '在', '几度', '夕阳红'], ['白发', '渔樵', '江渚上', '惯看', '秋月春风', '一壶', '浊酒', '喜相逢', '古今', '多少', '事', '都', '付笑谈', '中'], ['调寄', '临江仙']]
2.模型训练
#创建模型的时候就会进行训练
#vector_size=embedding_dim,把原始数据压缩成多少维度,不能太高或者太低,太低就会丢失太多信息
#window 滑动窗口大小
#min_count=5 词频低于5就被删除
#sg=1 表示使用Word2Vec的skip_gram模型
#negative=10 负采样的噪声词的数量
#epochs=30 训练次数不是越多效果越好
model = Word2Vec(sentences=lines, vector_size=20, window=3, min_count=3, epochs=10, sg=1, negative=10)
print('刘备的词向量:\n', model.wv['刘备']) #等同于上一句代码
#获取某个词的词向量: 按照索引在词汇表中查找
#model.wv 是中心词的词向量
print('刘备的词向量:\n', model.wv.get_vector('刘备'))
刘备的词向量: [-0.2890919 -0.64534736 0.35023224 0.5738358 0.615334 -0.20633562 0.39474598 0.5770406 -0.6374094 0.6299717 0.53927785 -0.3620445 -0.58977085 -0.18836461 -0.17590947 0.6360351 0.5856611 -0.99581605 -0.51967734 -1.1827276 ]
#找与“刘备”最相似的前n个词
model.wv.most_similar('孔明', topn=10)
[('玄德', 0.9126482009887695),
('二嫂', 0.8797737956047058),
('鲁肃入', 0.8780523538589478),
('庞统', 0.8647811412811279),
('孔明入', 0.8644561171531677),
('甘夫人', 0.8625627756118774),
('回书', 0.8624818921089172),
('孙夫人', 0.8620772361755371),
('一遍', 0.8579021096229553),
('孔明遂', 0.8574188947677612)]
3.可视化
model.wv.index_to_key
输出结果部分展示:
['曰', '之', '也', '吾', '与', '而', '将', '了', '有', '在',]
raw_wordvec = [] #存放原始分词的词向量
word2ind = {} #存放词与索引
#i, w表示 索引, 原始分的词
for i, w in enumerate(model.wv.index_to_key): #enumerate()遍历元素及元素对应的索引
raw_wordvec.append(model.wv[w]) #根据分的词w,获取到w的词向量,再添加到列表raw_wordvec中
word2ind[w] = i #将词w与索引i一一对应存放到字典word2ind中
#降维只能用ndarray进行, 将数据转化为ndarray
raw_wordvec = np.array(raw_wordvec)
#数据降维,将数据降成二维
X_reduced = PCA(n_components=2).fit_transform(raw_wordvec)
X_reduced
array([[-0.9565789 , 0.43193746], [-0.62351465, 0.20734401], [-0.9055981 , 0.18587902], ..., [-0.47270492, -0.0872296 ], [ 0.24143706, -0.00525565], [ 0.44416195, -0.20065238]], dtype=float32)
word2vec中获取每个词的词向量直接在预训练好的模型中查找得到
#创建视图大小
fig = plt.figure(figsize=(15,10))
#获取当前视图
ax = fig.gca()
#设置背景色
ax.set_facecolor('white')
#绘制
ax.plot(X_reduced[:, 0], X_reduced[:, 1], '.', markersize=1, alpha=0.3, color='black')
#绘制几个文章中常见的词
words = ['孙权','刘备','曹操','周瑜','诸葛亮','司马懿','张飞','关羽','吕布','大乔','小乔']
#设置中文字体的显示
font = matplotlib.font_manager.FontProperties(fname='../data/华文仿宋.ttf', size=16)
for w in words:
if w in word2ind:
ind = word2ind[w]
xy = X_reduced[ind]
plt.plot(xy[0], xy[1], '.', alpha=1, color='red', markersize=10)
plt.text(xy[0], xy[1], w, fontproperties=font, alpha=1, color='green')
4.知识点个人理解
词向量的用途
- 主题聚类
- 情感分析
- 信息检索
word2vec的缺点:
- 没有考虑同义词
- 窗口长度有限
- 没有考虑全局的文本信息
- 不是严格意义上的语序