【NLP】Word2Vec模型文本分类

自然语言处理之词向量模型聚类分析

Word Embedding

词嵌入向量(Word Embedding)是NLP里面一个重要的概念,我们可以利用Word Embedding一个单词固定长度向量的表示一种表示形式。Word Embedding矩阵给每个单词分配一个固定长度的向量表示,这个长度可以自行设定,这个长度相对于one hot模型的词典长度维数上要小很多,但是却可以表示更多的信息,因为Word Embedding向量中每个维度都有含义。

Word2Vec

Word2Vec是生成Word Embedding的方式,Word2Vec有很对方法例如Continuous Bag Of Words (CBOW)Skip-gram等,本次作业中使用了CBOW模型。

NN

基于神经网络的分布表示又称为词向量、词嵌入,神经网络词向量模型与其它分布表示方法一样,均基于分布假说,核心依然是上下文的表示以及上下文与目标词之间的关系的建模。 2001年, Bengio 等人正式提出神经网络语言模型( Neural Network Language Model ,NNLM),该模型在学习语言模型的同时,也得到了词向量。

输入是One-Hot Vector,Hidden Layer没有激活函数,也就是线性的单元。Output Layer维度跟Input Layer的维度一样,用的是SoftMax回归。当这个模型训练好以后,我们并不会用这个训练好的模型处理新的任务,我们真正需要的是这个模型通过训练数据所学得的参数,例如隐层的权重矩阵。

这个模型是如何定义数据的输入和输出呢?一般分为CBOW与Skip-Gram两种模型。CBOW模型的训练输入是某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量。Skip-Gram模型和CBOW的思路是反着来的,即输入是特定的一个词的词向量,而输出是特定词对应的上下文词向量。CBOW对小型数据库比较合适,而Skip-Gram在大型语料中表现更好。

CBOW

而如果是拿一个词语的上下文作为输入,来预测这个词语本身,则是CBOW模型。

1 输入层:上下文单词的one hot. {假设单词向量空间dim为V,上下文单词个数为C}

2 所有one hot分别乘以共享的输入权重矩阵W. {VN矩阵,N为自己设定的数,初始化权重矩阵W}

3 所得的向量 {因为是one hot所以为向量} 相加求平均作为隐层向量, size为1N.

4 乘以输出权重矩阵W’ {NV}

5 得到向量 {1V} 激活函数处理得到V-dim概率分布

6 概率最大的index所指示的单词为预测出的中间词(target word)与true label的one hot做比较,误差越小越好(根据误差更新权重矩阵)

所以,需要定义loss function(一般为交叉熵代价函数),采用梯度下降算法更新W和W’。训练完毕后,输入层的每个单词与矩阵W相乘得到的向量的就是我们想要的词向量(word embedding),这个矩阵(所有单词的word embedding)也叫做look up table(就是矩阵W自身),也就是说,任何一个单词的one hot乘以这个矩阵都将得到自己的词向量。有了look up table就可以免去训练过程直接查表得到单词的词向量了。

Skip-gram

如果是用一个词语作为输入,来预测它周围的上下文,那这个模型叫做Skip-gram模型。

PCA

PCA(Principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据降维算法。PCA的主要思想是将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。

K-means

k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是,预将数据分为K组,则随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。

程序实现

运行环境

Anaconda 4.9.2

断句分词

'。' '\n'标点进行断句,删除标点,并用'\n'表示一句的结束,最后调用Jiaba库进行分词。

    def sepSentences(self):
        line = ''
        sentences_list = []

        for w in self.txt:
            if w in ['。', '\n'] and line != '\n':
                if line.strip() != '':
                    sentences_list.append(line.strip())
                    line = ''
            elif w not in self.punctuation:
                line += w

        self.sentences = sentences_list

    def sepWords(self):
        words_list = []

        dete_stopwords_flag = 1
        if dete_stopwords_flag:
            for i in range(len(self.sentences)):
                words_list.extend([x for x in jieba.cut(
                    self.sentences[i]) if x not in self.stopwords])
                words_list.append('\n')
        else:
            for i in range(len(self.sentences)):
                words_list.extend([x for x in jieba.cut(self.sentences[i])])
                words_list.append('\n')

        words_str = ' '.join(words_list)
        self.words = words_str

生成词向量

调用gensim库,读取断句分词后的保存的文件,转换为词向量。

    def train(self):
        self.sepSentences()
        self.sepWords()

        with open('./SentenceFile/' + self.txtname + '_句子.txt', 'w', encoding='UTF-8') as f2:
            f2.write(self.words)

        self.sent_iter = word2vec.LineSentence(
            './SentenceFile/' + self.txtname + '_句子.txt')
        self.model = word2vec.Word2Vec(self.sent_iter, workers=1)

主成分分析与聚类

调用Sklearn库中的PCA与K-means,对词向量进行主成分分析降温,聚类。

    keys = Character

    # 获取词向量
    wordvector = []
    for key in keys:
        wordvector.append(d.model.wv[key])

    # 降维
    wordvector_ = PCA(n_components=2).fit_transform(wordvector)

    # 分类
    labels_ = KMeans(n_clusters=4).fit_predict(wordvector_)

结果输出

    # 可视化
    plt.scatter(wordvector_[:, 0], wordvector_[:, 1], c=labels_)
    for i in range(len(keys)):
        plt.annotate(text=keys[i], xy=(
            wordvector_[:, 0][i], wordvector_[:, 1][i]))
    plt.show()

运行结果

测试用例

倚天屠龙记.txt

关键词

Character = ['张无忌', '赵敏', '谢逊', '周芷若', '张翠山', '杨逍', '灭绝师太', '张三丰', '殷离', '殷素素', '小昭', '殷梨亭',
             '韦一笑', '俞岱岩', '胡青牛', '宋远桥', '殷天正', '周颠', '纪晓芙', '宋青书', '杨不悔', '金花婆婆', '说不得',
             '范遥', '丁敏君', '陈友谅', '常遇春', '鹿杖客', '莫声谷', '鹤笔翁', '朱元璋', '阳顶天', '郭襄', '成昆', '空见',
             '冷谦','彭莹玉']
Kungfu = ['太极拳', '太极剑', '真武七截阵', '九阳神功', '峨嵋九阳功', '少林九阳功', '乾坤大挪移', '九阴真经', '九阴白骨爪',
          '七伤拳', '九阳真经', '玄冥神掌']
sect = ['明教', '峨嵋派', '天鹰教', '昆仑派', '崆峒派', '武当派', '少林派', '神拳门', '华山派']

输出相近词

    # 查找相近的词
    for key in d.model.wv.similar_by_word('张无忌', topn=10):
        print(key[0], key[1])

与张无忌关系比较近的词:

赵敏 0.9944162368774414
殷素素 0.9893664717674255
张翠山 0.9883266091346741
谢逊 0.9879009127616882
低声 0.9870488047599792
周芷若 0.9858320355415344
无忌 0.9820763468742371
罢 0.9808448553085327
微笑 0.976464569568634
周颠 0.9755969047546387

比较相似度

    # 两词相近程度
    print(d.model.wv.similarity('武当', '张三丰'))

比较武当与张三丰的相近度:

0.9800525

输出聚类结果

可以大致从中看出其中人物关系,例如张无忌与赵敏、张翠山、殷素素、周芷若关系较近,玄冥二老的鹿仗客与鹤笔翁关系较近。

人物关系:
在这里插入图片描述

武功关系:
在这里插入图片描述

门派关系:
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值