关于对词向量的一个小结

在用深度学习处理自然语言的过程中,必然会用到词向量,用google的word2vec工具可以很容易地生成词向量。可是,具体这其中的原理是什么呢?在这里从简单到复杂以问答的形式做一个总结。

什么是词向量呢?
很简单,顾句思义,就是把词用向量的形式表示出来。

为什么说用深度学习处理自然语言时,就要用到词向量呢?
这个也很容易理解,既然涉及到计算,那么就自然要用到数了,你总不能直接将一段文字输到算法里,然后期望算法明白你输入的是啥吧。图像要转换为数字,那么语言也要转换成数字。

那怎么把词转化为数字呢?
这不是很简单的事么,直接将词和数一一对就不就好了。比如我有三个词A, B, C,将它们分别编号成1, 2,3就行啦,那每个词就可以用数字来表示啦。

经常听说 One-hot Representation,这到底是什么?
有了上面的那一步,我们就可以把数字转化为向量了。所谓one-hot,就是说一个向量里只有一个值为1,其它的都是0。这样一来就有如下的表示:
A [1,0,0]
B [0,1,0]
C [0,0,1]
如此一来,我们就可以用一个二维矩阵来表示任意的一句话了。矩阵的大小为(句子中词的个数,词典中词的个数)

词向量真的这么简单吗?
不是的。现在我们一般都不用one-hot的表示方法啦。这个方法为什么不好呢?因为它仅仅是一个词与向量的映射关系。我们知道词与词之前是有各种各样的关系的,但是one-hot向量之间都是相互垂直的关系,并没有体现出词之间的关系来。所以我们希望用一种新的方式来将词变成词向量,使得向量之间的关系也体现相应的词之间的关系。因此我们希望将词向量训练地更有‘意义’些。

Continuous Bag of Words (CBOW) 和Skip-gram又是什么呢?和词向量又有什么关系?
在CBOW(连续词袋模型)方法中,目的是将文章中某个词的上下文经过模型预测该词。而Skip-gram(跳词模型)方法则是用给定的词来预测其周边的词。而词向量是在训练模型中所得到的一个副产品,此模型在源码中是为一个浅层的神经网络(3层)。

简单地说,首先随机初始化词向量,然后我们给模型‘看’大量的上下文-词汇的对子,模型再调整词向量。最后给模型‘喂’了各种各样的对子之后,我们的词向量就有‘意义’了。

以上讲的比较抽像,下面以CBOW为例具体地讲讲:
我们现在有一句话,La France est loin de la Chine,设置上下文的窗口为2,那么针对这句话而言,输入输出对有:
输入, 输出
la , France
la , est
France , la
France , est
France , loin
est , France
est , la
est , loin
est , de

也就是说,每次以其中一个词作为输入,此词的左右两个单词中的一个为输出,直到把所有的可能配对都做完。

具体的输入输出形式以及中间过程又是什么样的呢?
首先定义一个你最后想要的词向量的维度,假设为3。以上面的句子为例,定义我们的词典大小为6, 输入以one-hot为形式,那么是一个(1,6)的向量。经过一个大小为(6,3)的W参数矩阵后, 我们的单词就变成了(1, 3)。而最后的输出我们需要的是生成词典中每个词的概率是多少,相当于一个多分类问题,输出的向量大小为(1,6)。所以在输出之前还应有一个大小为(3,6)的参数矩阵。
那训练完这个模型后,我们的词向量在哪呢?其实就是W参数矩阵啦。

说起来好像挺简单,但是实际应用中,词汇量是很大的,比如现在在100000个词,想要一个128维的词向量,那么就有2*100000*128个参数。每一次的训练都要做softmax以及BP,这样训练起来计算开销就太大啦。

所以要怎么解决这个问题呢?
提出这个模型的作者给出了三种减少计算量的方案:
对高频次单词进行抽样来减少训练样本的个数。根据皮雅夫定律,其实常见的词在总的数据库中频次是很高的,所以减少一些高频词的训练词数,将极大地减少总训练次数。
对优化目标采用“negative sampling”方法,这样每个训练样本的训练只会更新一小部分的模型权重,从而降低计算负担。
Hierarchical softmax(这种方法还不懂,先不详细说了。)
对于这一部分,推荐一个视频:https://www.bilibili.com/video/av10812680?spm_id_from=333.338.__bofqi.19

大概了解了一些基本原理,那具体怎么应用呢?
下面以python中gensim中word2vec工具为例,展示一下具体怎么用自己的数据来训练词向量。
大概流程十分简单,首先把需要用来训练的数据转化为word2vec所要求的输入格式;然后调用word2vec工具并设置参数,词向量的维度,窗口的大小, 所训练的词的最少出现次数, 线程个数;之后就可以调用保存好的模型,并进行你想要的操作了,比如查找某个词的向量,查看两个词之间的相似度,查找与某个词相似的词,或者还可以加入新的数据继续进行词向量的训练。

#encoding=utf-8

import csv
import random
from gensim.models import word2vec
import re


def w2v(filepath):

    with open(filepath, 'r', encoding='utf8')as f:
        lines = f.readlines()
        sens = [line.strip().split(' ') for line in lines]
    #create word2vec model, each word has a size of 132
    model = word2vec.Word2Vec(sens, size = 132, window = 5, min_count = 1, workers = 10)
    model.save('w2v_smalldata')

def evaluation(model_path):
    model = word2vec.Word2Vec.load(model_path)
    print(model['盗窃'])

if __name__ == '__main__':
    w2v('data_train_after.txt')
    evaluation('w2v_smalldata')
    listVal = []
    for i in range(1):
        listVal.append([0]*10)
    print(listVal)

这次只是一个简单的总结,主要参考资料为:
https://www.leiphone.com/news/201706/PamWKpfRFEI42McI.html
https://www.bilibili.com/video/av18512944?from=search&seid=14457894643818070881
下次有时间了再阅读原文献或者原倾做一个深入的了解。

猜你喜欢

转载自blog.csdn.net/weixin_42936560/article/details/81707014