上一篇讲到,fastText在训练数据中过拟合的问题。接下来将介绍一些提高fastText泛化能力的尝试。
使用过fastText的人,往往会被它的很多特性征服,例如训练速度、兼具word embedding和分类等。但是正如一个硬币有正反两面,fastText也并非完美,fastText的泛化性是它的短板。
在Logistic Regression中,调节正则项能够提高模型的泛化性能。通过上一篇博客可知,fastText的代价函数是:
L ( d , h ) = − ∑ i = 1 C y i log P i = − ∑ i = 1 C y i log e θ i T h ∑ j = 1 C e θ j T h L(d,h)=-\sum_{i=1}^{C} y_{i}\log{P_{i}}=-\sum_{i=1}^{C} y_{i}\log{\frac{e^{\theta^{T}_{i}h}}{\sum_{j=1}^{C}{e^{\theta^{T}_{j}h}}}} L(d,h)=−i=1∑CyilogPi=−i=1∑Cyilog∑j=1CeθjTheθiTh
增加正则项后,代价函数:
L ( d , h ) = − ∑ i = 1 C y i log P i + λ ∑ i = 1 V ∥ w i ∥ + μ ∑ j = 1 C ∥ θ j ∥ L(d,h)=-\sum_{i=1}^{C} y_{i}\log{P_{i}} + \lambda \sum_{i=1}^{V}\|w_{i}\|+\mu\sum_{j=1}^{C}{\|\theta_{j}\|} L(d,h)=−i=1∑CyilogPi+λi=1∑V∥wi∥+μj=1∑C∥θj∥
此时词向量的更新方式变为:
w j = w j − η ∑ i = 1 C ( P i − y i ) θ i − λ w j , j = 1 , 2 , . . . , L w_{j}=w_{j}-\eta\sum_{i=1}^{C}(P_{i}-y_{i})\theta_{i}-\lambda w_{j} ,\ j=1,2,...,L wj=wj−ηi=1∑C(Pi−yi)θi−λwj, j=1,2,...,L
增加了正则项后,同一个句子的词向量无法按照相同的方向更新,词向量间的相似便无法保证。此时,fastText与常见的前馈神经网络(DNN)没有任何差别,它的很多优秀的特质全部丧失了。个人猜测,这是Mikolov大神为什么没有在word2vec或者fastText中增加正则项的原因。
Dropout是常见的增加神经网络泛化性能的trick,它按照一定的概率将神经网络单元暂时从网络中丢弃。fastText作为一种浅层神经网络,能够加入dropout的地方非常有限:
在微博场景下,第二种方法的第一个子方法是最好的,即按照概率,随机干掉某个词。在引入dropout时,最开始通过等概率干掉某个词,即
d r o p o u t ( w i ) = { w i if p > t 0 o t h e r w i s e dropout(w_{i})= \begin{cases} w_{i}\ \ \text{if}\ p > t \\ 0\ otherwise \end{cases} dropout(wi)={wi if p>t0 otherwise
经过试验发现效果不好,模型对于某些关键词的学习效果不佳,例如上面提到的皮肤问题。考虑到微博广告文本中有许多强特征(关键词),它们的存在干扰了模型的泛化能力,因此等概率dropout是不适用的,需要一种不等概率的dropout——category dropout,简记为cdropout。在cdropout中,某个词被干掉的概率与它在某个类别的出现频率相关:
c d r o p o u t ( c , w i ) = { w i if p > 1 − t ( c , i ) 0 o t h e r w i s e cdropout(c, w_{i})= \begin{cases} w_{i}\ \ \text{if}\ p > 1 - t(c, i) \\ 0 \ \ otherwise \end{cases} cdropout(c,wi)={wi if p>1−t(c,i)0 otherwise
其中 c c c表示训练样本的类别, t ( c , i ) t(c,i) t(c,i)表示词 i i i在类别 c c c中的阈值。设计 t ( c , i ) t(c,i) t(c,i)时,需要考虑两个问题:
基于上述两个问题, t ( c , i ) t(c, i) t(c,i)的形式如下:
t ( c , i ) = m a x ( 0.5 , l o g 7 n ( c , i ) 10 ) t(c,i)=max(0.5, \frac{log_{7}{n(c,i)}}{10}) t(c,i)=max(0.5,10log7n(c,i))
其中 n ( c , i ) n(c,i) n(c,i)表示词 i i i在类别 c c c中出现的个数。 t ( c , i ) t(c,i) t(c,i)既保证强特征不会被完全干掉,也使模型能够从剩余的句子中寻找有用的信息。使用上述方法后,fastText对于关键词的预测效果如下所示:
关键词 | 类别 |
---|---|
祛痘 | __label__祛痘 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
痘痘 | __label__祛痘 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
黑头 | __label__祛痘 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
长痘 | __label__祛痘 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
痤疮 | __label__祛痘 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
痘坑 | __label__祛痘 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
皮肤问题 | __label__美甲美瞳 1.00001 __label__祛痘 1.05769e-05 __label__美发护发 1.00299e-05 |
关键词 | 类别 |
---|---|
婚纱照 | __label__美甲美瞳 1.00001 __label__祛痘 1.05769e-05 __label__美发护发 1.00299e-05 |
婚纱照 | __label__旅行跟拍 0.549722 __label__婚纱摄影 0.450298 __label__邮政业务 1e-05 |
相册 | __label__婚纱摄影 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
拍一套 | __label__旅行跟拍 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
婚照 | __label__婚纱摄影 1.00001 __label__邮政业务 1e-05 __label__买点卡 1e-05 |
样片 | __label__婚纱摄影 1.00001 __label__祛痘 1.00004e-05 __label__美甲美瞳 1.00003e-05 |
金夫人 | __label__婚纱摄影 1.00001 __label__减肥瘦身 1.00005e-05 __label__美发护发 1.00002e-05 |
客片 | __label__婚纱摄影 1.00001 __label__旅行跟拍 1.00002e-05 __label__国内游 1e-05 |
显然,加入cdropout后,类别准确度有了长足的进步。与此同时,cdropout也兼顾了词的余弦相似度
祛痘
黑头 0.962714
粉刺 0.941785
痤疮 0.941042
毛孔 0.939662
痘坑 0.937129
长痘 0.934889
青春痘 0.915363
痘 0.910426
痘痘 0.910171
祛 0.909382
婚纱照
摄 0.921392
婚照 0.905441
海景 0.848199
造 0.832112
全送 0.831038
婚纱 0.826123
夜景 0.818146
放大 0.81653
视觉 0.807251
这座 0.804767
可见cdropout,不仅提高了模型的泛化性能,而且保证了fastText的很多优秀特质。
通过cdropout,fastText的泛化性能得到了长足的进步,但是对于实际场景,尤其是微博短文本场景,依然是不够。在实际应用中,我们做了很多模型以外的工作,例如规则、爬虫等等。希望这三篇博客,能够对你有所帮助!吃饭去喽~