word2vector总结与理解

  • 1. 目前成熟的Word2Vector
    • 1.1. English Pre-trained word embeddings
    • 1.2 Chinese Pre-trained word embeddings
  • 2. one_hot编码
    • 2.1. 简单对比
    • 2.2.优势分析:
    • 2.3. 缺点分析:
  • 3. 什么是word2vector?
  • 4. word2vector怎么做
    • 4.1. Skip-Gram& CBOW
    • 4.2. word2vector
    • 4.3. 模型细节
    • 4.4. 隐层
    • 4.5. 输出层
  • 5. 直觉上的理解
  • 6. Skip-Gram 代码实现
  • 什么是ELMO、BERT、GPT



N-Gram 模型

两个RNN–翻译, Encoder 和decoder. 中间是Context vector

1. 目前成熟的Word2Vector

1.1. English Pre-trained word embeddings

  1. Google’s word2vec embedding:
    外网地址: [ Word2Vec] [ DownloadLink]
    300维英语词向量: [ 百度云]

  2. Glove word vectors:
    外网地址: [Glove]
    国内地址: [百度云]

  3. Facebook’s fastText embeddings:
    外网地址:[FastText]
    国内地址:[百度云]

  4. FastText Crawl:
    https://pan.baidu.com/s/1NPlqAOnX1k88VictTshVMQ
    [DeepMoji]: To understand how language is used to express emotions

1.2 Chinese Pre-trained word embeddings

目前最全的
https://github.com/Embedding/Chinese-Word-Vectors
https://github.com/to-shimo/chinese-word2vec

2. one_hot编码

首先,了解下什么是one_hot编码,直接举例子如下:
词库

我   从   哪   里   来   要   到   何   处  去
0    1    2    3   4    5   6    7    8   9

__one_hot编码__如下:

# 我从哪里来,要到何处去
[
[1 0 0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0 1 0]
[0 0 0 0 0 0 0 0 0 1]
]# 我从何处来,要到哪里去
[
[1 0 0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0 1 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1]
]

one_hot编码后,一个句子可以用一个矩阵表示,出现在词库中的词对应在矩阵中位置为1

2.1. 简单对比

one_hot编码之前使用列表(一维)表达一个句子
one_hot编码之后使用矩阵(二维)表达一个句子

2.2.优势分析:

  1. 稀疏矩阵做矩阵计算的时候,只需要把1对应位置的数相乘求和就行,
  2. one-hot编码的优势就体现出来了,计算方便快捷、表达能力强

2.3. 缺点分析:

  1. 过于稀疏时,过度占用资源
    比如:中文大大小小简体繁体常用不常用有十几万,然后一篇文章100W字,要表达所有句子,需要100W X 10W的矩阵
  2. 每个向量之间相互正交的(内积为0)。向量正交意味着无相关性,这也正交意味着词与词之间是没有任何关系的。
  3. 每个词的向量维度和不同词的个数有关。比方说,在上面的这个句子里,有5个不同的词,所以向量的维度是5。然而往往实际应用中,一篇文章的中不同的词的个数是很多的。这样,向量的维度会非常的高

3. 什么是word2vector?

我们先来看一个问题,假如有一个句子 " the dog bark at the mailman"。
假如用向量来表示每个单词,我们最先想到的是用one hot 编码的方式来表达每个单词,具体来说。
the 可以表示为 [1,0,0,0,0]
dog 可以表示为 [0,1,0,0,0]
bark 可以表示为 [0,0,1,0,0]
at 可以表示为[0,0,0,1,0]
mailman可以表示为[0,0,0,0,1]

我们可以看到每个单词其实就用一个向量来表示。我们发现几个问题:
第一,每个向量之间相互正交的(内积为0)。也就是说词与词之间是没有任何关系的。
第二,每个词的向量维度和不同词的个数有关。比方说,在上面的这个句子里,有5个不同的词,所以向量的维度是5。然而往往现实中,一篇文章的中不同的词的个数是很多的。这样,向量的维度会非常的高。
这种对词的向量表示方法存在着以上的问题,忽略了词与词之间的关系(比如说,dog和cat都是动物,并非完全无关系)。维度太高的向量作为模型输入会导致模型变的复杂(模型复杂需要更多的训练样本才能够收敛)

那么是否存在一种更加合理的对词的用向量的表达方式呢?有的,其实就是word embedding。
word embedding说的简单一点其实就是将高维稀疏的向量降维成稠密的低维向量。(一种高维到低维的映射)

那么如和实现word embedding?
w2v其实就是一种高效实现word embedding的工具
所以,如果用一句话来描述word2vector的话你会怎么描述?简单的说,我觉得可以这么说w2v其实是一种将单词转化向量的工具。这一种向量的其实是对单词更有效的表达

4. word2vector怎么做

下面总结一下word2vector主要的思想

4.1. Skip-Gram& CBOW

在介绍w2v模型之前,先介绍两个模型。一个是Skip-Gram和CBOW(Continuous Bag-of-Words)。首先看CBOW,它的做法是,将一个词所在的上下文中的词作为输入,而那个词本身作为输出。

来看Skip-Gram,它的做法和CBOW相反,将一个词所在的上下文中的词作为输出,而词本身作为输入。


(下面有例子说明)另外,我们介绍这两个模型都会涉及到的一个重要参数。

window_size:窗口大小。举一个例子,还是上面那句话:" the dog bark at the mailman"。假设window_size取1时,利用CBOW模型可以得到:

([the,bark],dog)

([dog,at],bark)

([bark,the],at)

([at,mailman],the)

一共4组数据。同样的,假设window_size还是1,利用Skip-Gram模型可以得到:

(dog,[the,bark])

(bark,[dog,at])

(at,[bark,the])

(the,[at,mailman])

对于每组数据会稍微做一下处理。比如对于第一组 (dog,[the,bark])一般处理成

(dog,the),(dog,bark)。

类似有:

(bark,dog),(bark,at),(at,bark),(at,the),(the,at),(the,mailman)共8组数据。

下面的图中给出了一些我们的训练样本的例子。我们选定句子“The quick brown fox jumps over lazy dog”,设定我们的窗口大小为2(window_size=2),也就是说我们仅选输入词前后各两个词和输入词进行组合。下图中,蓝色代表input word,方框内代表位于窗口内的单词。

我们的模型将会从每对单词出现的次数中习得统计结果。例如,我们的神经网络可能会得到更多类似(“Soviet“,”Union“)这样的训练样本对,而对于(”Soviet“,”Sasquatch“)这样的组合却看到的很少。因此,当我们的模型完成训练后,给定一个单词”Soviet“作为输入,输出的结果中”Union“或者”Russia“要比”Sasquatch“被赋予更高的概率。

4.2. word2vector

下面就可以直接介绍如何进行w2v,上面提到w2v可以看作是一个将高维空间映射到低维空间的过程,用一个单层神经网络就可以实现这种功能(和自编码器有点类似其实)。对于CBOW,假如还是上面的句子" the dog bark at the mailman",训练数据是([the,brak],dog)那么网络的输入输出如下图所示:

这里有几个细节:

(1).上面介绍CBOW模型的时有一个模型的结构图,其中的SUM意思其实就是把各个上下文的词one-hot后的向量相加。比如对于the的向量是[1,0,0,0,0]。bark向量是[0,0,1,0,0],SUM之后就是[1,0,1,0,0]这就是网络的输入。输出就是[0,1,0,0,0],对应-dog

(2).我们所谓的embedding vetcor其实就第二个红框里的线,每一根线其实就是一个权值。

(3).第二个框里的红线其实就是dog这个单词的embedding结果(由5维变成3维)

(4).这个单层NN训练完毕之后有用的部分就是embedding martrix这部分,其大小为 输入个数(词汇表长度)×embedding后的维度。

类似对于Skip-Gram模型有:


当取训练数据(dog,bark)时,网络结构如上图,对比上面的CBOW最大的不同其实就是在于输入数据。

4.3. 模型细节

我们如何来表示这些单词呢?首先,我们都知道神经网络只能接受数值输入,我们不可能把一个单词字符串作为输入,因此我们得想个办法来表示这些单词。最常用的办法就是基于训练文档来构建我们自己的词汇表(vocabulary)再对单词进行one-hot编码。

假设从我们的训练文档中抽取出10000个唯一不重复的单词组成词汇表。我们对这10000个单词进行one-hot编码,得到的每个单词都是一个10000维的向量,向量每个维度的值只有0或者1,假如单词ants在词汇表中的出现位置为第3个,那么ants的向量就是一个第三维度取值为1,其他维都为0的10000维的向量(ants=[0, 0, 1, 0, …, 0])。

还是上面的例子,“The dog barked at the mailman”,那么我们基于这个句子,可以构建一个大小为5的词汇表(忽略大小写和标点符号):(“the”, “dog”, “barked”, “at”, “mailman”),我们对这个词汇表的单词进行编号0-4。那么”dog“就可以被表示为一个5维向量[0, 1, 0, 0, 0]。

模型的输入如果为一个10000维的向量,那么输出也是一个10000维度(词汇表的大小)的向量,它包含了10000个概率,每一个概率代表着当前词是输入样本中output word的概率大小。

下图是我们神经网络的结构:

隐层没有使用任何激活函数,但是输出层使用了sotfmax。

我们基于成对的单词来对神经网络进行训练,训练样本是 ( input word, output word ) 这样的单词对,input word和output word都是one-hot编码的向量。最终模型的输出是一个概率分布。

4.4. 隐层

说完单词的编码和训练样本的选取,我们来看下我们的隐层。如果我们现在想用300个特征来表示一个单词(即每个词可以被表示为300维的向量)。那么隐层的权重矩阵应该为10000行,300列(隐层有300个结点)。

Google在最新发布的基于Google news数据集训练的模型中使用的就是300个特征的词向量。词向量的维度是一个可以调节的超参数(在Python的gensim包中封装的Word2Vec接口默认的词向量大小为100, window_size为5)。

看下面的图片,左右两张图分别从不同角度代表了输入层-隐层的权重矩阵。左图中每一列代表一个10000维的词向量和隐层单个神经元连接的权重向量。从右边的图来看,每一行实际上代表了每个单词的词向量。

所以我们最终的目标就是学习这个隐层的权重矩阵。

我们现在回来接着通过模型的定义来训练我们的这个模型。

上面我们提到,input word和output word都会被我们进行one-hot编码。仔细想一下,我们的输入被one-hot编码以后大多数维度上都是0(实际上仅有一个位置为1),所以这个向量相当稀疏,那么会造成什么结果呢。如果我们将一个1 x 10000的向量和10000 x 300的矩阵相乘,它会消耗相当大的计算资源,为了高效计算,它仅仅会选择矩阵中对应的向量中维度值为1的索引行(这句话很绕),看图就明白。

我们来看一下上图中的矩阵运算,左边分别是1 x 5和5 x 3的矩阵,结果应该是1 x 3的矩阵,按照矩阵乘法的规则,结果的第一行第一列元素为0 x 17 + 0 x 23 + 0 x 4 + 1 x 10 + 0 x 11 = 10,同理可得其余两个元素为12,19。如果10000个维度的矩阵采用这样的计算方式是十分低效的。

为了有效地进行计算,这种稀疏状态下不会进行矩阵乘法计算,可以看到矩阵的计算的结果实际上是矩阵对应的向量中值为1的索引,上面的例子中,左边向量中取值为1的对应维度为3(下标从0开始),那么计算结果就是矩阵的第3行(下标从0开始)—— [10, 12, 19],这样模型中的隐层权重矩阵便成了一个”查找表“(lookup table),进行矩阵计算时,直接去查输入向量中取值为1的维度下对应的那些权重值。隐层的输出就是每个输入单词的“嵌入词向量”

4.5. 输出层

经过神经网络隐层的计算,ants这个词会从一个1 x 10000的向量变成1 x 300的向量,再被输入到输出层。输出层是一个softmax回归分类器,它的每个结点将会输出一个0-1之间的值(概率),这些所有输出层神经元结点的概率之和为1。

下面是一个例子,训练样本为 (input word: “ants”, output word: “car”) 的计算示意图。

5. 直觉上的理解

下面我们将通过直觉来进行一些思考。

如果两个不同的单词有着非常相似的“上下文”(也就是窗口单词很相似,比如“Kitty climbed the tree”和“Cat climbed the tree”),那么通过我们的模型训练,这两个单词的嵌入向量将非常相似。

那么两个单词拥有相似的“上下文”到底是什么含义呢?比如对于同义词“intelligent”和“smart”,我们觉得这两个单词应该拥有相同的“上下文”。而例如”engine“和”transmission“这样相关的词语,可能也拥有着相似的上下文

实际上,这种方法实际上也可以帮助你进行词干化(stemming),例如,神经网络对”ant“和”ants”两个单词会习得相似的词向量。

词干化(stemming)就是去除词缀得到词根的过程。

6. Skip-Gram 代码实现

完整代码请戳这里

下面是核心代码片段用tensorflow.embedding_lookup实现

    batch_size = 128embedding_size = 128skip_window = 1 # How many words to consider left and right.num_skips = 2 # How many times to reuse an input to generate a label.valid_size = 16 # Random set of words to evaluate similarity on.valid_window = 100# pick 8 samples from (0,100) and (1000,1100) each ranges. lower id implies more frequentvalid_examples = np.array(random.sample(range(valid_window), valid_size//2))valid_examples = np.append(valid_examples,random.sample(range(1000,1000+valid_window), valid_size//2))num_sampled = 64 # Number of negative examples to sample for sampeled_softmax.graph = tf.Graph()with graph.as_default(), tf.device('/cpu:0'):# Input data.train_dataset = tf.placeholder(tf.int32, shape=[batch_size])train_labels = tf.placeholder(tf.int32, shape=[batch_size, 1])valid_dataset = tf.constant(valid_examples, dtype=tf.int32)# Variables.embeddings = tf.Variable(tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))softmax_weights = tf.Variable(tf.truncated_normal([vocabulary_size, embedding_size],stddev=1.0 / math.sqrt(embedding_size)))softmax_biases = tf.Variable(tf.zeros([vocabulary_size]))embed = tf.nn.embedding_lookup(embeddings, train_dataset)print("Embed size: %s"%embed.get_shape().as_list())loss = tf.reduce_mean(tf.nn.sampled_softmax_loss(softmax_weights, softmax_biases, embed,train_labels, num_sampled, vocabulary_size))optimizer = tf.train.AdagradOptimizer(1.0).minimize(loss)# Compute the similarity between minibatch examples and all embeddings.# We use the cosine distance:norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keep_dims=True))normalized_embeddings = embeddings / normvalid_embeddings = tf.nn.embedding_lookup(normalized_embeddings, valid_dataset)similarity = tf.matmul(valid_embeddings, tf.transpose(normalized_embeddings))with tf.Session(graph=graph) as session:tf.initialize_all_variables().run()print('Initialized')average_loss = 0for step in range(num_steps):batch_data, batch_labels = generate_batch(batch_size, num_skips, skip_window)feed_dict = {train_dataset : batch_data, train_labels : batch_labels}_, l = session.run([optimizer, loss], feed_dict=feed_dict)average_loss += lif step % 2000 == 0:if step > 0:average_loss = average_loss / 2000# The average loss is an estimate of the loss over the last 2000 batches.print('Average loss at step %d: %f' % (step, average_loss))average_loss = 0# note that this is expensive (~20% slowdown if computed every 500 steps)if step % 10000 == 0:sim = similarity.eval()for i in range(valid_size):valid_word = reverse_dictionary[valid_examples[i]]top_k = 8 # number of nearest neighborsnearest = (-sim[i, :]).argsort()[1:top_k+1]log = 'Nearest to %s:' % valid_wordfor k in range(top_k):close_word = reverse_dictionary[nearest[k]]log = '%s %s,' % (log, close_word)print(log)final_embeddings = normalized_embeddings.eval()

另外一个直接用BP网络实现。容易理解点

import tensorflow as tf# 假设vocab_size = 1000
VOCAB_SIZE = 1000
# 假设embedding_size = 300
EMBEDDINGS_SIZE = 300# 输入单词x是一个[1,vocab_size]大小的矩阵。当然实际上我们一般会用一批单词作为输入,那么就是[N, vocab_size]的矩阵了
x = tf.placeholder(tf.float32, shape=(1,VOCAB_SIZE))
# W1是一个[vocab_size, embedding_size]大小的矩阵
W1 = tf.Variable(tf.random_normal([VOCAB_SIZE, EMBEDDING_SIZE]))
# b1是一个[1,embedding_size]大小的矩阵
b1 = tf.Variable(tf.random_normal([EMBEDDING_SIZE]))
# 简单的矩阵乘法和加法
hidden = tf.add(tf.mutmul(x,W1),b1)W2 = tf.Variable(tf.random_normal([EMBEDDING_SIZE,VOCAB_SIZE]))
b2 = tf.Variable(tf.random_normal([VOCAB_SIZE]))
# 输出是一个vocab_size大小的矩阵,每个值都是一个词的概率值
prediction = tf.nn.softmax(tf.add(tf.mutmul(hidden,w2),b2))
# 损失函数 
cross_entropy_loss = tf.reduce_mean(-tf.reduce_sum(y_label * tf.log(prediction), reduction_indices=[1]))
# 训练操作
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(cross_entropy_loss)

什么是ELMO、BERT、GPT

[深度学习-NPL]ELMO、BERT、GPT学习与总结

参考资料

Word2Vec Tutorial - The Skip-Gram Model
Word2Vec (Part 1): NLP With Deep Learning with Tensorflow (Skip-gram)
https://www.leiphone.com/news/201706/PamWKpfRFEI42McI.html

[深度学习NPL]word2vector总结与理解相关推荐

  1. 深度学习技术在机器阅读理解应用的研究进展

    深度学习解决机器阅读理解任务的研究进展:https://blog.csdn.net/malefactor/article/details/52832134 深度学习技术在机器阅读理解应用的研究进展:h ...

  2. 点云上的深度学习及其在三维场景理解中的应用————PointNet(一)

    最近在学3D方向的语义分析. 师兄推荐了一个哔哩大学的将门创投 | 斯坦福大学在读博士生祁芮中台:点云上的深度学习及其在三维场景理解中的应用!的宝藏视频,我会多看几遍,并写下每次观看笔记. 下文的截图 ...

  3. [深度学习-NPL]ELMO、BERT、GPT学习与总结

    系列文章目录 深度学习NLP(一)之Attention Model; 深度学习NLP(二)之Self-attention, Muti-attention和Transformer; 深度学习NLP(三) ...

  4. 深度学习100问之深入理解Vanishing/Exploding Gradient(梯度消失/爆炸)

    这几天正在看梯度消失/爆炸,在深度学习的理论中梯度消失/爆炸也是极其重要的,所以就抽出一段时间认真地研究了一下梯度消失/爆炸的原理,以下为参考网上的几篇文章总结得出的. 本文分为四个部分:第一部分主要 ...

  5. 人工智能:深度学习算法及应用——简单理解CNN卷积神经网络并python实现(带源码)

    深度学习算法及应用 一. 实验目的 二. 实验要求 三. 实验的硬件.软件平台 四. 实验原理 1.1. 深度学习概述 1.2. 深度学习的常见结构 1.3. 卷积神经网络(CNN) **卷积** * ...

  6. 深度学习100问之深入理解Regularization(正则化)

    声明 1)该文章整理自网上的大牛和机器学习专家无私奉献的资料,具体引用的资料请看参考文献. 2)本文仅供学术交流,非商用.所以每一部分具体的参考资料并没有详细对应.如果某部分不小心侵犯了大家的利益,还 ...

  7. 【深度学习】各种卷积的理解笔记(2D,3D,1x1,可分离卷积)

    卷积 1. 2D卷积 单通道版本 多通道版本 2. 3D卷积 3. 1x1卷积 作用 应用 4. 卷积算法 5. 可分离卷积 空间可分离卷积 深度可分离卷积 1. 2D卷积 卷积的目的是从输入中提取有 ...

  8. 【深度学习入门-1】透彻理解卷积的三层含义:从“卷积”、到“图像卷积操作”、再到“卷积神经网络”的含义(学习笔记)

    一.写在前面 笔者在进行卷积神经网络入门的时候花了很多功夫,理解的也不够透彻,基础不牢,地动山摇.在查阅了很多资料后,发现了大佬up"王木头学科学"讲的卷积神经网络的理解,茅塞顿开 ...

  9. 基于病害区域图像的植物病害识别深度学习(创新点好理解)

    Deep Learning for Plant Disease Identification from Disease Region Images 1.摘要解读 [目的]提出了一种利用病理分割的病害区 ...

最新文章

  1. 我已经喜欢上了Python
  2. 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting
  3. 肖邦夜曲21_原装进口 | 肖邦夜曲全集 鲁宾斯坦 钢琴经典 2CD
  4. 【最长公共前缀】算法优化笔记
  5. nginx资源定向 css js路径问题
  6. java有趣的平方数_JAVA小程序之独特的完全平方数问题
  7. Delphi查询Sqlserver数据库传入日期类型方法总结
  8. 成绩单表格html,【Web前端HTML5CSS3】15-表格
  9. Java基础知识强化之IO流笔记59:打印流
  10. 翻译:where在Swift中的用法
  11. 【美赛】美赛字体格式和排版要求
  12. 基于openpose的人体姿态识别部署详细过程
  13. UnityECS-初识
  14. Mybatis-plus最新代码生成器(3.5.1+)的使用
  15. Win10虚拟桌面使用技巧
  16. ros参数服务器调用_ROS路由与秒开缓存服务器对接时如何设置使用
  17. 机器人图形变变变_中班数学活动——图形变变变 教案
  18. 前端基础(二十七):面向对象基础
  19. 关于几篇数据挖掘的文章(2)
  20. 风险投资(VC)与私募股权投资(PE)的区别

热门文章

  1. 浅谈V8引擎中的垃圾回收机制
  2. JavaScript玩转机器学习:张量(Tensors) 和 操作(operations)
  3. 创建设计模式 - 工厂设计模式
  4. 使用adduser命令在Debian Linux中创建用户
  5. portainer使用阿里云docker镜像加速器
  6. 代码重构之道,重构即重生,让你的代码起死回生
  7. C#LeetCode刷题之#69-x 的平方根(Sqrt(x))
  8. Linux入门学习(五)
  9. github api常用操作
  10. js向页面中动态添加脚本