词向量
链接: 数据集 提取码: 6cgu
一 论文导读
《Efficient Estimation of Word Representations in Vector Space》
—向量空间中词表示的有效估计
作者:Tomas Mikolov, Kai Chen,Greg Corrado,Jeffrey Dean
单位:谷歌
论文来源:ICLR 2013
1.语言模型
2.词向量介绍
1.语言模型
语言模型:预测每个句子在语言中出现的概率
举例:
-
机器翻译:价格高
P(high price) > P(large price) -
S代表一整句话,wi代表句中的词
P(S)就是语言模型,即用来计算一个句子概率的模型
满足了什么条件可以使这些等式成立?
独立性吗?
计算公式:
缺点:(主要原因就是对其中一个词(参数)的出现概率就要考虑过多的词(参数))从而导致了
- 数据过于稀疏
- 参数空间过大
但实际上,一句话中一个词的出现并不一定受前面所有词的影响,所以有了马尔科夫假设
基于马尔科夫假设:下一个词的出现依赖它前面的一个词,则有公式:
假设下面一个词的出现依赖它前面的两个词,则有公式:
从而提出了n-gram模型:假设当前词的出现概率只与它前面的n个词有关
如何选择n:
- 更大的n:对于下一个词出现的约束信息更多,就有更大的辨别力
- 更小的n:在训练语料库中出现的次数更多,具有更可靠的统计信息,具有更高的可靠性、
理论上,n越大越好,经验上,trigram用的最多,尽管如此,原则上,能用bigram解决的,绝不使用trigram
n-gram模型的参数一般使用最大似然估计法进行计算
Count(X):在训练语料库单词序列X在训练语料中出现的次数。
词向量的介绍
一 独热表示(One-hot representation)
对应的词所在的位置设为1,其他设为0
缺点:
- 语义鸿沟问题(无法捕捉词与词之间的相似度)
- 位数灾难、稀疏
- 无法表示未出现的词汇
二 分布式词向量表示
值的范围一般在-1到1之间
在下图中,我们可以看出语音相近的词分布位置相邻
词向量表示的核心:利用上下文信息进行词表示
左图的英语和右图的西班牙语,虽然语言不同,但是分布近似
分布式表示的词向量的特点
- 词表示:[0.454,-0.256,0.125…]
- 常见维度是50或者100
- 解决了语义鸿沟问题
- 即可以通过计算向量之间的距离来体现词与词之间的相似性
如何训练词向量?
没有直接的模型可以训练得到分布式词向量
但可以通过训练语言模型的同时得到词向量
连续词袋模型和跳字模型
二 论文精读
还有上半部分没写
1.CBOW模型
2.Skip-gram模型
3.实验和结果
4.总结
1.CBOW模型:连续词袋模型
神经网络模型参数量太大,作者从而提出了word2vector模型(简化版的神经网络语言模型)
第一个全连接层的参数就是词向量表
word2vector包含两种模型训练办法:
一 CBOW模型 VS Skip-gram模型
- CBOW:Continue Bag of Words 连续词袋模型,即利用中心词的上下文来预测中心词
- Skip-gram: 跳字模型,是根据中心词来预测周围的词,即预测上下文
二 CBOW模型: - 目标函数:
- 无隐层
- 使用双向上下文窗口
- 上下文词序无关(BoW)
- 输入层直接使用低维稠密向量表示
- 投影层简化为求和(平均)(不用拼接)
连续词袋模型的结构图:
实例:
开始输入的one-hot向量
目前的w权重参数是随机初始化的
下面做求和再平均操作
下面是Hidden Layer到输出层的过程
W’的权重也是随机初始化的
最后通过softmax进行输出。之后进行训练迭代,达到目标后的矩阵W就是词向量表
获取任意单词的词向量就是查表的过程
词向量的获取:
任意单词的独热向量乘权重矩阵,得到自己的词向量
训练优化的技巧:
- 层次softmax(下图中的画圈部分,运用了哈夫曼树的相关知识)
- 负采样
2.Skip-gram模型
Skip-gram模型:
- 目标函数:
- 输入层:只含有与当前样本的中心词w的词向量
- 投影层:恒等投影,为了和CBOW模型对比(是多余的)
- 输出层:和CBOW模型一样,输出层也是一颗Huffman树
模型结构图(三层结构,去掉了隐层)
滑动创建参数
介绍两个参数:
- skip_wiondow:如何设置为2,则中心词左右有2个
- num-skips:从整个窗口中选取多少个不同的词作为输出(Training Samples就是输出)的上下文
整个Skip-gram模型的开始输入依旧是one-hot向量,接着乘以随机初始化的权值矩阵w,接着一系列操作
其中one-hot向量和w的乘积向量就是词向量的分布式表示,如下图的Vc
3.实验与结果
一 实验评估任务:有两种比较通用的方法(现在的代表性并不强了)(主要还是看具体效果)
1 word similarity task
- word similarity task (相似度任务):目的是评估词向量模型在两个词之间的语义紧密程度和相关性的能力
- 评价指标是斯皮尔曼等级相关系数(绝对值越接近1,相似度越大)
2 word analogy task - 词汇类比任务,考察了用词向量来推断不同单词之间的语义关系的能力(具有推断能力)
- vec(法国)-vec(巴黎)=answer_vector-vec(罗马)
- answer_vector=vec(法国)-vec(巴黎)+vec(罗马)
以下都是实验结果:
五种语义问题,九种语法问题
CROW模型
左边是训练词向量的维度,右边是训练集语料库的大小
可以看出随着维度的增加和语料库的增多,模型的准确率在提高
不同模型的比较:
NNLM是神经网络语言模型的意思
为什么跳词模型要好过连续词袋模型呢?
可以从下图看出本文的两个模型训练的时间要明显比神经网络模型短,同时效果不差
下图展示了满足各种关系的单词对,词汇类比任务(可以加减得到关系)完成的不错
4 讨论与总结
1 存在问题
- 对每个局部上下窗口单独训练,没有利用包含在全局共现矩阵中的统计信息
- 对多义词无法很好的表示和处理,因为使用了唯一的词向量
2 解决方式
- Glove:利用全局信息编码词向量
3 主要创新点
- 提出两种从大规模数据集中计算向量表示的模型
- 能在较少的资源上进行运算
- 在大规模预料上得到高质量的词向量
三 代码实现
- 简介
- 准备
- Skip-gram模型实现
- CBOW模型实现
- 总结
1.简介
- 两个模型:跳字模型和连续词袋模型
- 两种高效训练的方法:负采样、层序softmax
- word2vec词向量可以较好地表达不同词之间的相似和类比关系
- word2vec:CBOW模型:根据上下文预测中心词,Skip-gram:根据中心词预测上下文
2.准备工作
运行工具:tensorflow1.4以上
运行环境:python3.5
语料库:text8.zip
推荐中文语料库
在tensorflow训练词向量大致需要以下五步:
3.Skip-gram模型实现
def maybe_download(filename, expected_bytes):
"""
这个函数的功能是:
如果filename不存在,就在上面的地址下载它。
如果filename存在,就跳过下载。
最终会检查文字的字节数是否和expected_bytes相同。
"""
if not os.path.exists(filename):
print('start downloading...')
filename, _ = urllib.request.urlretrieve(url + filename, filename)
statinfo = os.stat(filename)
if statinfo.st_size == expected_bytes:
print('Found and verified', filename)
else:
print(statinfo.st_size)
raise Exception(
'Failed to verify ' + filename + '. Can you get to it with a browser?')
return filename
# 将语料库解压,并转换成一个word的list
def read_data(filename):
"""
这个函数的功能是:
将下载好的zip文件解压并读取为word的list
"""
with zipfile.ZipFile(filename) as f:
data = tf.compat.as_str(f.read(f.namelist()[0])).split()
return data
vocabulary = read_data(filename)
print('Data size', len(vocabulary)) # 总长度为1700万左右
# 输出前100个词。
print(vocabulary[0:100])
def build_dataset(words, n_words):
"""
函数功能:将原始的单词表示变成index
"""
count = [['UNK', -1]]
count.extend(collections.Counter(words).most_common(n_words - 1))
dictionary = dict()
for word, _ in count:
dictionary[word] = len(dictionary)
data = list()
unk_count = 0
for word in words:
if word in dictionary:
index = dictionary[word]
else:
index = 0 # UNK的index为0
unk_count += 1
data.append(index)
count[0][1] = unk_count
reversed_dictionary = dict(zip(dictionary.values(), dictionary.keys()))
return data, count, dictionary, reversed_dictionary
四 问题思索
-
简述几种你了解的词向量。
-
简述分布式词向量的优点。
-
分别画出神经网络语言模型、CBOW和Skip-gram模型的数据流程图。
-
根据实验结果分析为什么论文中表4中skip-gram比CBOW的模型效果好。