word2vec词向量通俗化解释:
word2vec(word to vector)是一个将单词转换成向量形式的工具。
作用:
word2vec适合用作序列数据的分类,聚类和相似度计算。有用作app下载推荐系统中的,也有用在推荐系统和广告系统上的,也可以用在机器人对话类别判决系统上。
算法:
首先这是一个逻辑回归(分类)问题,使用最大似然估计。 在已知历史单词,要最大化下一个单词出现的概率,使用softmax函数做分类,则问题的数学描述如下:
这里计算上下文是时单词是的概率,显然上面的除法和指数计算是比较耗时,那么能否进行简化,答案就是取对数,将目标函数转换如下
假设我们的上下文是基于两个单词的,则根据the cat sits on the mat,将得到如下的训练样本:
上面只罗列了CBOW下的样本集。神经网络的结构如下:
输入层:
上述过程可以描述如下:
1.首先将所有的单词做one-hot映射,这把每一个单词映射到权重矩阵的一行,这每一行对应于该单词的特征向量,
这里左侧竖条是权重矩阵,对应于上图神经网络的权重
2.右侧蓝色方框的每一行都是一个单词的特征,把上图hidden layer linear neurons旋转90°就是其表示。
这里已经说明了如何从单词映射到特征向量。
输出层:
输入层使用softmax逻辑回归进行分类。
1.输出层输出的值累加和等于1,每一个神经元的值介于0~1
2.从单词特征向量和输出权重矩阵相乘得到softmax输出,由于输入特征向量是300维的,softmax输出预测的单词数量是和输入一致的,那么可以得出输出权重矩阵将是300*10000维的,这一过程如下:
实践
- 1.数据下载
wiki英文数据下载:https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2
wiki中文数据下载:https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2
- 2.数据处理
1.抽取文本 wiki数据内容比较复杂,所以在处理之前需要做一些预处理。通过 process_wiki.py 将wiki数据中的每一篇文章转为1行文本。
代码如下:
#--*-- coding:utf-8 --*--
from __future__ import print_function
import logging
import os.path
import six
import sys
from gensim.corpora import WikiCorpus
#import WikiCorpus
if __name__ == '__main__':
program = os.path.basename(sys.argv[0])
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))
# check and process input arguments
if len(sys.argv) != 3:
print("Using: python process_wiki.py enwiki.xxx.xml.bz2 wiki.en.text")
sys.exit(1)
inp, outp = sys.argv[1:3]
space = " "
i = 0
output = open(outp, 'w')
wiki = WikiCorpus(inp, lemmatize=False, dictionary={})
for text in wiki.get_texts():
if six.PY3:
output.write(bytes(' '.join(text), 'utf-8').decode('utf-8') + '\n')
# ###another method###
# output.write(
# space.join(map(lambda x:x.decode("utf-8"), text)) + '\n')
else:
output.write(space.join(text) + "\n")
i = i + 1
if (i % 10000 == 0):
logger.info("Saved " + str(i) + " articles")
output.close()
logger.info("Finished Saved " + str(i) + " articles")
2.训练词向量
训练word2vec的开源代码非常多,使用的语言种类也很丰富,本实验使用gensim包训练词向量,其特点使用简便,训练速度快。
代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
#导入日志配置
import logging
import os
import sys
import multiprocessing
#引入word2vec
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
if __name__ == '__main__':
program = os.path.basename(sys.argv[0])
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))
# check and process input arguments
if len(sys.argv) < 4:
print("Useing: python train_word2vec_model.py input_text "
"output_gensim_model output_word_vector")
sys.exit(1)
inp, outp1, outp2 = sys.argv[1:4]
model = Word2Vec(LineSentence(inp), size=128, window=5, min_count=5,
workers=multiprocessing.cpu_count())
model.save(outp1)
model.wv.save_word2vec_format(outp2, binary=False)
3.测试词向量
代码如下:
import gensim #导入包
model = gensim.models.KeyedVectors.load_word2vec_format("wiki.en.text.vector", binary=False)
model.most_similar('queen') #测试相关词
model.similarity("woman", "man") #测试次间距
Word2Vec 参数:
- min_count
model = Word2Vec(sentences, min_count=10) # default value is 5
在不同大小的语料集中,我们对于基准词频的需求也是不一样的。譬如在较大的语料集中,我们希望忽略那些只出现过一两次的单词,这里我们就可以通过设置min_count
参数进行控制。一般而言,合理的参数值会设置在0~100之间。
- size
size 是词向量维度
model = Word2Vec(sentences, size=200) # default value is 100
- workers
workers
参数用于设置并发训练时候的线程数,不过仅当Cython
安装的情况下才会起作用:
model = Word2Vec(sentences, workers=4) # default = 1 worker = no parallelization