最后更新于
最后更新于
Algorithms often break down when forced to make predictions about data for which little supervised information is available. 对于样本量很少的类别, 现有的分类算法在分类时, 表现很差, 我们希望在不需要扩充样本的情况下, 能够有效的将算法的能力在少数类中得到提升.
例如, 对于分类任务, 对于有些类别, 我们有些类别, 我们只观察到一个样本(训练集中), 然后就需要对一个测试样本预测它的类别. 我们将其称之为one-shot learning.
文章提出一种新的方法, 通过多层非线性的深度学习框架, 自动地获取输入的表征, 而且这种表征能力具有很好的泛化性, 能够在只有少量样本的类别中也有很好的表现. 然后再结合one-shot learning的特点, 将分类过程分为不同的特征, 总体获得即有鲁棒性, 又能够在同类识别上表现很好.
这是一篇图像领域的文章, 样本因此都是图像. 自然语言领域可以类比.
我们通过metric-based的监督学习模型, 即siamese neural networks来学习图像(文本)的表征, 然后进行one-shot learning任务, 重复使用这个神经网络提取特征(而不需要重新训练).
上面所述的过程用图表示如下:
对于图像的表征, 采用了large siamese convolutional neural networks, 主要考虑到:
能够学习到图像的通用特征(共性特征), 从而样本数很少的类别中的样本进行预测时, 很有帮助
从数据源中采样得到的样本对, 用标准的优化方法就能够进行训练
用深度学习的方法就能够得到一个很棒的方法, 从而摆脱了对专业领域的知识的依赖
为了得到这种one-shot分类模型, 首先要获得一个神经网络模型, 能够很好地对图片对是否属于一个类别进行区分, 这就是基础的图像验证任务. 因此我们认为, 那些表现很好的用于图像验证的神经网络模型, 都能够很好的扩展到one-shot classification任务当中来.
这种verification model(图像验证模型)将两张图片是否属于同一类别用概率表示. 在训练得到这种模型后, 在做测试预测时, 对于一张新的图片, 就可以判断它是否属于一些新颖的类别了(通过组成图片对来进行), 对于这张图片组成的若干个image pair, 选取具有最高分数的pair作为最有可能的结果, 从而完成了one-shot任务.
Siamese Networks(孪生网络)就是为了完成上述的Verification工作的. Siamese Networks是一个比较古老的模型, 在90年代就被提了出来.
Siamese Networks如同它的名字一样, 包含了一对且共享参数的twin networks, 分别接受不同的inputs, 并且在网络的最后使用一个energy function连接起来. energy function的作用是在网络的末端抽取到最终的表征后, 计算度量两边的相似性.
由于参数的共享, twin networks之间会有高度的一致性关系. 这种一致性关系表现在将两个极其相似的图片放入网络中, 两边抽取到的表征向量在向量空间中不会有很大的差异. 而且这种结构是对称的, 对于两张图片, 无论我们放入的位置如何, 末层得到的metric都会是一样的, 避免了样本的位置带来的误差.
整体的图示如下:
首先是多层卷积层进行表征(对于NLP问题, 也可以更换成其他如RNN, Transformer等), 在一层全连接层之后, 再接上最顶层的energy function层评价相似性.
每个卷积层都用ReLU函数进行激活. 后面的全连接成或最后的metric层用sigmoid进行激活.
具体来说, 最后两层(全连接层, metric计算层)进行了如下的映射, 得到了计算距离的prediction vector:
整体的结构如下, 这里只描述了twin network其中的一个, 因为他们是共享参数的:
由于twin network共享参数, 因此目标函数在反向传播时, 在两个网络都会得到对应参数的梯度, 因此参数在更新时时将这两个梯度加在一起然后再更新的.
作者使用如下方法初始化参数
全连接层的参数使用均值为0, 标准差为0.2的正态分布初始化
使用了Omniglot data set. 这是一个包含各国以及各时代alphabets的字符集数据集, 共有50个不同的字符集, 每个字符集包含的字符个数在15个到40个之间. 每个字符又包含20个图像样本. 再将40个字符集作为background set, 用来训练和dev调试参数, 剩余的10个字符集作为evaluation set, 用来做test, 评价进行one-shot分类任务的表现如何.
使用60%的数据做训练, 即30个字符集, 每个字符抽取20*0.6=12个图像样本. 由于有的字符集包含的字符较多, 有的较少, 又使用方法保证每个字符集在训练过程中使用使用到的图片的数量是相同的, 但不保证每个字符集中的所有字符使用的样本数量是相同的. 又使用了多种数据扩充的方法, 大大扩充了训练集中样本的数量(原来的9倍).
注意这里的样本是一个image pair而不是单张的图片. 组成图片对的逻辑, 是随机对样本进行所有的相同/不同对进行采样得到(这样会不会有数据不平衡的问题?).
而用来进行validation的dev集, 有10个不同字符集, 并且每个有4张图片. 用同样本的方法抽样组成dev图片对样本进行验证.
训练完毕之后, 对于一个新的图片(图片来自于测试集), 选取若干个类别(类别也来自于测试集独有的), 从这些类别中获取一个样本, 组成样本对, 以最高的概率对应的类别为结果.
关于这篇论文, 有一篇文章及代码重现了论文中的过程(细节部分不太一致, 例如数据增强, 超参数优化, 迭代次数等等, 但整体的过程很清晰), 参考:
对应的jupyter notebook代码为:
翻译文章:
文章使用keras对论文中的模型进行了重建, 可以更好的理解两张图片的交互部分.
可以看到, 在对单个图片进行表征的时, 在卷积展平之后, 还使用了一层Dense
层, 并进行sigmoid, 得到了每张图片长度为4096的表征向量:
之后对两张图片计算绝对距离, 得到距离向量, 然后再连接一层激活函数为sigmoid的输出全连接层, 得到两张图片属于同一类别的概率:
以上是模型部分. Siamese模型的特殊的训练和测试方法更需要注意. 由于使用的是图片对作为输入, 因此进入模型训练的样本数量是图片样本的数量的平方正比, 所以即使原有的样本数量很少, 也不必担心样本量不足无法对模型中这么多参数拟合的问题.
需要关注的点有:
投入到模型训练的每个batch中的样本类别应当是1:1的, 即有的一半样本图片对是属于一个类别的, 另外一半是不属于同一个类别的
因此需要在生成batch的时候使用一定的策略
这里的batch和普通模型使用的batch在模型中的地位一样, 但这里的batch中包含的样本的数量, 与类别的数量有关, 而不是普通的样本数量选择
这里的train, dev, test集合会在类别上进行分割, 例如在dev中的任何类别, 在train中都没有出现过
生成训练集和dev集的代码如下:
具体来说, siamese convolutional neural network 拥有层卷积, 每层的卷积核的通道数量为. 我们使用表示first twin第层输出的隐向量, 同理用表示second twin第层输出的隐向量.
这里的卷积层使用的卷积核比较特殊, 每层使用个卷积核, 不同层的卷积核有着不同的size, 但步幅(stride)都是固定为1的. 每层卷积核的数量为16的倍数. 使用ReLU激活函数, 并且每层的最后使用一个与卷积核size一直, 步幅为2的max pool. 因此第层的第个卷积核的输出为:
其中是一个三维的张量. 并且对最后一个卷积层得到的结果进行flatten, 得到一个表征向量. 后面紧跟一个全连接层. 然后接着计算twin之间距离的一层, 最后给出一个标量, 作为距离的度量.
twin network将两张图片映射成和, 上面所说的全连接层不是对twin中单独的一个进行, 而是先对两个图片的表征向量中的每个元素对应计算L1距离得到新的距离向量后, 再进行全连接, 使用sigmoid激活, 这里的指的就是这层全连接层中的可训练参数. 而其中的表示了全连接层中的第个神经元. 这层全连接层的输入和输出的大小是等同的.
最后一层就是将层得到两张图片的相似性度量, 值域在之间.
假设batch size为, 并用表示第个batch. 因此就应该是一个长度为的向量, 代表了真值标签, 里面的值为1或者为0, 1表示两个图片是同一个类别, 0表示不是. 由于是一个二分类问题, 使用带正则项的cross-entropy目标函数表示如下:
卷积层参数使用均值为0, 标准差为的正态分布初始化
卷积层的bias使用均值为0.5, 标准差为的正态分布初始化
全连接层的bias使用均值为0.5, 标准差为的正态分布初始化, 与卷积层一样
每一个epoch缩小1%, 即.
训练的细节可以参考: .