今天开始复习+学习下NLP的知识,写博客记录一下,本着简明通俗易懂的原则,只说听得懂的大白话,有问题和建议欢迎指出~
什么是自然语言处理
自然语言处理(natural language processing),字面意思就是处理语言的算法(语言也就是文字),比如:
- 给出I want a glass of orange ???,希望预测出下划线中的是juice,这就是语言模型(language model)
注:语言模型可以这么理解,假设有两个作家,第一个作家喜欢在下划线上用juice,第二个作家喜欢在下划线上用jam,用语言模型就可以通过学习某个作家的所有文章,预测出在该作者的写作风格下,下划线上应该是什么词 - 给出Tom is a farmer,希望预测出Tom是人名,这就是命名实体识别(named entity recognition)
- 给出Tom is a farmer,希望翻译出汤姆是一个农夫,这就是机器翻译(machine translation)
one-hot
解决自然语言处理问题的第一个关键问题,是如何把上面说的这些文字,表示成计算机能看懂的数字。
最直观的方法,是把所有可能的单词组成一个词典,比如一共有10000个单词,那词典的大小就是10000。
然后用单词在词典中的位置,来给这个单词编号。
例如,
1)单词a排在词典中的第1个,那就用一个1x10000维的向量 [1,0,0,0,…,0,0]1x10000 来表示,其中向量的第1个元素是1,其余元素都是0。
2)单词orange排在词典中的第6257个,那就用向量[0,0,0,…,0,1,0,0,0,0]1x10000来表示,其中向量的第6257个元素是1,其余元素都是0。
这样,每个单词都有一个独一无二的向量(或者说编码)来表示,且这个向量只有1个元素是1,其余元素均为0,这就叫做one-hot编码。
word embedding
one-hot编码解决了在计算机中表示文字的问题,但是有一些缺陷:
- one-hot编码维度很大(特别是当词典很大的时候),且非常稀疏
- one-hot向量相互独立(两两正交,正交的意思就是两个向量u,v,满足uTv=0),无法表达词与词之间的关系
我们希望得到的词向量(就是表示单词的向量)是:
- 维度可以低一些,比如300维
- 可以表达单词之间的相关性,比如apple和orange的相似度较高(都是水果),apple和woman的相似度较低。相似度可以用向量间的余弦相似度来表示(向量u和v的余弦相似度为: u T v ∣ ∣ u ∣ ∣ ⋅ ∣ ∣ v ∣ ∣ \frac{{\bf u}^{T}{\bf v}}{||{\bf u}||·||{\bf v}||} ∣∣u∣∣⋅∣∣v∣∣uTv)
将one-hot编码转化成如上描述的词向量的过程,就叫word embedding(词嵌入)。
把词典中的每一个单词的这300维的词向量拼在一起,就可以得到一个10000*300维的矩阵,
[
w
1
,
1
w
1
,
2
.
.
.
w
1
,
9999
w
1
,
10000
w
2
,
1
w
2
,
2
.
.
.
w
2
,
9999
w
2
,
10000
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
w
300
,
1
w
300
,
2
.
.
.
w
300
,
9999
w
300
,
10000
]
T
\left[ \begin{matrix} w_{1,1} & w_{1,2} & ... & w_{1,9999} & w_{1,10000}\\ w_{2,1} & w_{2,2} & ... & w_{2,9999} & w_{2,10000} \\ ... & ... & ... & ... & ... \\ w_{300,1} & w_{300,2} & ... & w_{300,9999} & w_{300,10000} \end{matrix} \right]^{T}
⎣⎢⎢⎡w1,1w2,1...w300,1w1,2w2,2...w300,2............w1,9999w2,9999...w300,9999w1,10000w2,10000...w300,10000⎦⎥⎥⎤T
该矩阵就称为词嵌入矩阵(word embedding matrix)。
这个矩阵也可以看作是一个表,把单词的one-hot编码当作索引去查找这个表,就可以得到该单词的词嵌入向量。
例如单词a的one-hot编码为[1,0,0,…,0],查找出表的第一行[w1,1,w2,1,…,w300,1]就是a的词嵌入向量。
通常,用上述查找表(look up table)的方式,通过单词的one-hot编码和词嵌入矩阵,得到单词的词嵌入向量。
查找表的过程也可以看作是矩阵相乘的过程。例如,记one-hot编码向量为X1 x 10000,词嵌入矩阵为W10000 x 300,词嵌入向量为H1 x 300,可以发现,
H
=
X
W
\bf H = XW
H=XW
只要得到词嵌入矩阵W,就可以得到维度较低,又可以表示单词间相关性的向量。
word2vec
通常通过学习(即训练模型)的方式来学习得到词嵌入矩阵。
学习的方式是,建立一个fake task(伪任务),在训练模型解决这个task的过程中,可以学到词嵌入矩阵。
也就是说,这个最终训练好的模型,不是为了解决这个fake task,而是要截取这个模型的某个部分,这个部分可以作为词嵌入矩阵。
这也是该任务称为fake task的原因。
其中一种学习词嵌入矩阵的方法是word2vec。
word2vec建立的fake task是一个预测模型,给定一个输入词,预测一个输出词。输入和输出词均用one-hot表示。
建立这个预测模型要回答两个问题,
- 训练的数据集(输入词和对应的输出词)是什么?
- 模型的结构是什么?
以句子“ I want a glass of orange juice. ”为例,介绍word2vec构建数据集的两种方案:
skip-grams
skip-grams是给定一个词,预测这个词一定区间(skip windows)内的上下文。
也就是随机选择句子中的一个词orange为输入词,设置区间长度为2,也即选择这个词的前后两个词分别作为输出词,最后得到如下输入-输出词对:
(orange,of)
(orange,glass)
(orange,juice)
这就是用skip-grams方式得到的训练数据集。
skip-grams方法适用于大数据集。
CBOW
CBOW是给定一个词一定区间内的上下文,预测这个词。
也就是随机选择句子中的一个词orange作为输出词,设置区间长度为2,也即选择这个词的前后两个词分别作为输入词,最后得到如下输入、输出词对:
(of,orange)
(glass,orange)
(juice,orange)
这就是用CBOW方式得到的训练数据集。
CBOW方法适用于小数据集。
建立模型要满足的条件是,模型要输入 输入词的one-hot(1 x 10000)X,输出 输出词的one-hot(1 x 10000)Y,并且要用上词嵌入向量。
一种直观的方法是,用输入词的one-hot查找表获得输入词的词嵌入向量H(1 x 300),再将该向量映射到输出词的one-hot,映射的方法是将词嵌入向量H连接一个含10000个神经元的全连接层,再对神经元的输出做softmax,就得到输出词的预测向量 Y ^ \hat { \bf Y} Y^(1 x 10000),该预测向量满足各元素和为1(softmax的性质)。
联系前面的描述,one-hot查找表获得词嵌入向量H的过程也可以用矩阵相乘 H = X W \bf H = XW H=XW来描述,因此也可以看作是1 x 10000的输入层,连接一个300维的隐藏层,该隐藏层没有偏置项b,也不加激活函数,词嵌入矩阵就是这个隐藏层的权重矩阵。
因此,从另一个角度看,word2vec的使用的模型,就是一个含单隐层的神经网络,网络中用一个1 x 10000的输入层,连接一个无激活函数无偏置的300个神经元的隐藏层,再连接一个1 x 10000,且使用softmax的输出层(类似encoder-decoder的结构),用skip-grams/CBOW得到的输入-输出对训练,训练完成后,输入层到隐藏层的权重矩阵就是要学习到的词嵌入矩阵。