详细研究Batchnorm的原理
前言:Batchnorm是深度网络中常用的加速神经网络训练、加速收敛速度和稳定性的算法,可以说是当前深度网络不可缺少的一部分。
本文旨在用通俗易懂的语言详细解读深度学习的常用算法-batchnorm的原理及其代码实现。 本文主要包括以下部分。
Batchnorm主要解决的问题Batchnorm原理解读Batchnorm的优点Batchnorm源代码解读第一节: Batchnorm主要解决的问题首先是这一部分,为什么深度网络需要Batchnorm
我们知道batchnorm需要对数据进行规范化,尤其是在深度学习方面,尤其是在CV上。 因为深度神经网络主要是为了学习训练数据的分布,在测试集中达到很好的泛化效果。 但是,batch输入的每个数据都有不同的分布,显然会给网络训练带来困难。 另一方面,数据经过一层网络计算后,其数据分布也发生了变化。 这种现象称为internalinternalcovariatecovariateshiftshift,接下来将进行详细说明,但会给下一层的网络学习带来困难。 巴斯蒂尔诺
batchnorm直译为批量标准化,是为了解决这一分布变化问题。
1.1国际co variate shift
国际航空
internalcovariatecovariateshiftshift :这个术语是谷歌集团在论文batchbatchnormalizatoinnormalizatoin中提出的,主要说明是训练深度网络这是因为每次参数反复更新,上一层网络的输出数据经过该层网络计算后,数据的分布会发生变化,给下一层网络的学习带来困难(神经网络本来就要学习数据的分布,分布
Shift。
白堤
Batch Normalizatoin
Normalizatoin之前的解决方案是使用较小的学习率和谨慎的初始化参数使数据白化,但明显难以治愈。
# # # 1.2 co可变偏移
国际航空
internalcovariatecovariateshiftshift和covariatecovariateshift相似,但不是一个。 前者发生在神经网络内部,因此是InternalInternal,后者发生在输入数据中。 CovariateCovariate Shift
Shift主要阐述了由于训练数据和测试数据的分布差异,影响了网络的通用性和训练速度,我们常用的方法是规范化或白化。 如果想直观感受,请查看下图:
给定简单的线性分类板栗,假定参数初始化通常具有零均值和较小方差,例如,a的数据分布,此时拟合的y=wx b
y=wx b重复多次后达到紫色线,就像b图中的橙色线一样。 此时,虽然有很好的分类效果,但是将其标准化为0点附近的话,训练速度明显会变快。 因此,通过转换使数据之间的相对差异更大会更容易区分。
Covariate
Covariate ShiftShift描述的是输入数据分布不均匀的现象,如果能加快数据规范化当然还有训练的速度,消除数据的相关性,强调这些分布的相对差异就更好了BatchnormBatchnorm如前所述,BatchnormBatchnorm是归一化的一种手段,从极限上讲,这种方式可以减小图像之间的绝对差异,强调相对差异,加快训练速度。 所以,并不是所有的深度学习领域都可以使用BatchNorm
BatchNorm,下面写下那个不适用的情况。
第二节: Batchnorm原理解读这一部分主要结合原论文部分,排除了一些复杂的公式,对Batchnorm
尽量详细说明BatchNorm的原理。
我之前说过,为了缩小国际
internalcovariatecovariateshiftshift不是对神经网络的各层进行归一化即可,假设将各层输出的数据归一化为0平均、1方差来满足正太分布的情况下,各层的数据分布为标准的正太分布
但是,稍微修改一下,放入可训练的参数进行正规化的话,就是BatchNorm
BatchNorm已实现,将结合下图中的伪代码进行详细分析。
之所以称为batchnorm,是因为假定norm的数据为batch,输入数据为=x1.m
=x1.m共计m个数据,输出为yi=BN(x(x ) yi=bn ) x )、batchnorm
batchnorm的步骤如下:
1.先求出此次批量数据x
x的均值,μβ=1m∑mi=1xiμβ=m1∑i=1mxi
2.求出此次batch的方差,σ2β=1m∑i=1m(xi−μβ)2σβ2=m1∑i=1m(xi−μβ)2
3.接下来就是对xx做归一化,得到x−ixi−
4.最重要的一步,引入缩放和平移变量$γ 和和beta$ ,计算归一化后的值,yi=γx−iyi=γxi− +β
接下来详细介绍一下这额外的两个参数,之前也说过如果直接做归一化不做其他处理,神经网络是学不到任何东西的,但是加入这两个参数后,事情就不一样了,先考虑特殊情况下,如果γ
γ和ββ分别等于此batch的标准差和均值,那么yiyi不就还原到归一化前的xx了吗,也即是缩放平移到了归一化前的分布,相当于batchnormbatchnorm没有起作用,$ β$ 和γ
γ分别称之为 平移参数和缩放参数 。这样就保证了每一次数据经过归一化后还保留的有学习来的特征,同时又能完成归一化这个操作,加速训练。
先用一个简单的代码举个小栗子:
def Batchnorm_simple_for_train(x, gamma, beta, bn_param):"""param:x : 输入数据,设shape(B,L)param:gama : 缩放因子 γparam:beta : 平移因子 βparam:bn_param : batchnorm所需要的一些参数eps : 接近0的数,防止分母出现0momentum : 动量参数,一般为0.9, 0.99, 0.999running_mean :滑动平均的方式计算新的均值,训练时计算,为测试数据做准备running_var : 滑动平均的方式计算新的方差,训练时计算,为测试数据做准备"""running_mean = bn_param['running_mean'] #shape = [B] running_var = bn_param['running_var'] #shape = [B]results = 0. # 建立一个新的变量 x_mean=x.mean(axis=0) # 计算x的均值 x_var=x.var(axis=0) # 计算方差 x_normalized=(x-x_mean)/np.sqrt(x_var+eps) # 归一化 results = gamma * x_normalized + beta # 缩放平移 running_mean = momentum * running_mean + (1 - momentum) * x_mean running_var = momentum * running_var + (1 - momentum) * x_var #记录新的值 bn_param['running_mean'] = running_mean bn_param['running_var'] = running_var return results , bn_param看完这个代码是不是对batchnorm有了一个清晰的理解,首先计算均值和方差,然后归一化,然后缩放和平移,完事!但是这是在训练中完成的任务,每次训练给一个批量,然后计算批量的均值方差,但是在测试的时候可不是这样,测试的时候每次只输入一张图片,这怎么计算批量的均值和方差,于是,就有了代码中下面两行,在训练的时候实现计算好mean
mean var
var测试的时候直接拿来用就可以了,不用计算均值和方差。
running_mean = momentum * running_mean + (1 - momentum) * x_meanrunning_var = momentum * running_var + (1 - momentum) * x_var所以,测试的时候是这样的:
def Batchnorm_simple_for_test(x, gamma, beta, bn_param):"""param:x : 输入数据,设shape(B,L)param:gama : 缩放因子 γparam:beta : 平移因子 βparam:bn_param : batchnorm所需要的一些参数eps : 接近0的数,防止分母出现0momentum : 动量参数,一般为0.9, 0.99, 0.999running_mean :滑动平均的方式计算新的均值,训练时计算,为测试数据做准备running_var : 滑动平均的方式计算新的方差,训练时计算,为测试数据做准备"""running_mean = bn_param['running_mean'] #shape = [B] running_var = bn_param['running_var'] #shape = [B]results = 0. # 建立一个新的变量 x_normalized=(x-running_mean )/np.sqrt(running_var +eps) # 归一化 results = gamma * x_normalized + beta # 缩放平移 return results , bn_param你是否理解了呢?如果还没有理解的话,欢迎再多看几遍。
第三节:Batchnorm源码解读本节主要讲解一段tensorflow中Batchnorm
Batchnorm的可以使用的代码3
3,如下:
代码来自知乎,这里加入注释帮助阅读。
至于此行代码tf.nn.batch_normalization()就是简单的计算batchnorm过程啦,代码如下:
这个函数所实现的功能就如此公式:γ(x−μ)σ+β
σγ(x−μ)+β
def batch_normalization(x, mean, variance, offset, scale, variance_epsilon, name=None): with ops.name_scope(name, "batchnorm", [x, mean, variance, scale, offset]): inv = math_ops.rsqrt(variance + variance_epsilon) if scale is not None: inv *= scale return x * inv + (offset - mean * inv if offset is not None else -mean * inv)###第四节:Batchnorm的优点
主要部分说完了,接下来对BatchNorm做一个总结:
注:或许大家都知道了,韩国团队在2017NTIRE图像超分辨率中取得了top1的成绩,主要原因竟是去掉了网络中的batchnorm层,由此可见,BN并不是适用于所有任务的,在image-to-image这样的任务中,尤其是超分辨率上,图像的绝对差异显得尤为重要,所以batchnorm的scale并不适合。
参考文献:
【1】http://blog.csdn.net/zhikangfu/article/details/53391840
【2】http://geek.csdn.net/news/detail/160906
【3】 https://www.zhihu.com/question/53133249