优化卷积核
在实际的卷积训练中,为了加快速度,常常把卷积层裁开。比如一个3x3的过滤器,可以裁成3x1和1x3两个过滤器,分别对原有输入做卷积操作,这样可以大大提升运算速度
原理:在浮点运算中乘法消耗的资源较多,我们的目的就是尽量减小乘法运算
比如:对一个5x2的原始图片进行一次3x3的同卷积,相当于生成的5x2像素中每一个都要经历3x3次乘法,一共90次。同样一张图片,如果先进行一次3x1的同卷积需要30次运算,再进行一次1x3的同卷积还是30次,一共60次。
看下面例子:
1 | W_conv2 = weight_variable([5, 5, 64, 64]) |
修改为:
1 | W_conv21 = weight_variable([5, 1, 64, 64]) |
批量归一化
批量归一化,简称BN算法。一般用在全连接层或卷积神经网络。它的作用是要最大限度地保证每次的正向传播输出在同一分布上, 这样反向计算时参照的数据样本分布就会与正向计算时的数据分布一样了。 保证了分布统一, 对权重的调整才会更有意义。
批量归一化的做法很简单,即将每一层运算出来的数据都归一化成均值为0、方差为1的标准高斯分布。这样就会在保留样本分布特征的同时,又消除了层与层之间的分布差异
Tensorflow中自带的BN函数定义:
tf.nn.batch_normalization(x,mean,variance,offset,scale,variance_epsion,name=None),参数说明如下:
x:代表输入
mean:代表样本的均值
variance:代表方差
offset:代表偏移,即相加一个转化值,后面我们会用激活函数来转换,所以直接使用0
scale:代表缩放,即乘以一个转化值。一般用1
variance_epsilon:为了避免分布为0的情况,给分母加一个极小值
要想使用上面这个BN函数,必须由另一个函数配合使用——tf.nn.moments,由他来计算均值和方差,然后就可以使用BN。tf.nn.moments定义如下:
tf.nn.moments(x,axes,name=None,keep_dims=False)
axes主要是指定哪个轴来求均值与方差
有了上面的两个函数还不够,为了有更好的效果,我们希望使用平滑指数衰减的方法来优化每次的均值与方差,于是就用到了tf.train.ExponentialMovingAverage函数。它的左右是上一次的值对本次的值有个衰减后的影响,从而使每次的值连起来后会相对平滑一些。展开后可以用下列等式表示:
shadow_variable = decay * shadow_variable + (1- decay) * variable,各参数说明如下:
decay:代表衰减指数,直接指定的。比如0.9
variable:代表本批次样本中的值
等式右边的shadow_variable:代表上次总样本的值
等式左边的shadow_variable:代表计算出来的本次总样本的值
上面的函数需要联合使用,于是在Tensorflow中的layers模块又实现了一次BN函数,相当于把上面几个函数结合在一起。使用时,首先将头文件引入:
1 | from tensorflow.contrib.layers.python.layers import barch_norm |
batch_norm(inputs,decay=0.999,center=True,scale=False,epsilon=0.001,activation_fn=None,param_initializers=None,param_regularizers=None,updates_collections=ops.GraphKeys.UPDATE_OPS,is_training=True,reuse=None,variables_collections=None,outputs_collections=None,trainable=True,batch_weights=None,fused=False,data_format=DATA_FORMAT_NHWC,zero_debias_moving_mean=False,scope=None,renorm=False,renorm_clipping=None,renorm_decay=0.9),参数看得眼都花了,参数说明如下:
inputs:代表输入
decay:代表移动平均值的衰败速度,是使用了一种叫做平滑指数衰减的方法更新均值方差,一般设为0.9;值太小会导致均值和方差更新太快,而值太大又会导致几乎没有衰减,容易出现过拟合。
scale:是否进行变化(通过乘一个gamma值进行缩放),一般设为False。
epsilon:是为了避免分母为0的情况,给分母加一个极小值,默认即可。
is_training:当它为True,代表是训练过程,这时会不断更新样本集的均值与方差。测试时,设为False,就会使用测试样本集的均值与方差
updatas_collections:默认为tf.GraphKeys.UPDARE_OPS,在训练时提供一种内置的均值方差更新机制,即通过图中的tf.GraphKeys.UPDATE_OPS变量来更新。但它是在每次当前批次训练完成后才更新均值和方差,这样导致当前数据总是使用前一次的均值和方差,没有得到最新的更新。所以都会将其设为None,让均值和方差即时更新。
reuse:支持共享变量,与下面的scope参数联合使用
scope:指定变量的作用域variable_scope