深度学习与自然语言处理第四次作业——词向量聚类问题

利用神经语言模型,训练词向量,通过对词向量的聚类或者其他方法来验证词向量的有效性。



一、解题背景

利用给定语料库(或者自选语料库),利用神经语言模型(如: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=1TP(w(t)w(tm),...,w(t1),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])


Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐