之前我们了解了孪生网络以及他是如何处理one-shot learning的例子,现在我们再来看看另一个模型,原型网络Prototypical Networks。
之前说过,孪生网络的缺点就是要对比目标和过去每个样本之间的相似度,从而分析目标的类别,而原型网络就提出,先把样本投影到一个空间,计算每个样本类别的中心,在分类的时候,通过对比目标到每个中心的距离,从而分析出目标的类别:
大致思路很简单,具体实现也不难,首先是把输入投影到新的特征空间,这个和nlp中的word embedding比较相似,也是通过神经网络,把输入(比如图像)转化为一个新的特征向量,使得同一类的向量之间的距离比较接近,不同类的向量距离比较远。同时,计算每个类别的均值表示该类的原型prototype。
但是原型网络也有一些细节需要注意,先来看看具体过程,首先我们有训练集:
D = { ( x 1 , y 1 ) , . . . , ( x n , y n ) } D = \{(x_1,y_1),...,(x_n,y_n)\} D={(x1,y1),...,(xn,yn)}
假设我们一共有K个类别,那么我们就从D中为每个类别分出K个子集,每一次迭代,就对一个子集随机抽样得到support set支持集和query set查询集(注意支持集和查询集不能有重复),利用支持集计算原型:
c k = 1 S k ∑ ( x i , y i ) ∈ S k c_k=\frac{1}{S_k}\sum_{(x_i,y_i)\in S_k} ck=Sk1(xi,yi)∈Sk∑
得到每个类的原型之后,再用查询集计算每个样本对应每个类的概率:
p ϕ ( y = k ∣ x ) = e x p ( − d ( f ϕ ( x ) , c k ) ) ∑ k ′ e x p ( − d ( f ϕ ( x ) , c k ′ ) p_{\phi}(y=k|x)=\frac{exp(-d(f_{\phi}(x),c_k))}{\sum_{k'}exp(-d(f_{\phi}(x),c_{k'})} pϕ(y=k∣x)=∑k′exp(−d(fϕ(x),ck′)exp(−d(fϕ(x),ck))
假设样本对应的真实类别为k’,那么就可以定义损失函数:
J ( ϕ ) = − l o g ( p ϕ ( y = k ′ ∣ x ) ) J(\phi) = -log(p_{\phi} (y=k'|x)) J(ϕ)=−log(pϕ(y=k′∣x))
我们希望最小化损失,所以相当于最大化log,也就是最大化x正确分类的概率。通过最小化损失函数,从而优化最初的embedding网络。
整个模型比较特别的地方是训练过程中把数据划分成支持集和查询集,这个很容易理解,毕竟我们必须要通过一部分数据去确定出prototype的位置,在测试过程中我们可以利用训练集确定prototype,但在训练过程中,我们只能划分出两部分,一部分用来确定prototype,另一部分用来训练模型。最后,值得一提的是,通过训练集确定prototype,其实本质上就是模型利用训练集作为先验知识的过程。
在github写的自然语言处理入门教程,持续更新:NLPBeginner
在github写的机器学习入门教程,持续更新:MachineLearningModels
想浏览更多关于数学、机器学习、深度学习的内容,可浏览本人博客