深度学习与自然语言处理第四次作业——词向量聚类问题
利用神经语言模型,训练词向量,通过对词向量的聚类或者其他方法来验证词向量的有效性。
文章目录
一、解题背景
利用给定语料库(或者自选语料库),利用神经语言模型(如:Word2Vec, GloVe等模型)来训练词向量,通过对词向量的聚类或者其他方法来验证词向量的有效性。
二、解题原理
1、词向量
自然语言处理相关任务中要将自然语言交给机器学习中的算法来处理,通常需要将语言数学化,因为机器不是人,机器只认数学符号。向量是人把自然界的东西抽象出来交给机器处理的东西,基本上可以说向量是人对机器输入的主要方式了。
词向量就是用来将语言中的词进行数学化的一种方式,顾名思义,词向量就是把一个词表示成一个向量。 我们都知道词在送到神经网络训练之前需要将其编码成数值变量,常见的编码方式有两种:One-Hot Representation 和 Distributed Representation。
2、Word2Vec模型原理
Word2vec,是一群用来产生词向量的相关模型。这些模型为浅而双层的神经网络,用来训练以重新建构语言学之词文本。网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模型假设下,词的顺序是不重要的。训练完成之后,word2vec模型可用来映射每个词到一个向量,可用来表示词对词之间的关系,该向量为神经网络之隐藏层。
Word2Vec主要包括CBOW模型(连续词袋模型)和Skip-gram模型(跳字模型)
本文主要使用的模型为CBOW模型, 给定一个长度为
T
T
T的文本序列,设时间步的词为
W
(
t
)
W(t)
W(t),背景窗口大小为
m
m
m。则连续词袋模型的目标函数(损失函数)是由背景词生成任一中心词的概率。
∑
t
=
1
T
P
(
w
(
t
)
∣
w
(
t
−
m
)
,
.
.
.
,
w
(
t
−
1
)
,
w
(
t
+
1
)
,
.
.
.
,
w
(
t
+
m
)
)
\sum_{t=1}^{T}P(w^{(t)}|w^{(t-m)},...,w^{(t-1)},w^{(t+1)},...,w^{(t+m)})
t=1∑TP(w(t)∣w(t−m),...,w(t−1),w(t+1),...,w(t+m))
三、实验分析
1.语料处理
在读取语料后,首先利用jieba分词对语料进行分词,去掉txt文本中一些无意义的广告和标点符号等内容,并将处理后的语料重新保存进新的文件夹中。
在实验过程中,注意到某些无关词语会在结果中出现,因此在进行语料处理时,去掉一些无关词语(例如,“我”、“你”、“他”、“她”、“它”等)
代码如下(语料处理):
def read_novel(path_in, path_out): # 读取语料内容
content = []
names = os.listdir(path_in)
for name in names:
novel_name = path_in + '\\' + name
fenci_name = path_out + '\\' + name
for line in open(novel_name, 'r', encoding='ANSI'):
line.strip('\n')
line = re.sub("[A-Za-z0-9\:\·\—\,\。\“\”\\n \《\》\!\?\、\...]", "", line)
line = content_deal(line)
con = jieba.cut(line, cut_all=False) # 结巴分词
# content.append(con)
content.append(" ".join(con))
with open(fenci_name, "w", encoding='utf-8') as f:
f.writelines(content)
return content, names
def content_deal(content): # 语料预处理,进行断句,去除一些广告和无意义内容
ad = ['本书来自www.cr173.com免费txt小说下载站\n更多更新免费电子书请关注www.cr173.com', '----〖新语丝电子文库(www.xys.org)〗', '新语丝电子文库',
'\u3000', '\n', '。', '?', '!', ',', ';', ':', '、', '《', '》', '“', '”', '‘', '’', '[', ']', '....', '......',
'『', '』', '(', ')', '…', '「', '」', '\ue41b', '<', '>', '+', '\x1a', '\ue42b', '她', '他', '你', '我', '它', '这'] #去掉其中的一些无意义的词语
for a in ad:
content = content.replace(a, '')
return content
2.模型训练
使用开源的Gensim库提供的接口来训练Word2vec模型,调用的函数如下:
Word2Vec(sentences=LineSentence(name), hs=1, min_count=10, window=5, vector_size=200, sg=0, epochs=200)
其中的参数的含义为:
- sentences:可以是一个list,对于大语料集,建议使用BrownCorpus,Text8Corpus或LineSentence构建;
- hs: 如果为1则会采用hierarchical softmax技巧。如果设置为0(defaut),则negative sampling会被使用;
- min_count: 可以对字典做截断,词频少于min_count次数的单词会被丢弃掉, 默认值为5,这里的值为10。
- window:表示当前词与预测词在一个句子中的最大距离是多少,这里为5;
- vector_size:是指特征向量的维度,默认为100;
- sg: 用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法;
- epochs:迭代次数,默认为5。这里的参数不是iter,官方在新的版本中将这个关键词改为了epochs,使用iter会报错。
3、聚类分析
模型训练完毕之后,通过Gensim库中给出的接口函数(例如,most_similar(),similarity()等),输出训练之后的模型,与某个给定输入词关联度最高的词或者是给定的某两个词之间的关联性。
我选择了金庸小说集中我较为了解的五本小说《倚天屠龙记》、《天龙八部》、《射雕英雄传》、《神雕侠侣》、《笑傲江湖》作为样本,对其中的主角、门派分别进行了聚类分析。
代码如下(聚类分析):
if __name__ == '__main__': ##
[data_txt, files] = read_novel("金庸小说集", "output")
#[data_txt, files] = read_novel("倚天屠龙记", "output")
#model = Word2Vec(data_txt, vector_size=400, window=5, min_count=5, epochs=200, workers=multiprocessing.cpu_count())
test_name = ['张无忌', '乔峰', '郭靖', '杨过', '令狐冲', '韦小宝']
#test_name = ['张无忌']
test_menpai = ['明教', '逍遥派', '少林', '全真教', '华山派', '少林']
for i in range(0, 5):
name = "output/" + files[i]
print(name)
model = Word2Vec(sentences=LineSentence(name), hs=1, min_count=10, window=5, vector_size=200, sg=0, epochs=200)
for result in model.wv.similar_by_word(test_name[i], topn=10):
print(result[0], result[1])
for result in model.wv.similar_by_word(test_menpai[i], topn=10):
print(result[0], result[1])
四、实验结果
1、《倚天屠龙记》
张无忌 | 关联度 |
---|---|
周芷若 | 0.511336 |
张翠山 | 0.463939 |
谢逊 | 0.412231 |
赵敏 | 0.403387 |
宋青书 | 0.392989 |
金花婆婆 | 0.37242 |
朱长龄 | 0.364297 |
鹿杖客 | 0.357451 |
殷素素 | 0.346302 |
了张无忌 | 0.346121 |
张无忌跟周芷若是青梅竹马,父亲为张翠山,义父为谢逊,后来跟赵敏在一起,宋青书是张无忌的师哥,金花婆婆是明教的紫衫龙王,也是小昭的母亲,也是与张无忌相关。
明教 | 关联度 |
---|---|
本教 | 0.415993 |
魔教 | 0.319323 |
从来不 | 0.275328 |
教 | 0.262971 |
僧侣 | 0.253044 |
报仇 | 0.248239 |
船只 | 0.245379 |
峨嵋派 | 0.244295 |
贵教 | 0.243198 |
明教之 | 0.238621 |
明教常自称本教,也常被六大门派叫做魔教。
2、《天龙八部》
段誉 | 关联度 |
---|---|
萧峰 | 0.564757 |
段正淳 | 0.472794 |
慕容复 | 0.459998 |
段誉 | 0.438487 |
游坦之 | 0.427203 |
王语嫣 | 0.417367 |
鸠摩智 | 0.391007 |
徐长老 | 0.37959 |
钟夫人 | 0.357237 |
阿朱 | 0.352062 |
段誉的结拜大哥是萧峰,父亲为段正淳,慕容复是对头,这些都是跟他相关的人。
逍遥派 | 关联度 |
---|---|
苏星河 | 0.338742 |
无崖子 | 0.332658 |
童姥 | 0.266579 |
虚竹 | 0.250159 |
丁春秋 | 0.247675 |
武学上 | 0.247264 |
小僧 | 0.242177 |
波罗星 | 0.239409 |
姥姥 | 0.237926 |
般若 | 0.232889 |
逍遥派的掌门是无崖子,首徒是苏星河,天山童姥是逍遥派前任掌门逍遥子的大弟子,虚竹后来加入了逍遥派,丁春秋之前也是逍遥派弟子。
3、《射雕英雄传》
郭靖 | 关联度 |
---|---|
黄蓉 | 0.754457 |
洪七公 | 0.689884 |
欧阳克 | 0.683156 |
欧阳锋 | 0.658934 |
裘千仞 | 0.606486 |
黄药师 | 0.597743 |
周伯通 | 0.573734 |
完颜康 | 0.561691 |
梅超风 | 0.534767 |
丘处机 | 0.522161 |
郭靖的老婆是黄蓉,师傅是洪七公,跟上述的人都有交集。
少林 | 关联度 |
---|---|
昆仑 | 0.582904 |
星宿 | 0.576276 |
六大 | 0.558112 |
全真 | 0.554336 |
崆峒 | 0.532443 |
海沙 | 0.508429 |
蓬莱 | 0.496702 |
大门 | 0.438703 |
青海 | 0.431732 |
污衣 | 0.425564 |
跟少林相关的都是一些其他门派。
4、《神雕侠侣》
杨过 | 关联度 |
---|---|
小龙女 | 0.728308 |
李莫愁 | 0.685839 |
黄蓉 | 0.664348 |
郭靖 | 0.641764 |
陆无双 | 0.640486 |
法王 | 0.619647 |
赵志敬 | 0.589013 |
周伯通 | 0.57856 |
公孙止 | 0.555143 |
洪七公 | 0.554223 |
杨过的姑姑也是小龙女,跟其他的人也有一些交集关系。
全真教 | 关联度 |
---|---|
赵志敬 | 0.354839 |
丘道长 | 0.337257 |
重阳 | 0.334504 |
全真 | 0.294923 |
丘处机 | 0.287868 |
北斗 | 0.279528 |
王重阳 | 0.278343 |
打架 | 0.276295 |
王处一 | 0.27136 |
孙婆婆 | 0.265189 |
全真教相关的都是全真教里面相关的人以及跟全真教相关的门派。
5、《笑傲江湖》
令狐冲 | 关联度 |
---|---|
岳不群 | 0.778345 |
林平之 | 0.725633 |
岳灵珊 | 0.700197 |
田伯光 | 0.680995 |
仪琳 | 0.67232 |
岳夫人 | 0.66513 |
盈盈 | 0.626171 |
向问天 | 0.613704 |
任行 | 0.593848 |
张无忌 | 0.589727 |
与令狐冲相关的是他的师傅、师弟、师妹等人,其余人都是与令狐冲有交集的人。有意思的是,在最后与令狐冲相关的人中,出现了张无忌。具体分析结果见实验分析。
华山派 | 关联度 |
---|---|
青城派 | 0.560951 |
华山 | 0.504883 |
本派 | 0.448503 |
武当派 | 0.434742 |
嵩山 | 0.432196 |
岳不群 | 0.426482 |
恒山 | 0.422759 |
本门 | 0.418473 |
峨嵋派 | 0.408812 |
青城 | 0.404923 |
与华山派相关的都是一些门派,其中岳不群是华山派的掌门。
五、实验分析
本次实验针对金庸先生的五本小说《倚天屠龙记》、《天龙八部》、《射雕英雄传》、《神雕侠侣》、《笑傲江湖》作为样本,对其中的主角、门派分别进行了聚类分析。
- 实验结果如上所示,其中人物与门派的关联度均较高,符合小说的实际情况。
- 但在针对《笑傲江湖》中的令狐冲的人物关联度分析时,出现了张无忌。对这种情况进行分析之后,考虑原因,可能是模型构建中出现问题,在模型构建时,应将每本小说的模型分开,本实验中未分开每本小说的模型。张无忌跟令狐冲都是两部小说的主角,他们的共同点都是与门派、少年英雄、学会了绝世武功等。因此作者金庸,可能在两个人物塑造时,人物语气、人物描述部分存在相似部分,因此分析出令狐冲与张无忌的关联度。
附录
实验全部代码如下所示:
实验代码参考前人
import math
import jieba
import os # 用于处理文件路径
import re
import sys
import random
import numpy as np
import multiprocessing
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
def read_novel(path_in, path_out): # 读取语料内容
content = []
names = os.listdir(path_in)
for name in names:
novel_name = path_in + '\\' + name
fenci_name = path_out + '\\' + name
for line in open(novel_name, 'r', encoding='ANSI'):
line.strip('\n')
line = re.sub("[A-Za-z0-9\:\·\—\,\。\“\”\\n \《\》\!\?\、\...]", "", line)
line = content_deal(line)
con = jieba.cut(line, cut_all=False) # 结巴分词
# content.append(con)
content.append(" ".join(con))
with open(fenci_name, "w", encoding='utf-8') as f:
f.writelines(content)
return content, names
def content_deal(content): # 语料预处理,进行断句,去除一些广告和无意义内容
ad = ['本书来自www.cr173.com免费txt小说下载站\n更多更新免费电子书请关注www.cr173.com', '----〖新语丝电子文库(www.xys.org)〗', '新语丝电子文库',
'\u3000', '\n', '。', '?', '!', ',', ';', ':', '、', '《', '》', '“', '”', '‘', '’', '[', ']', '....', '......',
'『', '』', '(', ')', '…', '「', '」', '\ue41b', '<', '>', '+', '\x1a', '\ue42b', '她', '他', '你', '我', '它', '这'] #去掉其中的一些无意义的词语
for a in ad:
content = content.replace(a, '')
return content
if __name__ == '__main__': ##
[data_txt, files] = read_novel("金庸小说集", "output")
#[data_txt, files] = read_novel("倚天屠龙记", "output")
#model = Word2Vec(data_txt, vector_size=400, window=5, min_count=5, epochs=200, workers=multiprocessing.cpu_count())
test_name = ['张无忌', '乔峰', '郭靖', '杨过', '令狐冲', '韦小宝']
#test_name = ['张无忌']
test_menpai = ['明教', '逍遥派', '少林', '全真教', '华山派', '少林']
for i in range(0, 5):
name = "output/" + files[i]
print(name)
model = Word2Vec(sentences=LineSentence(name), hs=1, min_count=10, window=5, vector_size=200, sg=0, epochs=200)
for result in model.wv.similar_by_word(test_name[i], topn=10):
print(result[0], result[1])
for result in model.wv.similar_by_word(test_menpai[i], topn=10):
print(result[0], result[1])