小样本学习(few-shot learning)在文本分类中的应用
1,概述
目前有效的文本分类方法都是建立在具有大量的标签数据下的有监督学习,例如常见的textcnn,textrnn等,但是在很多场景下的文本分类是无法提供这么多训练数据的,比如对话场景下的意图识别,这个时候如果我们还以传统的深度学习模型+softmax的形式来分类的话,是极容易陷入过拟合的状态。因此就有很多人研究在少量样本下如何建模。one-shot learning,few-shot learning,甚至是zero-shot learning都是旨在解决这类的问题。
本篇博客将会介绍下几种比较经典的one-shot learning或者是few-shot learning。
2,模型介绍
接下来我们来介绍几篇经典的文章,来看看都是怎么去做few-shot learning或者one-shot learning的。但因为大部分文章中的例子都是在图像领域的,因此不会很细的去描述模型的结构,应用到文本中这些结构可以自己去选择,在这里会侧重讲述其做法,代码实现见https://github.com/jiangxinyang227/few_shot_learning。数据集采用的是由阿里巴巴团队整理出来的ARSC数据集。
论文一:Siamese Neural Networks for One-shot Image Recognition
这篇论文的主体结构是孪生网络(Siamese Network),之前的一片博客有专门介绍过孪生网络,详情见孪生网络(Siamese Network)在句子语义相似度计算中的应用。这一篇介绍下孪生网络在one-shot learning中的应用。
假定你现在对孪生网络结构有个清晰的了解,我们现在来看看是怎么用孪生网络做one-shot learning的。我们给定三份数据集,用于训练的train set,用于测试时的support set,query。
train set包含M个类别,每个类别下有N个样本,我们现在随机从每个类别下去采样,从同一类别下采样相同的两个句子作为正样本,从不同的类别下采样两个句子作为负样本,保证正负样本对的数量为1:1。然后输入到孪生网络中作为一个二分类的任务来度量两个句子之间的距离。
在本论文中的度量方式用的是曼哈顿距离,并采用了加权和的方式来加权,加权系数是通过网络自己学习的,其表达式如下:
上面式子中$h_{1, L-1}^{(j)},h_{2, L-1}^{(j)}$分别表示第一个句子和第二个句子最终的向量表示,$\alpha_j$是上面两个向量相减后得到的向量的第$j$个值得系数,这个值是通过网络自己学习得到的,$\sigma$表示sigmoid函数,输入一个0-1之间的概率值。
上面说到通过这种采样方式将问题转化成一个0,1的二分类问题,因此损失函数可以采用二元交叉熵损失函数。
论文中也给出了自己的优化算法:
引入了动量和正则,不过这里的正则的作用是什么,我不太清楚。
one-shot learning在测试阶段是怎么实现的呢?具体如下:
首先在给定的测试时的support set,support set是一个C个类别(原则上这C个类别和train set中的M个类别是不相交的,这样才符合one-shot learning的本质),且每个类别下只有一个样本的数据集,现在给定一个query,将query和support set中的样本输入到孪生网络中,得到query和每个样本之间的概率分数,在这里因为是one-shot,因此support set中每个样本表示一个类别,然后取概率分数最大的类别作为输出类别,表达式如下:
上面式子中$P^{(c)}$表示query和support set中的样本的概率分数。
论文二:Prototypical Networks for Few-shot Learning
原型网络(Prototypical Network)中引入了一个混合密度估计的思想,用few-shot样本集的均值来表示该类别的向量,我们来看看具体的做法
给定一个训练时的train set,测试时的support set和query。support set 包含C个类别,每个类别下含有K个样本。train set 包含M个类别,每个类别下含有N个样本。为了在训练时期模拟测试时的场景,我们在训练时构造一系列的episode,每个episode实际上就是一个meta task。那该怎么构造这样一个episode呢?从train set中随机抽取C个类别,然后从每个类别中随机抽取K个样本,构造训练时期的support set,这样的问题也称为C-way K-shot问题,接着从另外N-K个样本中选取n个样本作为训练时期的query。构造一系列这样的episode来训练网络。其具体的结构可以描述如下:
1)embedding层,将训练时的support set和query embedding成向量表示
2)特征提取层,这里可以用LSTM来提取句子的高层特征
3)针对support set做的类的向量表示层,其实就是对每个类中的K个样本取平均来表示这个类
上面式子中$f_{\phi}(x_i)$表示support set中第$i$个样本的向量表示,$k$表示第$k$个类别。
4)计算query和每个类别之间的分数
上面式子中$f_{\phi}(X)$表示query的向量表示,$d(.)$是一个距离度量函数,上面整个式子是一个softmax函数,得到query和每个类别的概率分数。
真个算法流程图如下:
整个算法原理图示化:
如上图所示,整个模型也是可以很好的迁移到zero-shot,one-shot的任务上的。
到了这里还有一个问题,就是距离度量函数$d(.)$该怎么选择,上面我们说到是通过计算类别下所有样本的均值来表示该类别,文章中引入了Bregman 散度的概念,Bregman 散度认为:达到与指定点(query)最小距离的点为样本均值点,也就是说当我们的度量函数$d(.)$选择Bregman 散度时,用样本均值来表示类向量是最佳选择,而欧式距离的平方就是一种Bregman 散度。因此本文的距离度量函数是欧式距离的平方:
上面添加的负号是将求距离最小转换成求距离最大。
测试的时候和训练时的episode中的操作一样,将测试时的support set 和query输入到模型中,然后计算query和每个类别的概率分数,选择最大的概率值的类。
论文三:Learning to Compare: Relation Network for Few-Shot Learning
这篇论文中提出了关系网络(Relation Network)的概念。整个训练和预测时的方法和上一篇的原型是一样的。其主要创新点在于之前的网络都会给定一个确定的距离度量函数,然而作者认为没有一个确定的距离函数能作为所有类别的最佳度量函数,因此作者让网络自己去学习一个这样的度量函数,这里的Relation network就是通过关系网络来度量query和各类别之间的关系。
其网络结构图如下:
在这里是一个图像分类的例子,转换到文本上只要更改第一个embedding module。在这个模块之后有一个relation module模块,这个模块就是度量query和每个类别的关系分数的。
假设support set总共有C个类别,以one-shot为例,其关系分数表达式如下:
上面式子中$x_i$表示support set中第$i$个样本,因为是one-shot,所以一个样本表示一个类别,因此$f_{\varphi}(x_i)$表示的是第$i$个类别的向量,$f_{\varphi}(x_j)$表示的是query中第$j$个样本的向量。
而转换到few-shot的场景下,论文这里是通过对样本向量求和的方式来表示类向量。因为关系网络得到是一个关系分数,因此作者认为用回归的方式来训练网络更合适,因此这里的损失函数是均方误差,表达式如下:
真实的标签还是0和1,用计算出来的关系分数和0,1计算均方误差。
论文四:Few-Shot Text Classification with Induction Network
这篇论文是阿里小蜜团队提出的,并成功用在了他们的对话平台中,用来做少样本的意图识别。整体的训练方式和上面两篇论文一致,但是在类向量的表示上不再是简单的求均值或者求和,此外也引入了关系网络来计算query和类别之间的关系分数。
训练模型的算法如下:
和上面的训练方式基本一致。
首先来看下整个网络结构图:
整个网络结构由三个模块组成:Encoder Module,Induction Module,Relation Module。我们接下来一一介绍这三个模块:
1)Encoder Module
这个模块就是对输入的样本提取高层特征,用向量来表示它们。
在这里用的方法就是Bi-Lstm + attention的方式,这个做NLP的基本都很清楚,就不详述。
2)Induction Module
这里也是整个论文的创新点,提出用胶囊网络(Capsules Network)来动态的表征类向量,首先胶囊网络是有Hinton提出的,关于胶囊网络具体的描述见看完这篇,别说你还不懂Hinton大神的胶囊网络,capsule network。在这里通过动态路由算法来得到某个类别下不同样本对类向量的贡献,简单理解和attention中的加权和类似,所以后面作者也给出了基于attention的方法来表示类向量的实验结果,但是效果较胶囊网络要差一些。
首先将Encoder Module得到的support set的结果表示为$e^s$,query的结果表示为$e^q$,具体的流程如下:
(1)首先用一个矩阵将$e^s$映射到另一个空间,作者认为这一步很重要,可以起到类似聚类的效果,将相同的样本映射到一个相同的子空间中,作者给出了转换前后可视化图的对比
可以看到矩阵映射之后类别之间的界面更加明显,此外也和论文三做了对比:
可以看到本论文提出的Induction Network在类别聚合上的效果更好。
这个映射转换的公式如下:
(2)对动态路由的值归一化, 注意:这里的$b_i$在每个batch进来训练时都应该初始化为0,因此它只是一个每次迭代的临时变量,而不是计算图中被训练的永久变量。
上面的$i$表示第$i$个类
(3)加权和得到类向量
(4)经过激活函数squash函数,得到新的类向量
(5)更新动态路由值
这里的更新方式确保了和类向量相近的样本向量对应的路由值会增大,即$e_{i, j}^s$ 和 $c_i$的点积大,则$b_{i, j}$就大,在迭代计算$c_i$的时候,样本$j$的贡献就大。
动态路由值在一开始会全部初始化为0,经过softmax后可以认为所有的样本对类向量的贡献是一样的,经过迭代可以得到新的动态路由值。在这里的迭代次数为3,整个Induction Module的算法如下:
3)Relation Module
关系模块就是来度量query和类别之间的关系分数的,注意,这里的权重$W_r, b_r$在每个类别中是共享参数的,其计算公式如下:
最后的损失函数也是采用了均方误差。
参考文献:
Siamese Neural Networks for One-shot Image Recognition
Prototypical Networks for Few-shot Learning
Learning to Compare: Relation Network for Few-Shot Learning
Few-Shot Text Classification with Induction Network
数据集来源:Mo Yu, Xiaoxiao Guo, Jinfeng Yi, Shiyu Chang, Saloni Potdar, Yu Cheng, Gerald Tesauro, Haoyu Wang, and Bowen Zhou. 2018. Diverse few-shot text classification with multiple metrics