word2vec之Skip-Gram模型的tensorflow实现

分类: 外汇量化投资 |
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量化最前沿技术、资讯。