Softmax分类器
我们来回顾一下机器学习中的分类问题。首先定义一些符号,假设我们有训练集
![]()
,其中
![]()
为输入,
![]()
为标签,共包括
![]()
个样本;
![]()
表示第
![]()
个样本,是一个
![]()
维的向量;
![]()
表示第
![]()
个样本的标签,它的取值是
![]()
个类别的其中一个。对于简单的二分类问题,我们可以用简单的逻辑回归来训练。而对于多分类问题,则可以用OVR (one-vs-rest) 等方法构造多个逻辑回归,或者用更简洁一些的softmax分类器,接下来我们就来介绍一下softmax分类器。设
![]()
权重矩阵,那么softmax分类器预测的概率为
其中
![]()
表示
![]()
的第
![]()
行。显然我们希望我们预测的概率分布与真实的分布尽量相似,而在信息论中,KL散度(KL divergence)是一种用来衡量两个分布的差异的方法,那么也就是说我们想让预测分布和真实分布的KL散度最小。对于
![]()
,如果用
![]()
表示其类别的真实分布,则
![]()
,即类
![]()
的概率为
![]()
,其他类的概率为
![]()
。如果我们预测的概率分布为
![]()
,则
![]()
与
![]()
的KL散度为
注意到其中
![]()
是一个常数,因此最小化
![]()
和
![]()
的KL散度相当于最小化
![]()
叫做交叉熵(cross entropy)损失函数。由于这里只有
![]()
,因此这时交叉熵与负对数似然
![]()
等价。接下来我们就通过交叉熵来定义softmax分类器的损失函数
其中
![]()
。而在实践中我们通常还要在损失函数中加上一个正则化项来防止过拟合,即
过拟合
通常
![]()
是模型中的所有参数组成的向量,这里
![]()
是
![]()
的所有列向量组成的向量,即
而在更新时,我们需要求
而如果我们需要同时训练词向量的话,我们则需要求
这时其维数达到了
![]()
,当词汇量很大时,将会很容易过拟合。那么我们需不需要自己训练词向量呢?我们来看下面的例子。
考虑一个用逻辑回归做单词分类问题。假设我们有预训练的词向量,其中单词“TV”、“telly”和“television”这几个词很接近,此时直接用逻辑回归得到的结果如下
而如果我们的训练集中有“TV”和“telly”,而没有“television”,并且在这个训练集上重新训练词向量的话,那么“TV”和“telly”的词向量就会有一定的偏移,但“television”的词向量却没有变化。即
这显然不是我们想要的结果。那么也就是说需不需要自己训练词向量取决于数据集。如果你只有一个很小的训练集,那么不要自己训练词向量,直接用预训练的词向量效果就会很好;而如果你有充足的训练集,那么自己训练词向量效果可能会更好一些。
Window Classification
对一个单词进行分类的问题并不常见,但是在判断多义词的词义时还是会用到。有些多义词可以同时表达两个相反的意思,比如“to sanction”的含义可能是“to permit”,也可能是“to punish”;“to seed”可能表示“to place seeds”,也可能表示“to remove seeds”。有些多义词则可能表示两个完全不相关的事物,比如“Paris”可能是法国巴黎,也可能是“Paris Hilton”(帕丽斯·希尔顿);“Hathaway”可能是“Berkshire Hathaway”(伯克希尔·哈撒韦公司),也可能是“Anne Hathaway”(安妮·海瑟薇女神!)。想要判断多义词在文中到底是哪个意思,就需要上下文的帮助。一个简单的方法就是Window Classification,即考虑一定窗口大小内的上下文。
比如一个命名实体识别(Named Entity Recognition, NER)任务,通常是四分类(人名、地名、机构名、None)任务,假设我们判断单词“Paris”,如果选取大小为2的窗口,那么我们需要考虑包括“Paris”在内的五个单词,即
我们把这五个单词的词向量拼在一起,得到
![]()
,之后我们通过softmax分类器来判断其词义了。令
![]()
表示真实的类
![]()
的预测概率,则
然后同样用交叉熵作为损失函数
其中
![]()
。接下来我们来推导损失函数的梯度,首先
其中
![]()
是我们预测的分布,
![]()
是真实分布(One-hot向量)。从而得到
简化一下,就是
这就是损失函数对
![]()
的导数了,也就是说
![]()
。同样我们可以求出损失函数对权重
![]()
的梯度
![]()
,将两个梯度拼在一起就是
![]()
。然后就可以使用梯度下降来训练模型了。
Neural Network
softmax虽然简单有效,但只能拟合线性的决策边界,无法解决线性不可分的问题。接下来我们来看看能够拟合非线性决策边界神经网络。一个简单的单层神经网络可以表示为
其中
![]()
是激活函数,通常使用非线性的sigmoid函数或ReLU等。损失函数通常也使用上文提到的交叉熵损失函数。
为了对神经网络有一个更深入的了解,我们来考虑一个简化版的NER任务:判断单词是不是地名。如果我们用一个简单的单层神经网络来建模,输入仍是
![]()
,而输出层只有一个神经元
![]()
表示其得分,那么
如果我们用
![]()
表示正确窗口(即中心词是地名)的得分,用
![]()
来表示错误窗口(即中心词不是地名)的得分,那么自然地会希望
![]()
要比
![]()
大。这时候我们就不需要交叉熵损失函数了,我们可以使用更简单的Max-margin loss(也称hinge loss,常用于SVM),即
当
![]()
的时候
![]()
,而当
![]()
时,
![]()
。也就是说,我们不仅希望
![]()
比
![]()
大,而且至少要大
![]()
,这样才能更好的判断结果。
上面是对于单个窗口的损失函数,而完整的损失函数则要对每个正确窗口采样几个错误窗口,然后再求和。这与Word2Vec的负采样类似。
接下来我们来推导其反向传播,首先
之后
这一步是对矩阵
![]()
求导,不理解的同学可以先考虑对单个元素
![]()
求导,由于
![]()
只出现在
![]()
中,因此
继续推导可得
也就是说
![]()
,拼成整个矩阵就是
![]()
。类似的,我们可以推导出
对于
![]()
,求导的过程也类似,在此不再赘述。至此我们成功推导了一个简单的单层神经网络的前向传播和反向传播,对于更复杂的神经网络,我们之后再详细说明。
相关阅读:
TJH:CS224N NLP with Deep Learning(一):Introductionzhuanlan.zhihu.com
TJH:CS224N NLP with Deep Learning(二):词向量之Word2Veczhuanlan.zhihu.com
TJH:CS224N NLP with Deep Learning(三):词向量之GloVezhuanlan.zhihu.com
TJH:CS224N NLP with Deep Learning(四):Window分类器与神经网络zhuanlan.zhihu.com
TJH:CS224N NLP with Deep Learning(番外1):fastTextzhuanlan.zhihu.com
TJH:CS224N NLP with Deep Learning(五):反向传播zhuanlan.zhihu.com
TJH:CS224N NLP with Deep Learning(五):依存分析zhuanlan.zhihu.com
TJH:CS224N NLP with Deep Learning(六):语言模型与循环神经网络zhuanlan.zhihu.com