加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

word2vec之Skip-Gram模型的tensorflow实现

(2017-11-02 18:56:06)
分类: 外汇量化投资

gensim里内置了word2vec模型,训练和使用都很方便。但word2vec本身这个模型的设计是很精妙的,自己从头使用tensorflow实现一遍很有意义。


http://mattmahoney.net/dc/text8.zip
python可以直接读zip文件,里边是一个命名为text8的文件,约100M,总共就一行,以
空格分词


from aipack.datasets import text8
words = text8.load_text8_dataset()#就是词列表,约1700W
data_size = len(words)
print(data_size) # 17005207
print(words[0:10]) # ['anarchism', 'originated', 'as', 'a', 'term', 'of', 'abuse', 'first', 'used', 'against']

data, count, dictionary, reverse_dictionary = build_words_dataset(words, vocabulary_size=50000)
#下标,词频dict,词序dict,序对词didct
print('Most 5 common words (+UNK)', count[:5])
print('Sample data', data[:10], [reverse_dictionary[i] for i in data[:10]])

读进来的text8约有1700W个词,排重后得到25W+个词,我们只保留50000个高频的,其余用UNK代替。

build_words_dataset返回:data:词的下标list,count:{词:词频},dictionary:{词:词下标},reverse_dictionary:{词下标:词}


有了原始的数据集,那就可以开始建模。

Word2Vec模型中,主要有Skip-Gram和CBOW两种模型,从直观上理解,Skip-Gram是给定input word来预测上下文。而CBOW是给定上下文,来预测input word,如下图:

http://s9/mw690/001rxTlvzy7fuKtwnGga8&690



batch, labels, data_index = generate_skip_gram_batch(data=data,batch_size=8,num_skips=4,skip_window=2,data_index=0)

data就是之前取出来的word_list的下标数组,每批取的pair数batch_size=8,num_skip=4是以这个词为中心,取对的次数

skip_window=2,是以当前词为中心,前后两个词(往前看包含当前词本身)。


下面是建模,官方示例损失函数用到了如下这个:


def nce_loss(vocab_size,embedding_size,embed,train_labels,num_sampled):
# 模型内部参数矩阵,初始为截断正太分布
   nce_weight = tf.Variable(tf.truncated_normal([vocab_size, embedding_size],
stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocab_size]))

# 得到NCE损失(负采样得到的损失)
   loss = tf.nn.nce_loss(
weights=nce_weight, # 权重
       biases=nce_biases, # 偏差
       labels=train_labels, # 输入的标签
       inputs=embed, # 输入向量
       num_sampled=num_sampled, # 负采样的个数
       num_classes=vocab_size # 类别数目
   )
print(loss)
nce_loss = tf.reduce_mean(loss)
return nce_loss

输入N*embedding_size的词嵌入之后的向量,与input_labels=[N,1]之间的loss。按常规情况,input_labels用one_hot得扩展成[N,vocab_size]维,但vocab_size-1维都是负样本。这样使用负采样,主要是减少计算量为[N,64]。


后面的训练就是正常输入数据,反向传播,迭代了。

在迭代25W轮之后,看下相似度,还是不错的:


http://s8/mw690/001rxTlvzy7fuKq6pPp87&690

从直观的视角,还原一下skip-gram的原理:

1,每批选择N个字的下标,对应的期望输出是这N个字周围的字(下标)。

2,对输入进行embedding,得到[N,embedding_size]的矩阵。

3,对这个embdding的结果,与期望输出[N,1]计算负采样损失。


关于作者:魏佳斌,互联网产品/技术总监,北京大学光华管理学院(MBA),特许金融分析师(CFA),资深产品经理/码农。偏爱python,深度关注互联网趋势,人工智能,AI金融量化。致力于使用最前沿的认知技术去理解这个复杂的世界。

扫描下方二维码,关注:AI量化实验室(ailabx),了解AI量化最前沿技术、资讯。

http://s1/mw690/001rxTlvzy7fuKrkDmM70&690

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有