談?wù)凾ensorflow的Batch Normalization

tensorflow中關(guān)于BN(Batch Normalization)的函數(shù)主要有兩個(gè),分別是:

  • tf.nn.moments
  • tf.nn.batch_normalization

關(guān)于這兩個(gè)函數(shù),官方API中有詳細(xì)的說(shuō)明,具體的細(xì)節(jié)可以點(diǎn)鏈接查看,關(guān)于BN的介紹可以參考這篇論文,我來(lái)說(shuō)說(shuō)自己的理解。
不得不吐槽一下,tensorflow的官方API很少給例子,太不人性化了,人家numpy做的就比tensorflow強(qiáng)。
對(duì)了,moments函數(shù)的計(jì)算結(jié)果一般作為batch_normalization的部分輸入!這就是兩個(gè)函數(shù)的關(guān)系,下面展開(kāi)介紹!

一、tf.nn.moments函數(shù)

官方的輸入定義如下:

def moments(x, axes, name=None, keep_dims=False)

解釋如下:

  • x 可以理解為我們輸出的數(shù)據(jù),形如 [batchsize, height, width, kernels]
  • axes 表示在哪個(gè)維度上求解,是個(gè)list,例如 [0, 1, 2]
  • name 就是個(gè)名字,不多解釋
  • keep_dims 是否保持維度,不多解釋

這個(gè)函數(shù)的輸出有兩個(gè),用官方的話說(shuō)就是:

Two Tensor objects: mean and variance.

解釋如下:

  • mean 就是均值啦
  • variance 就是方差啦

關(guān)于這個(gè)函數(shù)的最基本的知識(shí)就介紹完了,但依然沒(méi)明白這函數(shù)到底是干啥的,下面通過(guò)幾個(gè)例子來(lái)說(shuō)明:

  • 1、計(jì)算2×3維向量的mean和variance,程序節(jié)選如下:
img = tf.Variable(tf.random_normal([2, 3]))
axis = list(range(len(img.get_shape()) - 1))
mean, variance = tf.nn.moments(img, axis)

輸出的結(jié)果如下:

img = [[ 0.69495416  2.08983064 -1.08764684]
         [ 0.31431156 -0.98923939 -0.34656194]]
mean =  [ 0.50463283  0.55029559 -0.71710438]
variance =  [ 0.0362222   2.37016821  0.13730171]

有了例子和結(jié)果,就很好理解了,moments函數(shù)就是在 [0] 維度上求了個(gè)均值和方差,對(duì)于axis這個(gè)參數(shù)的理解,可以參考這里。
另外,針對(duì)2×3大小的矩陣,axis還可以這么理解,若axis = [0],那么我們2×3的小矩陣可以理解成是一個(gè)包含了2個(gè)長(zhǎng)度為3的一維向量,然后就是求這兩個(gè)向量均值方差啦!多個(gè)向量的均值、方差計(jì)算請(qǐng)自行腦補(bǔ)。
當(dāng)然了,這個(gè)例子只是一個(gè)最簡(jiǎn)單的例子,如果換做求形如“[batchsize, height, width, kernels]”數(shù)據(jù)的mean和variance呢?接下來(lái)來(lái)簡(jiǎn)單分析一下。

  • 2、計(jì)算卷積神經(jīng)網(wǎng)絡(luò)某層的的mean和variance
    假定我們需要計(jì)算數(shù)據(jù)的形狀是 [batchsize, height, width, kernels],熟悉CNN的都知道,這個(gè)在tensorflow中太常見(jiàn)了,例程序如下:
img = tf.Variable(tf.random_normal([128, 32, 32, 64]))
axis = list(range(len(img.get_shape()) - 1))
mean, variance = tf.nn.moments(img, axis)

形如[128, 32, 32, 64]的數(shù)據(jù)在CNN的中間層非常常見(jiàn),那么,為了給出一個(gè)直觀的認(rèn)識(shí),這個(gè)函數(shù)的輸出結(jié)果如下,可能輸出的數(shù)字比較多。。。

mean =  [ -1.58071518e-03   9.46253538e-04   9.92774963e-04  -2.57909298e-04
             4.31227684e-03   2.85443664e-03  -3.51431966e-03  -2.95847654e-04
            -1.57856941e-03  -7.36653805e-04  -3.81006300e-03   1.95848942e-03
            -2.19231844e-03   1.88898295e-04   3.09050083e-03   1.28045678e-04
            -5.45501709e-04  -7.49588013e-04   3.41436267e-03   4.55856323e-04
             1.21808052e-03   1.71916187e-03   2.33578682e-03  -9.98377800e-04
             1.01172924e-03  -3.25803459e-03   1.98090076e-03  -9.53197479e-04
             3.37207317e-03   6.27857447e-03  -2.22939253e-03  -1.75476074e-04
             1.82938576e-03   2.28643417e-03  -2.59208679e-03  -1.05714798e-03
            -1.82652473e-03   4.51803207e-05  -1.38700008e-03   1.88308954e-03
            -3.67999077e-03  -4.22883034e-03   8.54551792e-04  -1.30176544e-04
            -1.02388859e-03   3.15248966e-03  -1.00244582e-03  -3.58343124e-04
             9.68813896e-04  -3.17507982e-03  -2.61783600e-03  -5.57708740e-03
            -3.49491835e-04   7.54106045e-03  -9.98616219e-04   5.13806939e-04
             1.08468533e-03   1.58560276e-03  -2.76589394e-03  -1.18827820e-03
            -4.92024422e-03   3.14301252e-03   9.12249088e-04  -1.98567938e-03]
variance =  [ 1.00330877  1.00071466  1.00299144  1.00269675  0.99600208  0.99615276
                0.9968518   1.00154674  0.99785519  0.99120021  1.00565553  0.99633628
                0.99637395  0.99959981  0.99702841  0.99686354  1.00210547  1.00151515
                1.00124979  1.00289011  1.0019592   0.99810153  1.00296855  1.0040164
                1.00397885  0.99348587  0.99743217  0.99921477  1.00718474  1.00182319
                1.00461221  1.00222814  1.00570309  0.99897575  1.00203466  1.0002507
                1.00139284  1.0015136   1.00439298  0.99371535  1.00209546  1.00239146
                0.99446201  1.00200033  1.00330424  0.99965429  0.99676734  0.99974728
                0.99562836  1.00447667  0.9969337   1.0026046   0.99110448  1.00229466
                1.00264072  0.99483615  1.00260413  1.0050714   1.00082493  1.00062656
                1.0020628   1.00507069  1.00343442  0.99490905]

然后我解釋一下這些數(shù)字到底是怎么來(lái)的,可能對(duì)于2×3這么大的矩陣,理解起來(lái)比較容易,但是對(duì)于 [128, 32, 32, 64] 這樣的4維矩陣,理解就有點(diǎn)困難了。
其實(shí)很簡(jiǎn)單,可以這么理解,一個(gè)batch里的128個(gè)圖,經(jīng)過(guò)一個(gè)64 kernels卷積層處理,得到了128×64個(gè)圖,再針對(duì)每一個(gè)kernel所對(duì)應(yīng)的128個(gè)圖,求它們所有像素的mean和variance,因?yàn)榭偣灿?4個(gè)kernels,輸出的結(jié)果就是一個(gè)一維長(zhǎng)度64的數(shù)組啦!
手畫(huà)示意圖太丑了,我重新畫(huà)了一個(gè)!


計(jì)算mean和variance

二、tf.nn.batch_normalization函數(shù)

官方對(duì)函數(shù)輸入的定義是:

def batch_normalization(x, mean, variance, offset, scale, variance_epsilon, name=None):

關(guān)于這幾個(gè)參數(shù),可以參考這篇論文和這個(gè)博客,我這里就直接給出一個(gè)公式的截圖了,如下

晦澀難懂的公式

官方對(duì)參數(shù)的解釋如下


官方的解釋

這一堆參數(shù)里面,我們已經(jīng)知道x、mean、variance這三個(gè),那offset和scale呢??答案是:這兩個(gè)參數(shù)貌似是需要訓(xùn)練的,其中offset一般初始化為0,scale初始化為1,另外offset、scale的shape與mean相同。

variance_epsilon這個(gè)參數(shù)設(shè)為一個(gè)很小的數(shù)就行,比如0.001。

但是,我這里要但是一下!BN在神經(jīng)網(wǎng)絡(luò)進(jìn)行training和testing的時(shí)候,所用的mean、variance是不一樣的!這個(gè)博客里已經(jīng)說(shuō)明了,但具體怎么操作的呢?我們看下面的代碼

update_moving_mean = moving_averages.assign_moving_average(moving_mean, mean, BN_DECAY)
update_moving_variance = moving_averages.assign_moving_average(moving_variance, variance, BN_DECAY)
tf.add_to_collection(UPDATE_OPS_COLLECTION, update_moving_mean)
tf.add_to_collection(UPDATE_OPS_COLLECTION, update_moving_variance)
mean, variance = control_flow_ops.cond(['is_training'], lambda: (mean, variance), lambda: (moving_mean, moving_variance))

看不懂沒(méi)關(guān)系,這段代碼的意思就是計(jì)算moving mean(滑動(dòng)平均)、moving variance(滑動(dòng)方差),然后利用 (moving_mean, moving_variance) 進(jìn)行網(wǎng)絡(luò)測(cè)試。

關(guān)于BN的完整實(shí)現(xiàn),在Ryan Dahl的repository里有,名字叫做tensorflow-resnet,可以自行查看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容