本系列文章是吴恩达深度学习攻城狮系列课程的笔记,分为五部分。
这一章讲了卷积神经网络相关的知识。
我的笔记不同于一般的笔记,我的笔记更加凝练,除了结论以及公式,更多的是对知识的理解,结合课程可以加速理解,省去很多时间,但是请注意,笔记不能替代课程,应该结合使用。
结构化机器学习项目,我建议放在最后看。
首先学这一节对你后面的学习没有影响,我就是跳过去学的。而且他更多的讲的是策略,尤其是举了很多后面的例子,你听了不仅不太好懂,而且没啥意思,所以我建议放在最后看。
神经网络与深度学习(Neural Networks and Deep Learning)
改善深层神经网络:超参数调整,正则化,最优化(Hyperparameter Tuning)
卷积神经网络(Convolutional Neural Networks)
序列模型与循环神经网络(Sequence Models)
结构化机器学习项目(Structuring Machine Learning Projects)
本章我不打算按着讲课顺序记录,而是按着便于复习的顺序。
理论上仅仅一个卷积层+池化层+一个logistic/softmax层就够了,但是加上全连接层的表现还是会更好。
卷积层可以类比神经网络:
卷积层理解:
池化层:
池化层其实就是一个固定的函数,将卷积后的图片进行进一步的处理,缩小,提取,然后变成一个 X ( i ) X^{(i)} X(i)向量。
全连接层:
这个就和我们前面的接上了。
卷积层的处理就是用filters去卷积图片,然后添加偏差,最后应用激活函数去非线性化。这个完全类似于经典神经网络,核心思路都是多参数。
这些层一般简称Conv layer
概述:
目前有一个大前提就是,一张图片的参数太多,一方面占据过多资源,另一方面没有足够的样本量以至于容易过拟合。
还有就是,人识别一个东西不会去一个像素一个像素地看,我们人类是要提取主要特征的,所以这就涉及到特征提取。
卷积就是将一个卷积核/过滤器(kernal/filter)覆盖到图像上,然后进行element-wise运算,再求和,将一个卷积核面积的图像变成一个像素,然后逐像素移动,直到遍历完整个图像。
实际上,我们计算机里的“卷积”实际上是互相关(cross-correlation),真正的数学意义上的卷积,是在cross-correlation之前先对filter沿着副对角线进行镜像翻转(flip)。
卷积的原理:
以 [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix} 1 & 0 & -1 \\ 1 & 0 & -1 \\ 1 & 0 & -1 \\ \end{bmatrix} ⎣ ⎡111000−1−1−1⎦ ⎤和 [ a b c a b c a b c ] \begin{bmatrix} a & b & c \\ a & b & c \\ a & b & c \\ \end{bmatrix} ⎣ ⎡aaabbbccc⎦ ⎤举例
原理的推广理解:
卷积是有一些缺点的:
解决方法——padding:
我们为卷积过程再添加一个参数:stride
跨越的步长会使得最后的生成成比例的缩小,体现在公式上就是分母+向下取整(round down)作用:
生成的尺寸 = ⌊ n + 2 p − f s ⌋ + 1 生成的尺寸=\lfloor\dfrac{n+2p-f}{s}\rfloor+1 生成的尺寸=⌊sn+2p−f⌋+1
3D卷积:
这个其实也仅仅是增加了一个通道(channel)的维度,对于图片就是RGB三通道,卷积核就变成三个通道叠加。计算方法也就是和2D的一样,elem-wise相乘再求和。
最后,3D*3D=2D
Multiple Filters:
无论是3D还是kD的卷积,最后只生成了一张2D平面,我们还可以继续增加维度,就是卷积核的数量。
比如我同时使用horizontal和vertical和45°的卷积核,这时就把这些堆叠起来。
最后总结一下维度:
我们使用C来表示Channels,那么卷积操作就是
n × n × n C ∗ f × f × n C ⋯ n × n × n C ∗ f × f × n C = ( n − f ) + 1 × ( n − f ) + 1 × n C ′ n\times n\times n_C * f\times f\times n_C \\ \cdots \\ n\times n\times n_C * f\times f\times n_C \\ =(n-f)+1\times(n-f)+1\times n_C^\prime \\ n×n×nC∗f×f×nC⋯n×n×nC∗f×f×nC=(n−f)+1×(n−f)+1×nC′
其中, n C ′ = 卷积核数量 n_C^\prime=卷积核数量 nC′=卷积核数量
而 n C n_C nC这一维度,不论是通道数量还是卷积核数量,通常被叫做3维立方体的深度(depth of 3D volume)
池化是一个没有学习参数,只由超参数决定的作用过程。其目标是进一步提取特征,缩小尺寸。
作用方式同样是用一个过滤器去覆盖,作用。但是过滤器是分别对每一个通道独立作用,所以如果输入时3D,那么输出也是3D,这是和卷积最大的不同。
重点用max-pooling,后面的例子也都是max-pooling。作用方式是取过滤器面积中最大的那个作为结果。虽然average-pooling也有用,但是不常用,多用于深卷积层网络。
池化层通常叫pool layer
没有可以学习的参数
但是average不被常用,大概是特征提取不够强烈。当然,这个还是可以用在很深的网络中,防止过拟合(我猜的效果)
池化还涵盖一个概念就是展开,将池化后的3D特征转化为1D的向量,便于投喂到全连接层。
卷积层和池化层是可以交错搭配的。一种经典的方案就是一个卷积层配一个池化层,称作一个Layer1,Layer2以此类推。
然后经过最后一步flattening,生成的向量样本就可以投入到全连接层了,我们称全连接层为FC3,FC4,以此类推。
经过全连接层,最后给一个sigmoid或者是soft-max层做出判断。
可以表示为:Conv-Pool-Conv-Pool-flatten-FCs-Soft-max
另一种常见的方式就是:Convs-Pool-Convs-Pool-flatten-FCs-soft-max
从这里就可以看出,这些层的变量都可以用W和B来表示。不过总的来说,卷积层的参数要远少于全连接层。
而且貌似FCs层,神经元个数会逐渐减少,大概是特征逐渐归纳。
首先就是,逐像素判断太费事儿而且,生物上,我们也不是逐个像素去识别的,而是通过特征。
而卷积层的参数相比于全连接层是真的少,原因如下:
搞研究的灵感,很多来源于他人的成果。而且相同的结构可能对不同的任务起效果。
阅读顺序建议AlexNet - VGG-16 - LeNet-5
[LeCun et al.,1998. Gradient-based learning applied
to document recognition]
架构
Conv-Pool-Conv-Pool-FC-FC-SoftMax
Convs-Pool-Convs-Pool-FC-FC-SoftMax
解读:
[Krizhevsky et al., 2012. ImageNet classification with deep convolutional neural networks]
架构:
Conv-MaxPool-SameConv-MaxPool-SameConv × \times × 3-MaxPool-FC × \times × 3-SoftMax
解读:
[Simonyan & Zisserman 2015.Very deep convolutional networks for large-scale image recognition]
架构:
SameConv[n=64] × \times × 2 - MaxPool - SameConv[n=128] × \times ×
2 - MaxPool - SameConv[n=256] × \times × 3 - MaxPool - SameConv[n=512] × \times × 3 - MaxPool - SameConv[n=512] × \times × 3 - MaxPool - FC - FC - SoftMax
解读:
[He et al., 2015. Deep Residual Networks for Image Recognition]
深层网络难以训练的原因之一就是梯度爆炸和梯度消失(vanishing)。残差网络可以有效解决这种问题,让我们可以训练100层级别的神经网络。
随着深度加深,一般的神经网络的效果会呈现一个v型变化,但是ResNet可以适应更深的网络。
从 A [ l ] 到 A [ l + 2 ] A^{[l]}到A^{[l+2]} A[l]到A[l+2]要经过linear+nonlinearity+linear+nonlinearity的作用。我们直接将两层网络合并为一个残差块。
所以公式把
Z [ l + 1 ] = W [ l + 1 ] A [ l ] + B [ l + 1 ] A [ l + 1 ] = g ( Z [ l + 1 ] ) Z [ l + 2 ] = W [ l + 2 ] A [ l ] + B [ l + 2 ] A [ l + 2 ] = g ( Z [ l + 2 ] ) Z^{[l+1]}=W^{[l+1]}A^{[l]}+B^{[l+1]} \\ A^{[l+1]}=g(Z^{[l+1]})\\ Z^{[l+2]}=W^{[l+2]}A^{[l]}+B^{[l+2]} \\ A^{[l+2]}=g(Z^{[l+2]})\\ Z[l+1]=W[l+1]A[l]+B[l+1]A[l+1]=g(Z[l+1])Z[l+2]=W[l+2]A[l]+B[l+2]A[l+2]=g(Z[l+2])
中的最后一个变为
A [ l + 2 ] = g ( Z [ l + 2 ] + A [ l ] ) A^{[l+2]}=g(Z^{[l+2]}+{A^{[l]}})\\ A[l+2]=g(Z[l+2]+A[l])
理解:
因为有一个矩阵相加,所以应该统一维度。
[Lin et al., 2013. Network in Network]
f=1的卷积,也有用。
理解:
应用:
背景:
在构建卷积层的时候,你要思考使用什么尺寸的filter。
Inception要解决两个问题:
Inception Block的构建细节:
[插入图片]
基本思想:
把各种尺寸的filter和Pool层产生的结果直接拼起来,然后由神经网络来学习权重,实现自动决策。
加法和乘法数量差不多,所以就用乘法数量来代表开销。
对于一个卷积操作,生成了一个 n × n × n c [ l ] n\times n\times n_c^{[l]} n×n×nc[l]的volume, 使用的是 f × f × n c [ l − 1 ] f\times f\times n_c^{[l-1]} f×f×nc[l−1],volume的每一个方块都是由一次卷积重叠操作生成的,每一次重叠,都有 f × f × n c [ l − 1 ] f\times f\times n_c^{[l-1]} f×f×nc[l−1]次乘法,然后生成这么多块,总共的开销实际上很简单
就是 A [ l − 1 ] A^{[l-1]} A[l−1]的尺寸 × \times × W [ l ] W^{[l]} W[l]的尺寸,即输入样本的三个维度 × \times ×过滤器的三个维度。
举个例子:
先用1=f的卷积(这一个步通常被叫做瓶颈层bottleneck layer)压缩信道数量,将尺寸减少,然后再用一个卷积扩大信道数量。
从例子上来看,把一个卷积层拆成两个,可以将大×大转化成小×小+小×小,实现保留性能的前提下,降低成本,同时能够减少(shrink down)参数数量。
[插入图片]
神经网络尴尬的地方在于,复现难度比较高,因为条件不一样,你的GPU,初始化等等。
主要是git,windows的安装与配置PATH都比较容易搞定,然后git clone URL即可。
但是需要注意的是,网上没有找到配置默认clone 目录的地方,所以如果用cmd的话,先cd 到合适的目录再clone,不然位置比较尴尬,整到默认根目录了。东西一多,就不好管理。
说白了就是用别人已经训练好的东西或者预训练好的模型,去魔改。省事,不用痛苦地寻找最优参数。
如果你样本不多:
你可以把别人的模型下载好,然后就是用别人的模型再和你的浅层拼一下,就可以实现你自己的模型了。
目前框架已经实现了冻结特定层权重的操作,可以把别人的模型冻结,然后只训练你自己的,这样就可以用小样本来训练。
另一个技巧就是,既然你已经冻结前面的了,那你就可以直接计算出 A [ L ] A^{[L]} A[L]做为你的 X ′ X^\prime X′,就省去了反复计算一个相同值的过程(我感觉框架可以把这个功能内置进去)
如果你有大量样本:
那就少冻结点,或者自己的层多弄点,直到最后解冻所有,然后把他的权重作为initialization。
如果有巨量样本:
自己训练from scratch,一般这种的也不缺GPU。
总之:
还是样本量和参数量要匹配。
详见视频。
首先区分几个概念:
定位原理:
以左上角为(0,0),右下角为(1,1),定位就是给soft-max层再加四个输出表示边框,边框的参数为 b x , b y , b h , b w b_x,b_y,b_h,b_w bx,by,bh,bw,因此,标签还要加上位置的四个参数。
具体的标签: [ P C b x b y b h b w c 1 c 2 ⋯ c C − 1 ] \begin{bmatrix} P_C \\ b_x \\ b_y \\ b_h \\ b_w \\ c_1 \\ c_2 \\ \cdots \\ c_{C-1} \end{bmatrix} ⎣ ⎡PCbxbybhbwc1c2⋯cC−1⎦ ⎤
第一个参数为是否有物体,有就是1,然后跟着坐标,以及类别。没有就是0,后面的数没有意义,应该是任意的。
损失函数:
L ( y ^ , y ) = { ∣ ∣ y ^ − y ∣ ∣ 2 2 , y 1 ( P C ) = 1 ,有对象,对比全体 ( y ^ 1 − y 1 ) 2 , y 1 = 0 ,只有背景,仅仅对比背景判断 L(\hat{y},y)= \begin{cases} ||\hat{y}-y||_2^2 &, y_1(P_C)=1,有对象,对比全体\\ (\hat{y}_1-y_1)^2 &, y_1=0,只有背景,仅仅对比背景判断\\ \end{cases} L(y^,y)={∣∣y^−y∣∣22(y^1−y1)2,y1(PC)=1,有对象,对比全体,y1=0,只有背景,仅仅对比背景判断
需要注意的是,这里的L函数是简写了,实际上还可以分成三个部分写,第一个就是 P c P_c Pc用交叉熵,然后坐标用差平方和,类别用交叉熵。
特征点识别(Landmark Detection):
这个是比边框检测更加精细的识别,比如眼角,嘴角等等特征。有了特征点,可以进行很多操作,比如识别人的表情,姿势,p脸。
至于标签,类似于目标定位,第一个是有没有目标,然后剩下的就是特征点坐标的顺次排列。
注意要保持特征点类别一致,这个也很好理解,不能教错对吧。
指定方框大小和步长,然后遍历图片,每次裁剪出一个小块去分类检测分类。
这个有一个巨大的问题就是,计算成本,以前用线性分类器的时候还比较快速,但是现在卷积神经网络计算一次成本比较高,所以需要替代方案。
论文参考[sermanet et.al.,2014,OverLeaf: Integrated recognition,localization and detection using convolutional works]
将卷积神经网络的FC层转化成卷积层。其实就是用一个和原图片同样大小的volume去进行卷积,效果等同于全连接的计算,都是乘一个系数然后求和,然后有多少个神经元就用多少个filter。
我们训练用的图片大小都是相等的,比如14 × \times × 14,问题来了,如果来一张16 × \times × 16的,会有什么结果?配合特定大小的MaxPool,就可以实现类似于滑动窗口遍历的效果。
比如我们原来是生成一个 1 × 1 × n 1\times 1\times n 1×1×n的结果向量,如果我们用这种方式,最后就会生成 m × m × n m\times m\times n m×m×n大小的volume, m × m m\times m m×m 就是所有滑动窗口的数量。
这种方式可以提高效率的原因有一点类似于动态规划,可以避免重复计算,不同的window可以共享一片区域的计算结果。
但是这个还有一个问题就是,我们这个其实仅仅是分类而已(但我觉得也可以同时计算边框位置,但是成本或许太大了?),真实的轮廓和我们的windows往往不重叠,而且我们用的还是方块,真实情况不一定是方块,所以下一步要让定位和尺寸更加准确,优化/换一种方法。
[Redmon et al.,2015,You Only Look Once:Unified real-time object detection]
这篇文章是著名的YOLO算法的出处(据说难度不小,比较玄学)。
这个和前面的slide windows是两个不同的东西,只不过都用到了用卷积加速分块操作。
核心思路就是,将前面的Classification with Localization一次性运用到图片切分后的grid中,至于一次性计算所有分块,就通过卷积来实现。
具体思路就是,slide windows不是会有重叠部分嘛,我们这个对图片做一个划分,将每一个块看做独立的图。用卷积操作计算出 m × m × n m\times m\times n m×m×n的结果,因为图片块少,所以我们的n的维度可以多一些,加上坐标和方框大小。
给我的感觉就是,是一种加强版的slide windows,去除了重叠部分,只进行划分,同时计算的更精细,这样又准速度又快,可以达到实时(real-time)。
需要注意的是,在制作标签的时候, b H , b w b_H,b_w bH,bw完全可以>1,因为虽然把小块看做图片,但是不是真正独立的图。
本算法用于评估检测算法,基于这个算法可以用来优化检测算法。
字面意思, 交集 并集 \dfrac{交集}{并集} 并集交集,这个函数比较有意思,相同的预测,交并比的结果<交预比。他的变化更剧烈,因此0.5就不错了,可以视作正确。
除了识别不出,还可能发生一个对象被不同的块重复识别,尤其是切得太小的时候,每个小块都觉得自己是物体中心。
如果没有措施,会产生很多框,以下操作不考虑类别:
如果考虑类别,就用类别分类,然后分别进行单类别的non-max suppression
切割太细容易导致多个框出现同一个物体,这个问题通过non-max suppression来解决。
切割太大容易导致一个框出多个物体,这个问题用到Anchor Boxes。
一般来说,这种问题很少出现,所以我们假设最多出现两个物体(极端情况可以增加Anchor Box,我们可以针对性定制)
但是我们也可以看出,如果两个物体都是同一类Anchor Box,那么仍然无法解决。
综合上面的操作,我们来举个例子。
[Girshik et.al,2013,Rich feature hierarchies for accurate object detection and semantic segmentation]
这个在b站上貌似是丢失了一些视频,就简单记录一点。
R-CNN思路:
其实我感觉这个才更像是人眼判断,首先是用连续区域来着色,一个色块就是一个区域,然后对这种区域内进行卷积判断。
这样可以省去很多计算,毕竟,人眼是先找到哪个区域有东西,再进行分类的。但是实际运用的时候,这个还是比YOLO慢很多。不过总的来说,这个引起了广泛的关注
人脸识别的一个挑战就是,单个样本情况下的识别表现并不是很好,这也是为什么我们平时人脸识别都要动动嘴啥的。
一方面,小样本训练不出具有鲁棒性的网络,另一方面,如果用soft-max输出,要加人怎么办?不太好扩容。
所以要弃用soft-max,用新的判断方式:
新的函数为d(img1,img2)=两张图片差异度大小,然后设置一个阈值 τ \tau τ,如果超过这个阈值,就不是一个人。这种图对图的判断具有好的扩充性。
[Taigamen et.al.,2014.DeepFace closing the gap to human level performance]
如何去训练我们上面说的d函数呢?
我们搭建一个网络,输出一个vector,那么这个网络的作用相当于将一个图片转化成一个向量,用来精准表示一个图片的主要特征,写成 f ( x ) f(x) f(x)
由此,可以定义 d ( x ( 1 ) , x ( 2 ) ) = ∣ ∣ f ( x ( 1 ) ) − f ( x ( 2 ) ) ∣ ∣ 2 2 d(x^{(1)},x^{(2)})=||f(x^{(1)})-f(x^{(2)})||_2^2 d(x(1),x(2))=∣∣f(x(1))−f(x(2))∣∣22
问题由训练d转化成训练f函数,我们需要定义一个损失函数。
[Schroff et al.,2015,FaceNet:A unified embedding for face recognizing and clustering]
我们要训练f函数,要有三张图片,Anchor,Positive,Negative,简称(abbreviate)为A,P,N。
我们要实现这个效果,令AP差距尽可能小于AN差距, α \alpha α越大,这个差距就越大。
如果实现了,就是成功,准确识别。
α \alpha α作为一个超参数,如果太小,太容易满足,就容易误判,即不是同一个人也判断为同一个人,如果太大,不容易满足,就会将同一个人判断成不同的人。
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 + α ≤ ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 ||f(A)-f(P)||^2+\alpha \leq ||f(A)-f(N)||^2 ∣∣f(A)−f(P)∣∣2+α≤∣∣f(A)−f(N)∣∣2
因此,我们定下这个损失函数,如果达到前面的效果,就视为0损失,否则就是正损失。
L ( A , P , N ) = m a x ( ∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 + α − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 , 0 ) = R e L U ( ∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 + α − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 ) L(A,P,N)=max(||f(A)-f(P)||^2+\alpha -||f(A)-f(N)||^2 , 0) \\ =ReLU(||f(A)-f(P)||^2+\alpha -||f(A)-f(N)||^2 ) L(A,P,N)=max(∣∣f(A)−f(P)∣∣2+α−∣∣f(A)−f(N)∣∣2,0)=ReLU(∣∣f(A)−f(P)∣∣2+α−∣∣f(A)−f(N)∣∣2)
对应的cost function:
J = 1 m ∑ i = 1 m L ( A ( i ) , P ( i ) , N ( i ) ) J=\dfrac{1}{m}\sum_{\mathclap{i=1}}^{m}L(A^{(i)},P^{(i)},N^{(i)}) J=m1i=1∑mL(A(i),P(i),N(i))
下面问题就又来了,样本怎么做?
一个样本就是一个三元组。
假设给你10k个图片,对应1k个人,那么平均1人有10张图,我们可以随机提取图片构成三元组。但是这样训练的不够好,我们可以优化一下,专门挑难的来训练。
现在的人脸识别系统都是基于大数据的,可以选择拿别人现成的模型来看。
除了Triplet Loss,其实还有一种直观的方式去衡量差距并训练f函数。
按我的第一印象来看,我感觉Triplet有点多余,因为实际上就相当于用A作为PN差距的参考系,用PA-NA,来间接反映PN差距,将其调整到 α \alpha α以上。为什么就不能直接算PN的差距呢?
虽然还没有理解Triplet的核心,但是二分类给出了另一条直接算差距的路。
首先定义样本,是二元组,将二元组输入进去,得到 f ( x ( i ) ) , f ( x ( j ) ) f(x^{(i)}),f(x^{(j)}) f(x(i)),f(x(j)),计算得向量 v e c t o r = ∣ f ( x ( i ) ) − f ( x ( j ) ) ∣ vector=|f(x^{(i)})-f(x^{(j)})| vector=∣f(x(i))−f(x(j))∣,然后把这个向量扔到一个logistic单元里判断即可。
至于损失函数和成本函数,就用logistic即可
公式可以调整,只要表现出差距那个意思即可,然后从中找出最好用的公式。
[Gatys et al.,2015.A neural algorithm of artistic style.]
简单说,神经风格转换,就是将一个风格(style)加到另一个内容(content)上,生成一个图片(generate),风格提供了色彩等元素,内容提供了轮廓。
滤镜貌似和这玩意有关系。
[Zeiler and Fergus.,2013,Visualizing and understanding convolutional networks]
第一层卷积可以提取轮廓,那么深层的在干什么?
随着卷积和池化的进行,图片尺寸会越来越小,这意味着图片蕴含的信息区域越来越大,也就是观察的维度越来越高,并且在不断寻找突出特征。
比如第一层提取了一些角度的线段。第二层可能会提取一些形状,比如纹路,圆形等等。后面就越来越广。第三层可能就给你合成一个耳朵,同层的filter负责其他特征,比如给你弄一个嘴出来。有了第三层的耳朵和嘴等特征,可能第四层就整出个脸来,第五层就给你弄出个人。
最后就是,观察的范围越来越大,维度越来越多,最后变成一个细长的东西,可以作为后面训练的输入。
我们的目标就是让生成的G与C的内容尽可能相似,与S的风格尽可能相似。
J ( G , C , S ) = α J c o n t e n t ( C , G ) + β J s t y l e ( S , G ) J(G,C,S)=\alpha J_{content}(C,G)+\beta J_{style}(S,G) J(G,C,S)=αJcontent(C,G)+βJstyle(S,G)
其实用一个 α \alpha α就够了,毕竟我们只是用一个相对比例,然而作者用了两个,我们就用两个,这表明了图片更趋向于哪个。
之后就是梯度下降了,实际上梯度下降的过程就是将初始的白噪音图片逐步调整成我们要的部分。
请注意,我们训练的不是神经网络,而是图片的像素,神经网络是拿来且冻结的,仅仅是用来提取一定深度的特征用来对比的。
我们需要控制网络的深度,如果比较浅,那么在内容上就会导致GC的像素过于趋同,如果比较深,就会导致GC的物体过于趋同,比如C中有个狗,G中就得有个狗。
适当的深度,可以保证有个形状又不至于完全挪过去。
内容比较简单,我们就弄一个预训练好的网络比如VGG,然后直接对比最后一层输出的区别,让最后一层越相近越好,深度控制的好,那么我们对比的特征就越准确。
J c o n t e n t [ l ] ( C , G ) = ∣ ∣ a [ l ] ( C ) − a [ l ] ( G ) ∣ ∣ 2 J_{content}^{[l]}(C,G)=||a^{[l](C)}-a^{[l](G)}||^2 Jcontent[l](C,G)=∣∣a[l](C)−a[l](G)∣∣2
这里默认将矩阵展开为vector,所以我们用2范数(如果用矩阵就是F范数,这不统一属实别扭)
这里吴恩达只用最后输出的向量处理了,我个人感觉其实可以用所有层的一个均值,比如定义:
J c o n t e n t ( C , G ) = ∑ l λ [ l ] J c o n t e n t [ l ] ( C , G ) J_{content}(C,G)=\sum_{\mathclap{l}}\lambda^{[l]}J_{content}^{[l]}(C,G) Jcontent(C,G)=l∑λ[l]Jcontent[l](C,G)
权重 λ [ l ] \lambda^{[l]} λ[l]根据不同的层来设定,取决于你最想要统一哪个级别的内容。
风格的定义:
风格这个东西比较玄乎,你说内容把,就单纯像素的轮廓,形状即可,但是风格就比较复杂。
我们将风格定义为某一层的不同channel之间的相关度(correlation)
进一步理解,风格说白了就是,A出现,B,C就应该伴随出现,比如汉服出现,那么袖子下摆或者刺绣等大概率都会出现,这就是一种典型的风格。
那么放到不同的channel之间,channel是分块的,每一小块就对应一个部位或者特征,这个特征要伴随另一层的某个特征,我们的目的是将这些特征绑定起来,也就是提高相关度,提高同时出现的概率。
风格的数学表示——Style Matrix:
首先定义 a i , j , k [ l ] a^{[l]}_{i,j,k} ai,j,k[l]为l层的i行j列k信道的元素。
然后定义风格矩阵 G [ l ] − n C [ l ] × n C [ l ] G^{[l]}-n_C^{[l]}\times n_C^{[l]} G[l]−nC[l]×nC[l],其两个维度代表信道,这个很像我之前做过的R语言数据分析的作业,其中就有一个协方差(cross-covariance)矩阵,也就是说,这其中的每一个元素都应该是某两个信道之间,类似于协方差 C o v ( X , Y ) = E [ X Y ] − E [ X ] E [ Y ] Cov(X,Y)=E[XY]-E[X]E[Y] Cov(X,Y)=E[XY]−E[X]E[Y]的东西
实际上,元素为:
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^\prime}=\sum_{\mathclap{i=1}}^{n^{[l]}_H}\sum_{\mathclap{j=1}}^{n^{[l]}_w}a^{[l]}_{i,j,k}a^{[l]}_{i,j,k^\prime} Gkk′[l]=i=1∑nH[l]j=1∑nw[l]ai,j,k[l]ai,j,k′[l]
也就是,第k信道和 k ′ k^\prime k′信道的两个矩阵进行elem-wise的乘积求和,和协方差的区别就是没有减去均值
理解style matrix:
a代表突出特征,如果在两个信道同一个位置都有突出特征,那么大概率这两个信道有联系,所以,这种同位置同特征的元素越多, G k k ′ [ l ] G^{[l]}_{kk^\prime} Gkk′[l]就越大,意味着就有强联系,也就是我们说的风格。
说白了,这个G矩阵,就是表达了l层位置,我们这张图片不同信道之间的联系程度。G就可以代表图片在l层的风格!
计算风格的区别:
说白了矩阵不就是G和S的风格矩阵差的F范数嘛。
J s t y l e [ L ] ( S , G ) = 1 ( 2 n H [ l ] n W [ l ] n C [ l ] ) 2 × ∣ ∣ G [ L ] [ S ] − G [ L ] [ G ] ∣ ∣ F 2 J^{[L]}_{style}(S,G)=\dfrac{1}{(2n_H^{[l]}n_W^{[l]}n_C^{[l]})^2}\times ||G^{[L][S]}-G^{[L][G]}||^2_F \\ Jstyle[L](S,G)=(2nH[l]nW[l]nC[l])21×∣∣G[L][S]−G[L][G]∣∣F2
我们前面只是用了一层,事实上,如果你想彻底统一一下,那么可以让所有层数的风格都统一了,也就是对1-L层的所有层的 J [ l ] J^{[l]} J[l]参数化加权平均。前面的系数可以控制不同层之间统一的比例。
J s t y l e ( S , G ) = ∑ l λ [ l ] J s t y l e [ l ] ( S , G ) J_{style}(S,G)=\sum_{\mathclap{l}}\lambda^{[l]}J_{style}^{[l]}(S,G) Jstyle(S,G)=l∑λ[l]Jstyle[l](S,G)
最后做个总结:
1D卷积,2D卷积,3D卷积都是一样的:
也就是说,1D,3D的数据也都是可以用卷积神经网络的,比如1D的心电图数据,音频文字,3D的CT片,可以检测器官病变啥的,视频段可以检测动作,行为之类的
格局打开好吧!