ud730深度学习(二)——Word2Vec and CBOW

近年来,基于神经网络来得到词表示的模型备受青睐。这类模型所得到的词的向量表示是分布式表示distributed representation,通常被称为wordembedding(词嵌入;词向量)。2013年的开源工具包word2vec包含了CBOW(Continuous Bag-of-Words)和Skip-gram这两个直接以得到词向量为目标的模型。

word2vec的流程是这样的:词汇嵌入表示成一个短向量,然后把短向量传给带有权值和偏置的简单线性模型,得到softmax概率,这个softmax概率和context中的词进行比较,由于周围词可能非常多,因此只挑选一小部分,假装其他非目标词不存在。我们用一个大型文本语料库,对其中每个词做嵌入表示,再去预测在其附近出现的词,由此得到词到向量的映射,词义相近,映射出来的向量也相近。

在CBOW/Skip-gram模型中,target(目标词或中心词)是一个词串中间的词而不是最后一个词,其拥有的context(上下文或周围词)为前后各m个词。任一个词将得到两个word embedding(设维度为n):作为中心词时的词向量,也称为输出词向量;以及作为周围词时的词向量,也称为输入词向量。词表中每个词的词向量都存在一个矩阵中。由于存在两套词向量,因此就有两个矩阵:输入词矩阵,其每一列都是一个词作为周围词时的词向量;输出词矩阵,其每一行都是一个词作为中心词时的词向量。比如说若想取出词作为周围词时的词向量,只要知道词在词表中的编号即可,取出的操作相当于用输入词矩阵乘以词的one-hot representation。

CBOW通过上下文来预测中心词。

CBOW的代码已上传到github:https://github.com/Mandalalala/lesson/tree/master/ud730

任务 5: Word2Vec and CBOW

使用 Text8 的数据训练一个 skip-gram 模型并可视化输出

注意: 这个课程中的任务是相互关联的,请按顺序完成。

初始代码

打开 IPython notebook 中的这个任务 (https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/udacity/5_word2vec.ipynb),按照指导去完成和运行每一个步骤。第一个模型 (Word2Vec) 已经提供给你,请以此作为参考,训练一个CBOW (Continuous Bag of Words) 模型。

 

使用text8作为训练的文本数据集。text8中只包含27种字符:小写的从a到z,以及空格符。如果把它打出来,读起来就像是去掉了所有标点的wikipedia。

初始代码训练的是Skip-gram模型,是根据目标词汇预测上下文,而word2vec还有一种方式,CBOW,根据上下文预测目标词汇。

 

数据处理,构建索引

defbuild_dataset(words)

可以看出,索引反映了该单词在文中出现的次数。其中data中的索引存在着上下文的关系。其中UNK是较少使用的单词。

 

 

大小

格式

含义

data

words_size

[5234, 3082, 12, 6, 195,…]

Words中的单词对应dictionary中的索引

count

vocabulary_size

['UNK', 418391], ('the', 1061396), ('of', 593677),…]

按出现次数排序

dictionary

vocabulary_size

['removable': 21031, 'bush': 1820, 'ames': 15348,…]

根据单词查索引

reverse_dictionary

vocabulary_size

{0: 'UNK', 1: 'the', 2: 'of', 3: 'and',…}

根据索引查单词

产生训练对

defgenerate_batch(batch_size, num_skips, skip_window)

在skip-gram中,输入是目标词汇,输出是上下文。

batch_size:每次训练的单词数。声明batch_size % num_skips == 0。

num_skips:从span中选择的上下文的个数,比如num_skips为4,则单词as有4个。也就是找num_skips个上下文。因此声明num_skips <= 2 *skip_window。

skip_window:规定上文大小或者下文大小。

span:目标词和它的上下文的大小之和。

buffer:大小为span,存储目标词和它的上下文。这里隐含着词语和词语之间的联系信息。比如buffer[0]索引指向的单词在buffer[1]对应单词的前面。并且规定了最大长度,随着新词的涌入,最旧的词会被挤出去。

buffer.append(data[data_index])
data_index = (data_index + 1) % len(data)

batch:目标词的索引。

label:目标词的上下文所对应的索引。

data_index:从0开始,按顺序取words中的词。

打印出索引所对应的单词:

看到num_skips决定了中心词出现的次数。

 

在CBOW中,输入是上下文,输出是目标词汇。

因此需要改变batch的大小。

batch:shape=(batch_size, num_skips)。batch[i,j]中,i是验证样本序号,j是上下文的序号,通过num_skips个上下文来推断中心词,batch[i,j]指第i个中心词的第j个上下文的索引。

labels:对应目标词的索引。

num_skips:上下文的个数。

建立图

embeddings是一个大小为[vocabulary_size, embedding_size]的矩阵,设置里面的元素大小为-1到1之间,每一行表示一个词,所以一共有vocabulary_size。调用tf.nn.embedding_lookup,索引与train_dataset对应的向量,相当于用train_dataset作为一个id,去检索矩阵中与这个id(词)对应的embedding。

embed =tf.nn.embedding_lookup(embeddings, train_dataset)

返回的embed是一个大小为(batch_size,embedding_size)的矩阵,表示训练集中的词对应的词向量。然后计算softmax损失(由于数据量比较大,因此选择tf.nn.sampled_softmax_loss),通过最小化损失进行优化。优化器会优化softmax权值和词向量。

接下来计算样本和所有词向量之间的相似度,采用cosine距离。对embeddings的每个元素进行平方,然后将一个词的所有上下文的平方相加,即tf.reduce_sum(tf.square(embeddings), 1,keep_dims=True)。这样得出的是大小为vocabulary_size的向量,对该向量开根号得到norm,将原始embeddings除以norm得到标准化之后的词向量normalized_embeddings。整个过程如下:

norm =tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keep_dims=True))

normalized_embeddings= embeddings / norm

计算相似度:将valid_embeddings和标准化之后的向量进行乘积。sim是一个大小为[valid_size,vocabulary]的数组。sim[i,:]是valid_dataset[i]和其它元素的相似程度。

在CBOW中,由于输入是一个二维向量,每一行表示词的上下文,因此在检索完id对应的词向量之后,embeddingss是一个大小为[vocabulary_size, num_skips, embedding_size]的三维数组,把vocabulary_size和embedding_size相同的元素相加,使之大小降为[vocabulary_size, embedding_size]。

验证

当经过一定时间训练,计算词之间的相似度,对验证集中的词i,选择和验证集相似度最高的前top_k个元素,nearest = (-sim[i, :]).argsort()[1:top_k+1],这里取1到top_k+1是因为0的位置是词本身。

对CBOW,由于词是多个词表示的,因此选择多个词预测相似度。

降维可视化

从sklearn.manifold引入TSNE。

class sklearn.manifold.TSNE(n_components=2, perplexity=30.0,early_exaggeration=4.0, learning_rate=1000.0, n_iter=1000,n_iter_without_progress=30, min_grad_norm=1e-07, metric='euclidean',init='random', verbose=0, random_state=None, method='barnes_hut', angle=0.5)

n_components:向量空间的维度。

perplexity:混乱程度。该参数并不是很重要,因为TSNE对此不敏感。

early_exaggeration:放大度。

n_iter:优化过程中最多的迭代次数。

init:词向量的初始化。可选:random,PCA,以及(n_samples,n_components)的数组。PCA初始化不能够使用预先计算的距离,通常比随机初始化更加稳定。

 

fit_transform(X, y=None)

将X放进一个向量空间,返回转换后的结果。

 

小结

经过10000次训练,loss从7降到3,打印出结果发现使用CBOW,返回的中心词属于上下文的情况非常多。这种情况出现的原因是验证集的输入采用的是随机选词的方法,随机选择的词与词之间可能没有相关性,因此导致结果不准确。

 

 

参考资料:

http://www.cnblogs.com/Determined22/p/5804455.html

http://www.jianshu.com/p/45dbfe5809d4

http://www.jeyzhang.com/tensorflow-learning-notes-3.html

 

转载于:https://www.cnblogs.com/mandalalala/p/6798259.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值