基于Tensorflow学习神经网络-CNN

5. CNN(卷积神经网络层)
CNN的强大之处在于它的多层结构能自动学习特征,并且可以学习到多个层次的特征:较浅的卷积层感知域较小,学习到一些局部区域的特征;较深的卷积层具有较大的感知域,能够学习到更加抽象一些的特征。这些抽象特征对物体的大小、位置和方向等敏感性更低,从而有助于识别性能的提高。
权重初始化
http://www.mamicode.com/info-detail-1835147.html
http://blog.csdn.net/app_12062011/article/details/57956920
https://zhuanlan.zhihu.com/p/25110150
不能都初始化为0。因为如果所有的参数都是0,那么所有神经元的输出都将是相同的,那在back propagation的时候同一层内所有神经元的行为也是相同的。
独立随机变量乘积方差
乘积方差公式推导:
令,当只有W是0均值,则有:
(MSRA初始化,以此为基础进行推导)
特别当W,x都是0均值,则有:
 (Xavier初始化用该假设为前提进行证明,可以初始化w为0均值,x用BN层服从N(0,1),但BN层后面加激活函数后数值分布有变化,尤其RELU去掉负向数值。所以就Xavier的假设而言,不适用RELU激活)
卷积
: y 是当前层所有输出,W是所有神经元的权重(w_m×w_n),X是对应输出周围的掩模区域内输入,b是偏置项。展开后,注:n = w_m×w_n×n_i,即卷积核的大小和当前层输入的神经元个数。如假设输入3通道图像,第一层卷积核5*5,则第一层n = 5*5*3;如果第一层神经元个数为32,第二层卷积核3*3,则第二层n=3*3*32。
假设同一层中权重W和X相互独立,不同神经元的W同分布,不同输入图像X同分布(一般初始化均满足),两边求方差:。
当b的方差=0时,则有(Xavier 和MSRA初始化,以此为基础进行推导)。
疑问:初始化推导中没写b,是否b必须=0???
初始化
tf.random_uniform    从均匀分布中返回随机值
tf.random_normal    从正态分布输出随机值。
tf.truncated_normal    截断的正态分布函数。生成的值遵循一个正态分布,但不会大于平均值2个标准差。
tf.random_shuffle     沿着要被洗牌的张量的第一个维度,随机打乱。
传统的固定方差的高斯分布初始化,在网络变深的时候使得模型很难收敛。改进如下………
Xavier初始化(2010)
http://blog.csdn.net/app_12062011/article/details/57956920
假设激活函数是线性的:
将以均匀分布的方式在的范围内对权重w进行初始化(m,n为前后两层维度)。
简单说明:从线性传播上考虑(也是使推导成立的前提)。为了保证前向传播和反向传播时每一层的方差一致,且输入和权重都是0均值时 (w -0均值,x-需白化||归一化,第一层白化后面没有做,BN层若在激活层前,relu显然不符合。sigmoid和tanh较为接近),应满足:
为了保证前向传播和反向传播时每一层的方差一致,应大约满足(实际当中输入与输出的个数往往不相等,为均衡考虑):
则Xavier初始化均匀分布(此处m,n同ni,ni+1);
正态分布也一样能用,范围N(0,)。注意:标准差(std)=
前向信息的传播更重要一些,默认只考虑输入
如果激活函数使用sigmoid和tanh,最好使用xavir….
MSRA初始化(2015.2)
http://blog.csdn.net/shuzfan/article/details/51347572#motivation
https://arxiv.org/pdf/1502.01852.pdf
对于卷积层有(i表示层数,大写W表示i层一个神经元权重矩阵,X表示输入中一个卷积区,Y表示输出的一个点)
如果权重W的均值=0,则,假设(初始化b=0),则是一个以0为中心的一个对称分布(接近,但不一定是),
那么对于Relu激活函数,有;
而PRelu激活函数,有;
(注:上面两式分正负两段计算,下面仅写Relu激活推导,PRelu同样)
则有:
同样为保证传播时每一层的方差一致,有
PRelu激活函数时,有
补充说明:第一层数据,由于其之前没有经过激活函数,因此理论上这一层的初始化方差应为1/n。
如果激活函数使用Relu,最好使用Msra.
激活函数(activation function)
https://www.cnblogs.com/rgvb178/p/6055213.html
激活函数作用:
给神经网络加入一些非线性因素,使得神经网络可以更好地解决较为复杂的问题(非线性分类)。
类似于线性回归,解决曲线拟合问题:【选择模型,曲线变直,拟合直线,还原曲线方程】
%数据模型
t = [2,5,8,11,14,17,27,31,35];
cA = [0.948,0.879,0.813,0.749,0.687,0.640,0.493,0.440,0.391];
str = char('y = ax + b','y = 1/(ax + b)', 'y = ax^b', 'y = ae^b^x');
x = [];y = [];Y = [];
%验证模型1 y = ax + b
x(1,:) = t; y(1,:) = cA;
%验证模型2 y = 1/(ax + b),曲线变直
x(2,:) = t; y(2,:) = 1./cA;
%验证模型3 y = ax^b,曲线变直,两边都取对数
x(3,:) = log(t); y(3,:) = log(cA);
%验证模型4 y = ae^bx,曲线变直,两边都取对数
x(4,:) = t; y(4,:) = log(cA);
%拟合绘制计算误差
for i=1:4,
[p,s] = polyfit(x(i,:),y(i,:),1);
Y(i,:) = p(1) * x(i,:) + p(2);
subplot(2,2,i);
plot(x(i,:),Y(i,:),x(i,:),y(i,:),'--o'),title(sprintf('方程:%s\n误差:%0.4f',str(i,:),s.normr)), grid;
end
未引入激活函数效果如下:

引入激活函数效果如下:

不同函数特性对分类效果的影响:
https://www.zhihu.com/question/22334626/answer/21036590
非线性【平滑,分段;解决非线性分类问题】
梯度【反向传播算法,根据梯度,修正权重】
当x很大或者很小的时梯度趋于饱和【梯度接近于0,导致权重更新很小,甚至无法更新,网络层数多时,影响尤为严重,不适用于多层卷积层】
函数收敛【分类-适用于输出层】
普适性【挤压性质的激活函数:sigmoid和tanh挤压输出范围(0,1);ReLU稀疏】
稀疏性【信息解离,容忍噪声更具鲁棒性,缓和过拟合问题】
梯度收敛【梯度大,收敛速度越快,训练速度越快】
常用激活函数
https://www.cnblogs.com/rgvb178/p/6055213.html
http://blog.csdn.net/u014365862/article/details/52710698
Sigmoid函数(Logisitic函数)
Sigmoid公式                 

        导数            


优点:
1.Sigmoid函数的输出映射在(0,1)之间,单调连续,输出范围有限,优化稳定,可以用作输出层。
2.求导容易。
缺点:
1.由于其软饱和性,容易产生梯度消失,网络层数多时尤为明显。
2.其输出并不是以0为中心的。
在深度网络中,如果网络的激活输出很大,其梯度就很小,学习速率就很慢。假设每层学习梯度都小于最大值0.25,网络有n层,因为链式求导的原因,第一层的梯度小于0.25的n次方,所以学习速率就慢,对于最后一层只需对自身求导1次,梯度就大,学习速率就快。 这会造成的影响是在一个很大的深度网络中,浅层基本不学习,权值变化小,后面几层一直在学习,结果就是,后面几层基本可以表示整个网络,失去了深度的意义。
关于梯度爆炸,根据链式求导法,
第一层偏移量的梯度=激活层斜率1x权值1x激活层斜率2x…激活层斜率(n-1)x权值(n-1)x激活层斜率n
假如激活层斜率均为最大值0.25,所有层的权值为100,这样梯度就会指数增加。
tanh函数
现在,比起Sigmoid函数我们通常更倾向于tanh函数。
tanh公式
导数

优点:
1.比Sigmoid函数收敛速度更快。
2.相比Sigmoid函数,其输出以0为中心。
缺点:
还是没有改变Sigmoid函数的最大问题——由于饱和性产生的梯度消失。
ReLU(2012-Rectified Linear Units)
公式         ReLU(x) = max(0,x)

优点:
1.梯度大多数情况下是常数,有助于解决深层网络的收敛问题(更快的特征学习)。
2.稀疏性缓和过拟合问题。
3.计算简答

缺点:
1、结果不收敛,不适用于输出层
2、可能导致神经元”坏死”。ReLU在x<0时梯度为0,这样就导致负的梯度在这个ReLU被置零,而且这个神经元有可能再也不会被任何数据激活。设置了一个合适的较小的learning rate,这个问题发生的情况其实也不会太频繁。
疑问:
输入层白化后x~N(0,1),Relu后只留正数,分布变化???????????????AlexNet是配合的LRN(Local Response Normalization)使用的(当时还没有BN,注意::但BN是在激活之前,不会直接修正Relu导致的数据分布变化,在激活前-修正【上层卷积输出经激活和卷积后导致的数据分布变化】)。

PreLU

为解决ReLU神经元坏死的问题的。和ReLU不同,当x<0时,它的值不再是0,而是一个较小斜率(如0.01等)的函数【斜率也可训练】。

优点:
1.解决神经元坏死问题
缺点:
1、参数增多,不稀疏,仅缩放负数
梯度下降
https://www.cnblogs.com/maybe2030/p/5089753.html
https://www.cnblogs.com/ranjiewen/p/5938944.html
http://blog.csdn.net/xierhacker/article/details/53174558    !!!!tensorflow
http://blog.csdn.net/luo123n/article/details/48239963               !!!!
http://www.360doc.com/content/16/1010/08/36492363_597225745.shtml

概念
函数极小值点(一阶导==0 && 二阶导 >0),鞍点(一阶导、二阶导==0)
先看梯度下降法求已知函数的极小值点(可能陷入鞍点),下面是一个特例:
y= x^4  -  x^3 ,显然x=0是鞍点,x=0.5是极值点,当设置学习率为0.1会陷入鞍点,0.2可能跳过鞍点,以此理解BGD可能会跳过局部极值点。
%% 梯度下降法找极值点 x^4-x^3,学习率=0.1会陷入鞍点,学习率=0.2会跳过鞍点
% 设置步长为0.1,f_change为改变前后的y值变化,仅设置了一个退出条件。
syms x;f=  x^4-x^3;
step=0.1;x=-1;k=0;             %设置步长,初始值,迭代记录数
f_change= 999;                %初始化差值
f_current=  x^4-x^3;             %计算当前函数值
subplot(2,1,1);
ezplot(' x^3')                    %画出函数图像
axis([-2,2,-1,4])         %固定坐标轴
hold on
plot(x,f_current,'ro','markersize',7) %标记当前的位置
while f_change>0.000000001         %设置条件,两次计算的值之差小于某个数,跳出循环
x=x-step*(4*x^3-3*x^2 );                       %2*x为梯度反方向,step为步长
f_change = f_current -  (x^4-x^3);      %计算两次函数值之差
f_current = x^4-x^3;                 %重新计算当前的函数值
plot(x,f_current,'ro','markersize',7) %标记当前的位置
drawnow;pause(0.01);
k=k+1;
end
hold off
fprintf('在迭代%d次后找到函数最小值为%e,对应的x值为%e\n',k, x^4-x^3,x)

step=0.2;x=-1;k=0;             %设置步长,初始值,迭代记录数
f_change= 999;                %初始化差值
f_current=  x^4-x^3;             %计算当前函数值
subplot(2,1,2);
ezplot(' x^3')                    %画出函数图像
axis([-2,2,-1,4])         %固定坐标轴
hold on
plot(x,f_current,'ro','markersize',7) %标记当前的位置
while f_change>0.000000001         %设置条件,两次计算的值之差小于某个数,跳出循环
x=x-step*(4*x^3-3*x^2 );                       %2*x为梯度反方向,step为步长
f_change = f_current -  (x^4-x^3);      %计算两次函数值之差
f_current = x^4-x^3;                 %重新计算当前的函数值
plot(x,f_current,'ro','markersize',7) %标记当前的位置
drawnow;pause(0.01);
k=k+1;
end
hold off
fprintf('在迭代%d次后找到函数最小值为%e,对应的x值为%e\n',k, x^4-x^3,x)

样本拟合,损失函数极小值点
神经网络的样本训练过程就是求损失函数极小值的过程,下面是简单直线拟合例子(平方损失函数 ):
%% 梯度下降法拟合直线y = a+bx ,即求平方损失函数极小值问题
x_data=[1;1.5;2;2.5;3];y_data=[0.9;1.7;2.2;2.6;3];
a= 2;b=2;      
y = a+b*x_data;
plot(x_data,y_data,'ro',x_data,y)          %画出函数图像
hold on
step=0.01;k=0;                  %设置步长,初始值,迭代记录数
f_current = sum((y_data-a-b.*x_data).*(y_data-a-b.*x_data)); %平方损失函数
f_change=f_current;                   %初始化差值
a_last = a;b_last = b;
while f_change>0.0001        %设置条件,两次计算的值之差小于某个数,跳出循环
a=a_last-step*(-2)*sum(y_data-a_last-b_last.*x_data);   %梯度方向为a的偏导数
b=b_last-step*(-2)*sum((y_data-a_last-b_last.*x_data).*x_data); % b的偏导数
f_change = f_current-sum((y_data-a-b.*x_data).*(y_data-a-b.*x_data));      %计算两次函数值之差
f_current= sum((y_data-a-b.*x_data).*(y_data-a-b.*x_data));
y = a+b*x_data;
plot(x_data,y)                   %画出函数图像
drawnow;pause(0.0001);
a_last = a;b_last = b;
k=k+1;
end
hold off
plot(x_data,y_data,'ro',x_data,y)
fprintf('在迭代%d次后找到最小%e,函数y=%e+%ex\n',k,sum((y_data-a-b.*x_data).*(y_data-a-b.*x_data)),a,b)


批量梯度下降法(BGD)
所有样本导数更新梯度,凸函数收敛于全局极值点,非凸函数可能会收敛于局部极值点
优点:全局最优解(但不一定是全局极值点);易于并行实现;
缺点:当样本数目很多时,内存消耗很大,训练过程也会很慢。

随机梯度下降法(SGD)
每个样本来迭代更新一次梯度,噪音较多,每次更新可能并不会按照正确的方向进行,造成梯度波动。波动可能会使优化方向从当前的局部极小值点跳到另一个更好的局部极小值点,这样便可能对于非凸函数,最终收敛于一个较好的局部极值点,甚至全局极值点。
优点:训练速度快。也正由于梯度波动有可能收敛到全局极值点。
缺点:不易于并行实现 。梯度波动使迭代次数增多。【注:需要设置较大的迭代次数】

小批量梯度下降法(MBGD)
每次更新参数时使用b个样本(b取10,100等),性能较为折中,不错的方法。。。
Δxt=−ηgt    η为学习率,gt为x在t时刻的梯度
优点:训练速度较快;当训练集有很多冗余时(类似的样本出现多次),收敛更快。
缺点:更新方向完全依赖于当前的batch,batch差别较大,同样会有波动。

引入动量Momentum
为解决MBGD更新不稳定缺陷,模拟物体运动时的惯性,引入momentum,更新方法:一定程度上保留之前更新的方向【ρΔxt−1】+利用当前batch的梯度微调的更新方向【ηΔf(xt)】。
Δxt=ρΔxt−1−ηgt
ρ 即momentum,表示要在多大程度上保留原来的更新方向,这个值在0-1之间(衰减系数,一般不大于0.9);在训练开始时,由于梯度可能会很大,所以初始值一般选为0.5;当梯度不那么大时,改为0.9。η 是学习率,即当前batch的梯度多大程度上影响最终更新方向,跟普通的SGD含义相同。ρ 与 η 之和不一定为1。
Nesterov Accelerated Gradient (Nesterov Momentum)(NAG)
修正动量思路:既然知道这次会走【ρΔxt−1】的量,那么直接走到之后的地方【xt+ρΔxt−1】,然后再根据那里的梯度再前进一下【二阶导】,岂不美哉。方法:一定程度上保留之前更新的方向【ρΔxt−1 同上】+当前batch按保留方向前进后的更新方向【ηΔf(xt+ρΔxt−1 )】
首先,按照原来的更新方向更新一步(棕色线),然后在该位置计算梯度值(红色线),然后用这个梯度值修正最终的更新方向(绿色线)。上图中描述了两步的更新示意图,其中蓝色线是标准momentum更新路径。
优点:加速Momentum方法收敛,收敛速度快
缺点:需要调参,设定不同的学习率,防止后期震荡
以上所有共有缺点:
选择一个合理的学习率η很难。如果学习速率过小,则会导致收敛速度很慢。如果学习速率过大,那么其会阻碍收敛,即在极值点附近会振荡。
所有参数都使用了同一个学习率η 。【同一个η 不一定适合所有参数。比如有的参数可能已经到了仅需要微调的阶段,但又有些参数由于对应样本少等原因,还需要较大幅度的调动】。
对于非凸目标函数,容易陷入次优的局部极值点或鞍点。


Ada grad
Adagrad针对共有缺点1、2提出的,可自适应地为各个参数分配不同学习率的算法。其公式如下:
其中η 是初始学习率,ϵ是一个比较小的数(ϵ=1e−8),用来保证分母非0。
优点: 调参相对简单。随更新的总距离增多,学习率随之变慢,初始值不像之前的算法那样重要了
         不同参数的学习率不同。【跟该参数调整幅度有关,前面调整越多,后期越小】
缺点:
需要手工设置一个全局的初始学习率
后期收敛慢。学习率是单调递减的,训练后期学习率非常小 【Adadelta解决学习速率衰减过快问题】
更新xt时,左右两边的单位不同一 ?????
RMSprop
Adagrad->Adadelta的过渡

Ada delta
解决了共有缺点1、2、3。解决Adagrad中学习率衰减过快的缺陷,只依赖前一个学习率。


        
优点: 无需设置初始学习率。
         学习率衰减不会太快。         
Amad
Adam与RMSprop相比,增加了偏差校正和动量

各个方法的比较
adagrad:收敛慢,调参简单。
momentum:收敛快,需调参。
而adagrad一方面不用怎么调参,另一方面其性能稳定优于其他方法。
各优化方法在损失曲面上的表现
各优化方法在损失曲面鞍点处上的表现
卷积和池化
https://www.cnblogs.com/believe-in-me/p/6645402.html
卷积
卷积用于提取图像特征,掩模内所有通道、所有权值做乘加操作,输出单通道。

#卷积 conv2d
#输入图像input[imgNum,imgRow,imgCol,imgChannel]
#输入滤波器filter[filRow,filCol,imgChannl,filNum]
#输入步长strides[1?,rowStep,colStep,1?]
#输入边界处理padding 'SAME'同样处理,'VALID'忽略边界
#输出特征feature[imgNum, ceil(imgRow/rowStep),ceil(imgCol/colStep),filNum]
#注:一个点的所有通道都卷积成一个值
input = tf.Variable(tf.random_normal([1,10,10,3]))
filter = tf.Variable(tf.random_normal([3,3,3,1]))
op2 = tf.nn.conv2d(input, filter, strides=[1, 3, 5, 1], padding='SAME')
池化
http://blog.csdn.net/mao_kun/article/details/50507376
池化一般接在卷积层后面,输入通常是卷积层的输出。用于提对输入的特征图进行压缩,一方面使特征图变小,简化网络计算复杂度;一方面进行特征压缩,提取主要特征。
池化操作有一般池化、重叠池化【average对背景保留更好,max对纹理提取更好】 、金字塔池化。
一般池化,一般为两种(最大值|均值),区域不重叠(与卷积不同点)。一种是max Pooling,一种是average pooling。tensorflow中默认是重叠池化,无此项。如下:


重叠池化(Overlapping Pooling),相邻池化窗口之间会有重叠区域。
金字塔池化(SPP:Spatial Pyramid Pooling),可以把任何尺度的图像的卷积特征转化成相同维度,这不仅可以让CNN处理任意尺度的图像,还能避免cropping和warping操作,导致一些信息的丢失,具有非常重要的意义。
一般的CNN都需要输入图像的大小是固定的,这是因为全连接层的输入需要固定输入维度,但在卷积操作是没有对图像尺度有限制,所有作者提出了空间金字塔池化,先让图像进行卷积操作,然后转化成维度相同的特征输入到全连接层,这个可以把CNN扩展到任意大小的图像。

池化与卷积的差别:
卷积中输入图像的channel将归一为单通道,而池化中特征channel保留,输入多少,输出多少通道。
BN层(2015-Batch Normalization,批次归一化)
http://blog.csdn.net/myarrow/article/details/51848285 *****************************
http://blog.csdn.net/u014365862/article/details/77159778
http://blog.csdn.net/linmingan/article/details/50780761
https://www.zhihu.com/question/45270958
        为了使得神经网络中信息更好的流动,每一层的输入方差应该尽量相等,而对于每一层的输入进行白化花费较高,并且也不是处处可微,所以简化:对mini-batch的标量特征进行单独的进行零均值一方差归一化,来代替白化,同时对层的输入和输出同时进行归一化(输入:激活后的偏分布,输出:卷积后的ISC偏分布)。因此引入BN层,作者本意放在Activate之前。
归一化
此处的归一化是 Z-Score 归一化,使数据~N(0,1) 。下图代表数据是否均一化的最优解寻解过程:
数据没有归一化(左图),ICS(Internal Covariate Shift)可能造成图像的等高线为类似椭圆形状。
数据归一化后(右图),最优解的寻优过程明显会变得平缓,更容易正确的收敛到最优解。
训练
均值方差归一化(使x满足正态分布,均值归一化成0,方差归一化成1),如下:

显然归一化后的,均值为0,反差为1。但强制归一化后会影响本层网络学习到的特征,因此引入了可学习重构参数γ、β,让我们的网络可以学习恢复出原始网络所要学习的特征分布(特别的当,时,可还原输入;如此一来,既可以改变同时也可以保持原输入,那么模型的容纳能力(capacity)就提升了)。
注意:按作者思路,BN放在activate前,将训练过程中ICS导致的数据分布变化归一后再激活。特别在特定情况下,不会影响输入。
前向传导公式,如下:

反向求导,链式法则(chain rule)更新参数,如下:

测试
实际测试时,均值和方差不是针对某一个Batch,而是针对整个数据集而言。因此,在训练过程中除了正常的前向传播和反向求导之外,我们还要记录每一个Batch的均值和方差,以便训练完成之后按照下式计算整体的均值和方差。最后测试阶段,BN的使用公式就是(用整体的均值方差替换batch):

好处
归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。
    对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。
归一化数据分布,解决在训练过程中,中间层数据分布发生改变的情况。
加快训练速度 ,防止“梯度弥散”,解决Sigmoid与tanh梯度消失与梯度爆炸问题(BN归一化后数据分布较为适中);允许更大的学习率,提高训练速度。
移除或使用较低的dropout。dropout是常用的防止overfitting的方法,而导致overfit的位置往往在数据边界处,如果初始化权重就已经落在数据内部,overfit现象就可以得到一定的缓解。论文中最后的模型分别使用10%、5%和0%的dropout训练模型,与之前的40%-50%相比,可以大大提高训练速度。
降低L2权重衰减系数。 还是一样的问题,边界处的局部最优往往有几维的权重(斜率)较大,使用L2衰减可以缓解这一问题,现在用了Batch Normalization,就可以把这个值降低了,论文中降低为原来的5倍。
取消Local Response Normalization层。 由于使用了一种Normalization,再使用LRN就显得没那么必要了。而且LRN实际上也没那么work。????????
疑问
1、BN放在Activate之前,是否应该用tanh激活??用Relu激活下层输入数据分布不一致。。???
2、用Relu Activate之后是否有必要再加一层BN???????????

LRN(2012-局部响应归一化)
http://blog.csdn.net/yangdashi888/article/details/77918311
http://blog.csdn.net/hduxiejun/article/details/70570086
此处的归一化与BN不同,仅仅是平滑抑制,且LRN用于激活层之后。
原理是仿造生物学上活跃的神经元对相邻神经元的抑制现象(侧抑制),没有理论推导,用于激活层之后,实现即对激活后的特征沿着神经元方向做单向平滑,有助于增强模型泛化能力。速度减慢2-3倍,较少使用。
公式:,其中∑叠加的方向是沿着通道(神经元)方向的,即一个点同方向的前后n/2个通道的点的平方和(N表示当前层神经元个数,min、max限制不越界)。参数K、n、α、β都是超参数,一般设置k=2,n=5,α=1*e-4,β=0.75。可按下图理解:


tensorflow 实现一致:
sqr_sum[a, b, c, d] = sum(input[a,b, c, d - depth_radius : d + depth_radius + 1] ** 2)
output = input / (bias +alpha * sqr_sum) ** beta

全连接层(FC)
全连接层:连接所有的特征,将输出值送给分类器(如softmax分类器)。
CNN网络中前几层的卷积层参数量占比小,计算量占比大;而后面的全连接层正好相反,大部分CNN网络都具有这个特点。因此我们在进行计算加速优化时,重点放在卷积层;进行参数优化、权值裁剪时,重点放在全连接层。

个人理解:卷积层的卷积操作比全连接层的二维矩阵点乘计算复杂,卷积核越大计算量也就越大。
卷积层参数,由于权重共享原则,所以权重和偏置项都主要取决于神经元的个数,参数数量与图像大小无关【但图像大会提高计算复杂的】,而全连接层参数取决于特征点数(与图像大小有关)和神经元数,所以参数量比卷积层大。

FCN,全卷积网络优于CNN,可以把FC层卷积化,以后不用FC层,详见FCN。

Dropout层(2012-AlexNet)
    http://blog.csdn.net/stdcoutzyx/article/details/49022443           #############################
dropout的思想继承自bagging方法,舍弃部分神经元来评估结果。
dropout定义
    Dropout,按照一定的概率将神经元暂时从网络中丢弃【即让网络某些隐含层节点的权重不工作】,一般用在FC全连接层。
【分类特征足够多的时候 :总可以找到一个样本,使得在原始的网络上也能达到dropout单元后的效果,这样,每一次dropout其实都相当于增加了样本,特征点较多时适用,若特征点少dropout后可能成为负样本,如Q-O???用在全连接层时,每一个神经元的特征都可看做是一个通道,卷积过程中视野已经包含了较大或整个幅面,不能看作图像中的部分点,所以Q-O副作用应该是个人的错误理解。】
实现
http://blog.csdn.net/u012702874/article/details/45030991     *****
http://blog.csdn.net/stdcoutzyx/article/details/49022443
理论实现(dropout)
分两部分:训练、测试。
    训练的时候,按一定的概率(retaining probability)p 来对weight layer 的参数进行随机采样【注意:是对神经元n采样,即选p×n个神经元,假设p=0.5,FC输入[-1,10*10*256],神经元权重[10*10*256,n=1024],dropout随机选取0.5*1024=512个权重参数进行计算】,将这个子网络作为此次更新的目标网络。可以想象,如果整个网络有n个神经元,那么我们可用的子网络个数为 2^n 。 并且,当n很大时,每次迭代更新 使用的子网络基本上不会重复,从而避免了某一个网络被过分的拟合到训练集上。
    测试时不做任何的参数丢弃(p = 1.0),dropout layer 把进来的东西原样输出,导致在统计意义下,测试时 每层 dropout layer的输出比训练时的输出多加了【(1 - p)*100】%  个units 的输出。 即 【p*100】% 个units 的和是同训练时随机采样得到的子网络的输出一致,另【(1 – p)*100】% 的units的和 是本来应该扔掉但是又在测试阶段被保留下来的。所以,为了使得dropout layer 下一层的输入和训练时具有相同的“意义”和“数量级”,我们要对测试时的伪dropout layer的输出(即下层的输入)做 rescale【tensorflow中dropout层已包含rescale操作】: 乘以一个p,表示最后的sum中只有这么大的概率,或者这么多的部分被保留。
    假设x是dropout layer的输入,y是dropout layer的输出,W是上一层的所有weight parameters,是以retaining probability 为p 采样得到的weight parameter子集。用公式表示(忽略bias):
    训练:                            
    测试:                            
实际实现[Inverted  dropout]
    一般写程序的时候,想直接在test时用 , 这种表达式。(where )
因此我们就在训练的时候就直接训练。 所以训练公式修正为。 即把dropout的输入乘以p 再进行训练,这样得到的训练得到的weight 参数就是,测试的时候除了不使用dropout外,不需要再做任何rescale。Caffe 、Lasagne、Tensorflow里面的代码就是这样写的。
优劣
好处
防止过拟合
缺点
训练时间是没有dropout网络的2-3倍。
dropout率的选择
经过交叉验证,隐含节点dropout率等于0.5的时候效果最好,原因是0.5的时候dropout随机生成的网络结构最多【c(100,50)最大,因为c(100,70)== c(100,30)<c(100,50)】。
dropout也可以被用作一种添加噪声的方法,直接对input进行操作。输入层设为更接近1的数。使得输入变化不会太大(0.8)
数据量小的时候,dropout效果不好,数据量大了,dropout效果好
个人理解
    用在全连接层时,每一个神经元的特征都可看做是一个通道,卷积过程中视野已经包含了较大或整个幅面,不能看作图像中的部分点,所以Q-O副作用应该是个人的错误理解。
损失函数
0-1损失函数

绝对值损失函数

平方损失函数

对数损失函数(交叉熵)
https://www.zhihu.com/question/41252833/answer/108777563
        
如果损失函数越小,表示模型越好。逻辑回归(分类问题)中,采用的则是对数损失函数。线性回归(图像复原等问题)中,采用的是平方损失函数。
PSNR(峰值信噪比)
一种评价图像的客观标准,于loss不同,PSNR值越大,图像越相似。
其中,MSE(MeanSquareError) 是原图像与处理图像之间均方误差。

正则化(regulation)
https://www.zhihu.com/question/20924039
http://blog.csdn.net/zouxy09/article/details/24971995
引入正则项就是为了防止过拟合,所以还是以过拟合的经典图说明:
防止过拟合:减少x的数量(即Dropout方法);减少W的数量(即此处的正则化)。
0范数,向量中非零元素的个数。
1范数,为绝对值之和。
2范数,就是通常意义上的模。
减少W的数量,即使范数很小。1范数和0范数可以实现稀疏,1因具有比L0更好的优化求解特性而被广泛应用。L2范数是指向量各元素的平方和然后求平方根。我们让L2范数的正则项||W||2最小,可以使得W的每个元素都很小,都接近于0,但与L1范数不同,它不会让它等于0,而是接近于0,这里是有很大的区别的;所以大家比起1范数,更钟爱2范数。因此会在损失函数中加入正则化项如下:

目标函数 = 误差函数(损失函数 or 评价函数) + 正则化项,λ 被称为正则化系数,λ 越大,这个限制越强。
融合层(如 crop,wise等)
Crop
将A进行裁剪到B的shape,作为C输出。
Element wise
对输入A和B,实现A+B   ||  max(A,B)  ||  A.*B 等操作。
过拟合
    防止过拟合的方法
提前终止(当验证集上的效果变差的时候)
L1和L2正则化加权
soft weight sharing
dropout
阅读更多
个人分类: 深度学习
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭