NLP笔记 - Word Embedding // doc2vec 之 延禧攻略

面向读者:nlp入门,python选手,对word embedding(词嵌入)有大概了解。
本文是基于doc2vec的一个关于延禧攻略剧情文本的小demo。doc2vev基于word2vec,它俩很像,使用方法也很像。有空再把原理补上。

语料文本yxgltext.txt点这里下载,其实就是从百度上复制粘贴的前20集左右的剧情文字,大家可以随意更改语料文字。文件结构如下,记得下载yxgltext.txt

1
2
3
4
5
|-nlp //新建文件夹
|- doc2vec.py //新建python文件
|- data //新建文件夹
|- yxgltext.txt //下载语料数据放在data文件夹目录下
|- model //新建文件夹

Talk is cheap, show me the code! 上代码~~

输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

import os
os.chdir("C:/Users/Yi/Desktop/nlp") # nlp文件夹的路径

import jieba # 中文分词工具
import sys
import gensim
import sklearn
import numpy as np
from gensim.models.doc2vec import Doc2Vec, LabeledSentence #从gensim导入doc2vec
TaggededDocument = gensim.models.doc2vec.TaggedDocument

# 虚词,可以随意添加删除
stoplist = ['的','了','被','。',',','、','她','自己','他','并','和','都','去','\n']

输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

#进行中文分词
def cut_files():
filePath = 'data/yxgltext.txt'
fr = open(filePath, 'rb')
fvideo = open('data/yxglCut.txt', "w")

for line in fr.readlines():
curLine =' '.join(list(jieba.cut(line)))
fvideo.writelines(curLine)


#读取分词后的数据并打标记,放到x_train供后续索引,占用很大内存(供小数据量使用)
def get_datasest():
with open("data/yxglCut.txt", 'r') as cf:
docs = cf.readlines()

# 删除常用词
for idx in list(range(0,len(docs))):
docs[idx] = ' '.join([word for word in docs[idx].split( ) if word not in stoplist])
docs = [doc for doc in docs if len(doc)>0]
print(len(docs))

x_train = []
for i, text in enumerate(docs):
word_list = text.split(' ')
l = len(word_list)
word_list[l - 1] = word_list[l - 1].strip()
document = TaggededDocument(word_list, tags=[i])
x_train.append(document)

return x_train

#模型训练
def train(x_train, size=200, epoch_num=1): # size=200 意味着 每个词向量是200维的
# 使用 Doc2Vec 建模
model_dm = Doc2Vec(x_train, min_count=1, window=3, size=size, sample=1e-3, negative=5, workers=4)
#model_dm.train(x_train, total_examples=model_dm.corpus_count, epochs=70)
model_dm.save('model/model_dm_doc2vec')

return model_dm

#实例
def test():
# model_dm = Doc2Vec.load("model/model_dm_doc2vec")
test_text = ['我', '喜欢', '傅恒']
inferred_vector_dm = model_dm.infer_vector(test_text)

# 选取相关度最高的10个词
sims = model_dm.docvecs.most_similar([inferred_vector_dm], topn=10)
return sims

输入:

1
2
3
4
5
6
7
8
9
10
cut_files()
x_train=get_datasest()
model_dm = train(x_train)
sims = test()
for count, sim in sims:
sentence = x_train[count]
words = ''
for word in sentence[0]:
words = words + word + ' '
print (words, sim, len(sentence[0]))

输出:

1
2
3
娴妃 提议 让 从 江南 请来 名医 叶天士 为 五 阿哥 医治 皇上 应允 叶天士 肯定 五 阿哥 患 黄疸 保证 用退 黄方 就 可治好 弘历 松 口气 高 贵妃 见风使舵 向 皇上 告罪 皇上 表示 谅解 这时 纯妃 带 人 抬 此前 照料 愉 贵人 饮食 一名 蒙古 厨师 尸体 上来 了解 过愉 贵人 孕期 饮食习惯 后 叶天士 禀报 弘历 婴儿 瞳孔 金黄 怪病 多因 母体 湿热 胆汁 淤积 而生 孕妇 应当 注意 饮食 不过 分 食用 甜食 烫食 腥膻 之物 璎珞 意有 所指 是 高 贵妃 想 对付 愉 贵人 五 阿哥 高 贵妃 辩驳 纯妃 却 呈 上 证据 是 厨师 死前 留下 一封 指认 高 贵妃 血书 弘历 大为 恼火 软禁 高 贵妃 皇上 准备 离开 时 明玉 拦住 皇上 告发 璎珞 盗用 皇后 金印 璎珞 打开 匣子 里面 只是 一块 砚台 明玉因 诬告 而 受罚 随后 璎珞 拦住 纯妃 与 说话 指出 厨师 自尽 留下 血书 一事 是 策划 纯妃 提醒 璎珞 别站 错 队  0.17824654281139374 160
高 贵妃 巧妙 利用 这次 机会 对 皇上 诉说 衷肠 赢得 弘历 谅解 与此同时 皇后 在 长春 宫门 口苦 等 弘历 不至 深感 失望 次日 璎珞 在 御花园 发泄 心中 对 皇上 辜负 皇后 不满 遇到 傅恒 璎珞 向 替 皇后 鸣不平 出言不逊 傅恒 劝阻 随即 璎珞 因 百般 查探 姐姐 死因 却 一无所获 越发 焦躁 弘历 深夜 批阅 奏章 身体 不适 召 太医 前来 诊治 发现 患 疥疮 皇后 不顾 传染 危险 执意 要 搬入 养心殿 亲自 照料 弘历 原本 让 明玉 随行 可明玉 却 将 此 差 推 给 璎珞 璎珞 为了 调查 皇上 身边 亲信 查探 姐姐 真正 死因 于是 同意 跟 明玉 调换 差事 跟随 皇后 一道 搬 养心殿 璎珞 替 皇上 上药 皇上 十分 反感 拒绝 璎珞 可 李玉 粗手笨脚 弄 痛 皇上 皇上 恼怒 璎珞 告诉 皇上 养心殿 伺候 多半 是 太监 如果 坚持 那么 只好 请 皇后 来 替 上药 皇上 无奈 只好 让 璎珞 继续 皇上 涂 药 之后 依然 燥热 瘙痒 难耐 皇后 衣不解带 地 照顾 整整 一 晚上 璎珞 见状 十分 动容 璎珞 试探 李玉 询问 乾 清宫 夜宴 当晚 曾经 离席 宗室 可惜 一无所获 0.1443883627653122 185
...

输入:

1
print(model_dm.wv['璎珞'])

输出’璎珞’的200维词向量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[ 1.32339250e-03 -4.36101720e-04  8.61682580e-04 -5.60876098e-04
-1.10074517e-03 -4.01582598e-04 1.39182212e-05 1.03741838e-03
1.33155310e-03 4.53286630e-04 -1.02781062e-03 -8.92800104e-04
1.19402306e-03 -3.00986052e-04 -1.55415002e-03 -2.69316044e-03
1.58681255e-03 -8.10362690e-04 5.34354069e-04 -1.31634891e-03
-3.59648140e-03 2.49065284e-04 8.13953171e-04 -8.55766921e-05
2.76492530e-04 -1.29517284e-03 1.02521526e-03 8.73336976e-04
1.62727723e-03 -6.10298535e-04 -1.21042994e-03 -1.87295862e-03
-2.03051459e-04 -3.54788470e-04 1.25130301e-03 8.69541487e-04
-2.45160703e-03 -9.03088134e-04 5.02681173e-03 -1.03742653e-03
3.97383585e-04 1.10275706e-03 3.76813230e-04 -2.43625650e-03
3.11101991e-04 1.97053305e-03 2.52972008e-03 -1.45180838e-03
-1.74685894e-03 1.52873830e-03 4.81644034e-04 1.05112646e-04
2.67350441e-03 8.58452288e-04 6.63276296e-05 -1.97039312e-03
5.31882746e-04 -4.36584116e-04 1.26765005e-03 -3.08679766e-03
1.69386994e-03 -2.96112709e-03 2.48387340e-03 -3.73846688e-03
-3.07446043e-03 -4.49631305e-04 1.78120867e-03 -1.19638827e-03
-2.00018892e-03 -6.16657664e-04 1.24890637e-03 1.04953512e-03
6.38565107e-04 -8.65224341e-04 1.56678446e-03 2.29814858e-03
-4.69850667e-04 6.30659808e-04 2.44404143e-03 1.34824484e-03
-3.52538045e-04 2.64616770e-04 9.84614133e-04 -5.64393296e-04
-1.46174955e-03 2.11890996e-03 2.74263322e-04 -1.95100205e-03
2.42348132e-03 -4.13818937e-03 1.28919329e-03 -7.49823987e-04
3.59561713e-03 2.89021351e-04 1.64465397e-04 3.35634919e-04
6.11493131e-04 2.10861443e-03 6.76521973e-04 -1.72132370e-03
-9.39077465e-04 1.75529323e-03 -1.22920389e-03 2.14341236e-03
-2.19211495e-03 1.65924046e-03 2.23257625e-03 -2.71887379e-03
-3.23694688e-03 -2.48166034e-03 -3.01317009e-03 1.18382962e-03
3.18966959e-05 3.01953492e-04 2.36387877e-03 5.23283597e-05
1.89765415e-03 8.61766574e-04 -2.39132158e-03 -1.02647720e-03
-1.90407838e-04 5.11635910e-04 1.44841790e-03 2.69743241e-03
1.57171465e-03 -7.98581314e-05 -3.73520626e-04 2.92094832e-04
-7.90165941e-05 -1.03529333e-03 3.86003614e-03 2.65925983e-03
-9.42493731e-04 -2.91984412e-03 -8.32679973e-04 -6.22316380e-04
1.62830914e-03 1.41070038e-03 -1.05310581e-03 -4.29132691e-04
-3.38748004e-03 -2.14482704e-03 2.66522495e-03 -1.70672731e-03
2.21871235e-03 7.67852471e-04 -4.05522675e-04 3.69134732e-03
-2.68788106e-04 8.00681883e-04 1.98179367e-03 -1.21154217e-03
-7.56838883e-04 -9.01334104e-04 -2.56626052e-03 4.35368915e-04
7.19753269e-04 -2.40792311e-03 7.30484782e-04 -1.04375300e-04
1.82642520e-03 -1.83782264e-04 -2.16018991e-03 -1.67128816e-03
-3.14951874e-03 -1.74462073e-03 -3.66404653e-04 1.16418314e-03
2.36262940e-03 -7.21087854e-04 2.59639206e-03 -1.85696199e-03
7.52747059e-04 -1.90908764e-03 -2.16792268e-03 -2.83251936e-03
-1.03030400e-03 3.27490713e-03 4.00006247e-04 3.08081927e-03
-1.79204450e-03 1.68617186e-03 9.10512696e-04 1.23125815e-03
-1.02122920e-03 4.01859492e-04 -3.32432962e-03 9.13784548e-04
-2.05583894e-03 -2.35229125e-03 -8.21198220e-04 -6.70439913e-04
-1.70158059e-03 3.93540040e-03 1.72487774e-03 1.93191075e-03
2.05451762e-03 3.47349187e-03 -2.65299017e-03 -3.04736476e-03]

输入:

1
2
#可以用句向量模型直接根据词向量查询相似度
print (model_dm.wv.most_similar('璎珞'))

输出跟“璎珞”最相关的前10个词,以及相关系数:

1
2
3
4
5
6
7
8
9
10
[('庆锡', 0.36982783675193787), 
('答应', 0.30098065733909607),
('弘历', 0.29272472858428955),
('贵妃', 0.28584328293800354),
('发现', 0.2655611038208008),
('认定', 0.25713881850242615),
('不是', 0.2567000389099121),
('多多', 0.24867823719978333),
('又', 0.2475070059299469),
('利用', 0.2474854439496994)]

看完与“璎珞”强相关的词后,也可以尝试看看“傅恒”,“皇上”的相关词。(还是心疼傅恒😭)

“傅恒”的输出结果是:

1
2
3
4
5
6
7
8
9
10
[('谣言', 0.25737541913986206), 
('离开', 0.24646247923374176),
('涂', 0.23385187983512878),
('媚惑', 0.2333744615316391),
('是', 0.2153894603252411),
('借', 0.20425426959991455),
('却', 0.20283949375152588),
('璎珞', 0.20118796825408936),
('贵人', 0.19429181516170502),
('公道', 0.1942289024591446)]

语料库是前20集的内容,可以看下在前20集“傅恒”与“璎珞”的相关程度,输入:

1
print(model_dm.similarity('璎珞', '傅恒'))

输出:

1
0.23082738

同理输入看看与富察皇后和大猪蹄子的缘分:

1
2
print(model_dm.similarity('璎珞', '皇后'))
print(model_dm.similarity('璎珞', '皇上'))

查询字典的样子,输入:

1
print(model_dm.wv.vocab)

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{...
'傅恒所言': <gensim.models.keyedvectors.Vocab at 0x18391f309e8>,
'祥瑞': <gensim.models.keyedvectors.Vocab at 0x18391f5b438>,
'恒等': <gensim.models.keyedvectors.Vocab at 0x18391f30a58>,
'珍惜': <gensim.models.keyedvectors.Vocab at 0x18391f30a90>,
'出是': <gensim.models.keyedvectors.Vocab at 0x18391f6eb70>,
'置之不理': <gensim.models.keyedvectors.Vocab at 0x18391f5ba90>,
'立刻': <gensim.models.keyedvectors.Vocab at 0x18391f30b00>,
'自从': <gensim.models.keyedvectors.Vocab at 0x18391f30b38>,
'里面': <gensim.models.keyedvectors.Vocab at 0x18391f30ba8>,
'发抖': <gensim.models.keyedvectors.Vocab at 0x18391f30be0>,
'之巅': <gensim.models.keyedvectors.Vocab at 0x18391f30c18>,
'搬': <gensim.models.keyedvectors.Vocab at 0x18391f30c50>,
'对尔晴': <gensim.models.keyedvectors.Vocab at 0x18391f5e470>,
'心惊': <gensim.models.keyedvectors.Vocab at 0x18391f5e5f8>,
'我行我素': <gensim.models.keyedvectors.Vocab at 0x18391f6afd0>,
'途中': <gensim.models.keyedvectors.Vocab at 0x18391f30cf8>,
'三个': <gensim.models.keyedvectors.Vocab at 0x18391f30d30>,
'原来': <gensim.models.keyedvectors.Vocab at 0x18391f30d68>,
'保护': <gensim.models.keyedvectors.Vocab at 0x18391f30da0>,
'那尔布': <gensim.models.keyedvectors.Vocab at 0x1838cf9b5c0>,
'近身': <gensim.models.keyedvectors.Vocab at 0x18391f30e48>,
'名医': <gensim.models.keyedvectors.Vocab at 0x1838a970908>,
'嫁给': <gensim.models.keyedvectors.Vocab at 0x18391f30eb8>,
'盛世': <gensim.models.keyedvectors.Vocab at 0x18391f30ef0>,
'坠落': <gensim.models.keyedvectors.Vocab at 0x18391f30f28>,
'淤积': <gensim.models.keyedvectors.Vocab at 0x18391f74eb8>,
'隐患': <gensim.models.keyedvectors.Vocab at 0x18391f4b470>,
'进': <gensim.models.keyedvectors.Vocab at 0x18391f30f98>,
'侍奉': <gensim.models.keyedvectors.Vocab at 0x18391f54048>,
'迥异': <gensim.models.keyedvectors.Vocab at 0x18391f33080>,
...}

查询字典大小:

1
print(len(model_dm.wv.vocab))

同样,也可以把后面的剧情加进去,看看会发生什么变化😁

其余操作参考链接:

打赏2块钱,帮我买杯咖啡,继续创作,谢谢大家!☕~
0%