One-Shot learning(一次学习问题):
每个人的训练样本只包含一张照片,需要通过单单一张图片就能去识别这个人。
相似函数:
d ( i m g 1 , i m g 2 ) d(img1,img2) d(img1,img2) = 两张图片之间的差异度
若 d ( i m g 1 , i m g 2 ) ≤ τ d(img1,img2)≤ \tau d(img1,img2)≤τ则判断是一个人;反之不是
相似函数如何解决了一次学习问题:
假设要识别5个人脸,我们会使用有5个输出softmax卷积神经网络,然后对这个小样本训练集进行训练,CNN人脸识别效果会很差;若后面要添加新员工,需要修改输出和重新训练。
使用相似函数,就可以一个函数解决所有样本,所有样本训练一个函数。
CNN训练的目标为:
为了定义人脸识别CNN的损失函数,引入Triplet Loss(三元组损失函数)。
如下图,Triplet Loss需要三张图片进行比较:
(1)Anchor【目标】;(2)Positive【正例】;(3)Negative【反例】
将Anchor(A)分别与Positive§和Negative(N)进行比较。
希望A与P的相似函数小一些,A与N的相似函数大一些,即:
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 ≤ ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 ||f(A)-f(P)||^2≤||f(A)-f(N)||^2 ∣∣f(A)−f(P)∣∣2≤∣∣f(A)−f(N)∣∣2
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 ≤ 0 ||f(A)-f(P)||^2-||f(A)-f(N)||^2≤0 ∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣2≤0
当CNN输出 ∣ ∣ f ( x ) ||f(x) ∣∣f(x)都是0或都相等时,上述式子也都成立的,但不希望CNN训练出这样的参数;因此我们添加一个间隔 α α α:
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 ≤ − α ||f(A)-f(P)||^2-||f(A)-f(N)||^2≤-α ∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣2≤−α
习惯 α α α在左边:
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 + α ≤ 0 ||f(A)-f(P)||^2-||f(A)-f(N)||^2+α≤0 ∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣2+α≤0
α也被称为边界margin,类似 S V M SVM SVM中的margin,作用是拉大Anchor和Positive 图片对和Anchor和Negative 图片对之间的差距。
损失函数:
给出三张图片:A、P、N
L ( A , P , N ) = m a x ( ∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 + α , 0 ) L(A,P,N)=max(||f(A)-f(P)||^2-||f(A)-f(N)||^2+α,0) L(A,P,N)=max(∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣2+α,0)
只要小于0,损失函数值就为0;大于0就会得到一个大于0的正数损失函数值
m个样本损失函数:
J = ∑ i = 1 m L ( A ( i ) , P ( i ) , N ( i ) ) J=\sum\limits_{i=1}^mL{(A^{(i)},P^{(i)},N^{(i)})} J=i=1∑mL(A(i),P(i),N(i))
在训练的时候,要保证一个人包含很多照片
,否则无法使用这种方法。如:10k张照片包含1k个不同的人脸,平均一个人有10张照片。
如果随机的选择A、P、N, d ( A , P ) + α ≤ d ( A , N ) d(A,P)+α≤d(A,N) d(A,P)+α≤d(A,N)很容易满足,因为A和N之间很容易有很多不同。所有我们应该选择比较“难”训练的三元组去训练网络。
如选择 d ( A , P ) ≈ d ( A , N ) d(A,P)≈d(A,N) d(A,P)≈d(A,N)的三元组,这样CNN就会竭尽全力去满足这个式子,使算法效率更加高效。
相关论文:
Florian Schroff, Dmitry Kalenichenko, James Philbin (2015). FaceNet: A Unified Embedding forFace Recognition and Clustering
可以将两张图片分别经过CNN得到128个features,再将两个图片的features作为逻辑回归的输入。如下图所示。
逻辑的输出:0表示两张图片不是同一个人;1表示两张图片是同一个人。
训练集从原来的三元组变成现在的二元组了,两个CNN的结构和参数都是相同的。逻辑回归的输出 y ^ \hat{y} y^可表示为:
y ^ = σ ( ∑ k = 1 128 w k ⋅ ∣ f ( x ( i ) ) k − f ( x ( j ) ) k ∣ + b ) \hat{y}=σ(\sum\limits_{k=1}^{128}w_k\cdot|f(x^{(i)})_k-f(x^{(j)})_k|+b) y^=σ(k=1∑128wk⋅∣f(x(i))k−f(x(j))k∣+b)
中间的绝对值可以换成 ( f ( x ( i ) ) k − f ( x ( j ) ) k ) 2 f ( x ( i ) ) k + f ( x ( j ) ) k \frac {(f(x^{(i)})_k-f(x^{(j)})_k)^2} {f(x^{(i)})_k+f(x^{(j)})_k} f(x(i))k+f(x(j))k(f(x(i))k−f(x(j))k)2,这个公式也被叫做 X \cal X X方相似度:
y ^ = σ ( ∑ k = 1 128 w k ⋅ ( f ( x ( i ) ) k − f ( x ( j ) ) k ) 2 f ( x ( i ) ) k + f ( x ( j ) ) k + b ) \hat{y}=σ(\sum\limits_{k=1}^{128}w_k\cdot\frac {(f(x^{(i)})_k-f(x^{(j)})_k)^2} {f(x^{(i)})_k+f(x^{(j)})_k}+b) y^=σ(k=1∑128wk⋅f(x(i))k+f(x(j))k(f(x(i))k−f(x(j))k)2+b)
为了加速运算,可以对数据库中的图片提前计算CNN的输出 f ( x ) f(x) f(x),保存 f ( x ) f(x) f(x)即可;因为编码层输出 f ( x ) f(x) f(x)比原始图片数据量少很多,所以无须保存模板图片,只要保存每个模板的 f ( x ) f(x) f(x)即可,节约存储空间。在进行测试时,只需要计算新的图片的 f ( x ( i ) ) f(x^{(i)}) f(x(i)),再和数据库中存储的 f ( x ( j ) ) f(x^{(j)}) f(x(j))进行比较即可。
如下图,用右边图片的风格去描述左边的图片。
Content©:内容图片
Style(S):风格图片
Generated(G):生成图片
本小节内容来源
在进行神经风格迁移之前,我们先来从可视化的角度看一下卷积神经网络每一层到底是什么样子?它们各自学习了哪些东西。
以Alex网络为例子:
首先来看第一层隐藏层,遍历所有训练样本,找出让该层激活函数输出最大的9块图像区域;然后再找出该层的其它单元(不同的滤波器通道)激活函数输出最大的9块图像区域;最后共找9次,得到9 x 9的图像如下所示,其中每个3 x 3区域表示一个运算单元。
可以看出,第一层隐藏层一般检测的是原始图像的边缘和颜色阴影等简单信息。
继续看CNN的更深隐藏层,随着层数的增加,捕捉的区域更大,特征更加复杂,从边缘到纹理再到具体物体。
定义代价函数为 J ( G ) J(G) J(G), J ( G ) J(G) J(G)由两部分组成:
J ( G ) = α ⋅ J c o n t e n t ( C , G ) + β ⋅ J s t y l e ( S , G ) J(G)=α\cdot J_{content}(C,G)+β\cdot J_{style}(S,G) J(G)=α⋅Jcontent(C,G)+β⋅Jstyle(S,G)
J c o n t e n t ( C , G ) J_{content}(C,G) Jcontent(C,G)表示C和G之间内容的相似程度, J s t y l e ( S , G ) J_{style}(S,G) Jstyle(S,G)表示S和G之间风格的相似程度。
接下来要做的是:
具体例子如下图:
C和S图:
梯度下降过程:
神经风格迁移学习的是G的像素值
先看看代价函数中的 J c o n t e n t ( C , G ) J_{content}(C,G) Jcontent(C,G):
所以 J c o n t e n t ( C , G ) J_{content}(C,G) Jcontent(C,G)可定义为:
J c o n t e n t ( C , G ) = 1 2 ∣ ∣ a [ l ] ( C ) − a [ l ] ( G ) ∣ ∣ 2 J_{content}(C,G)=\frac {1}{2}||a^{[l](C)}-a^{[l](G)}||^2 Jcontent(C,G)=21∣∣a[l](C)−a[l](G)∣∣2
接下来使用梯度下降调整G,使 J c o n t e n t ( C , G ) J_{content}(C,G) Jcontent(C,G)达到最小。
将图片的风格定义为 l l l层中各个通道之间激活函数值的相关系数(乘积)。即定义风格为通道之间的相关性
例如:
CNN如下图所示:
我们取出第 l l l层隐藏层的输出,假设di l l l层的通道数是5,第 l l l层隐藏层的输出为如下图所示:
每个通道提取图片的特征风格不同,如下图所示第一个通道获取的是图片中黄色风格特征,第二个获取的是图片中垂直纹理特征。
这两个通道的相关性可以理解为:
当有垂直条纹的地方,都是黄色的,那么正相关性很高。
在这里将两个通道值乘积之和
表示为两个通道之间的相关性系数。因为有黄色和垂直的时候,两个值都会很高,乘积也会很高。
所以定义风格矩阵(style matrix)为:
G k k ′ [ l ] = ∑ i = 1 n H [ l ] ∑ j = 1 n W [ l ] a i j k [ l ] a i j k ′ [ l ] G^{[l]}_{kk'}=\sum\limits_{i=1}^{n^{[l]}_H}\sum\limits_{j=1}^{n^{[l]}_W}a^{[l]}_{ijk}a^{[l]}_{ijk'} Gkk′[l]=i=1∑nH[l]j=1∑nW[l]aijk[l]aijk′[l]
所以 G [ l ] ( S ) G^{[l](S)} G[l](S)代表了S图第 l l l层的风格, G [ l ] ( G ) G^{[l](G)} G[l](G)代表了G图第 l l l层的风格。想要风格相近,就是要拉近这两个矩阵的距离,所以 J s t y l e [ l ] ( S , G ) J^{[l]}_{style}(S,G) Jstyle[l](S,G)可以定义为:
J s t y l e [ l ] ( S , G ) = 1 2 ⋅ n H [ l ] ⋅ n W [ l ] ⋅ n C [ l ] ∑ k = 1 n C [ l ] ∑ k ′ = 1 n C [ l ] ∣ ∣ G k k ′ [ l ] [ S ] − G k k ′ [ l ] [ G ] ∣ ∣ F 2 J^{[l]}_{style}(S,G)=\frac {1} {2 \cdot n^{[l]}_H\cdot n^{[l]}_W\cdot n^{[l]}_C}\sum\limits_{k=1}^{n^{[l]}_C}\sum\limits_{k'=1}^{n^{[l]}_C}||G^{[l][S]}_{kk'}-G^{[l][G]}_{kk'}||^2_F Jstyle[l](S,G)=2⋅nH[l]⋅nW[l]⋅nC[l]1k=1∑nC[l]k′=1∑nC[l]∣∣Gkk′[l][S]−Gkk′[l][G]∣∣F2
为了提取更多的风格,我们可以使用多层的风格矩阵相加计算风格代价函数,所以风格代价函数可以表示为:
J s t y l e ( S , G ) = ∑ l λ [ l ] ⋅ J s t y l e [ l ] ( S , G ) J_{style}(S,G)=\sum\limits_{l}λ^{[l]}\cdot J^{[l]}_{style}(S,G) Jstyle(S,G)=l∑λ[l]⋅Jstyle[l](S,G)
n维的就用n维的filter进行卷积
2 D 2D 2D到 1 D 1D 1D:
心电图