您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)TensorFlow如何實(shí)現(xiàn)Batch Normalization的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
一、BN(Batch Normalization)算法
1. 對數(shù)據(jù)進(jìn)行歸一化處理的重要性
神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)過程的本質(zhì)就是學(xué)習(xí)數(shù)據(jù)分布,在訓(xùn)練數(shù)據(jù)與測試數(shù)據(jù)分布不同情況下,模型的泛化能力就大大降低;另一方面,若訓(xùn)練過程中每批batch的數(shù)據(jù)分布也各不相同,那么網(wǎng)絡(luò)每批迭代學(xué)習(xí)過程也會出現(xiàn)較大波動,使之更難趨于收斂,降低訓(xùn)練收斂速度。對于深層網(wǎng)絡(luò),網(wǎng)絡(luò)前幾層的微小變化都會被網(wǎng)絡(luò)累積放大,則訓(xùn)練數(shù)據(jù)的分布變化問題會被放大,更加影響訓(xùn)練速度。
2. BN算法的強(qiáng)大之處
1)為了加速梯度下降算法的訓(xùn)練,我們可以采取指數(shù)衰減學(xué)習(xí)率等方法在初期快速學(xué)習(xí),后期緩慢進(jìn)入全局最優(yōu)區(qū)域。使用BN算法后,就可以直接選擇比較大的學(xué)習(xí)率,且設(shè)置很大的學(xué)習(xí)率衰減速度,大大提高訓(xùn)練速度。即使選擇了較小的學(xué)習(xí)率,也會比以前不使用BN情況下的收斂速度快??偨Y(jié)就是BN算法具有快速收斂的特性。
2)BN具有提高網(wǎng)絡(luò)泛化能力的特性。采用BN算法后,就可以移除針對過擬合問題而設(shè)置的dropout和L2正則化項(xiàng),或者采用更小的L2正則化參數(shù)。
3)BN本身是一個(gè)歸一化網(wǎng)絡(luò)層,則局部響應(yīng)歸一化層(Local Response Normalization,LRN層)則可不需要了(Alexnet網(wǎng)絡(luò)中使用到)。
3. BN算法概述
BN算法提出了變換重構(gòu),引入了可學(xué)習(xí)參數(shù)γ、β,這就是算法的關(guān)鍵之處:
引入這兩個(gè)參數(shù)后,我們的網(wǎng)絡(luò)便可以學(xué)習(xí)恢復(fù)出原是網(wǎng)絡(luò)所要學(xué)習(xí)的特征分布,BN層的錢箱傳到過程如下:
其中m為batchsize。BatchNormalization中所有的操作都是平滑可導(dǎo),這使得back propagation可以有效運(yùn)行并學(xué)到相應(yīng)的參數(shù)γ,β。需要注意的一點(diǎn)是Batch Normalization在training和testing時(shí)行為有所差別。Training時(shí)μβ和σβ由當(dāng)前batch計(jì)算得出;在Testing時(shí)μβ和σβ應(yīng)使用Training時(shí)保存的均值或類似的經(jīng)過處理的值,而不是由當(dāng)前batch計(jì)算。
二、TensorFlow相關(guān)函數(shù)
1.tf.nn.moments(x, axes, shift=None, name=None, keep_dims=False)
x是輸入張量,axes是在哪個(gè)維度上求解, 即想要 normalize的維度, [0] 代表 batch 維度,如果是圖像數(shù)據(jù),可以傳入 [0, 1, 2],相當(dāng)于求[batch, height, width] 的均值/方差,注意不要加入channel 維度。該函數(shù)返回兩個(gè)張量,均值mean和方差variance。
2.tf.identity(input, name=None)
返回與輸入張量input形狀和內(nèi)容一致的張量。
3.tf.nn.batch_normalization(x, mean, variance, offset, scale, variance_epsilon,name=None)
計(jì)算公式為scale(x - mean)/ variance + offset。
這些參數(shù)中,tf.nn.moments可得到均值mean和方差variance,offset和scale是可訓(xùn)練的,offset一般初始化為0,scale初始化為1,offset和scale的shape與mean相同,variance_epsilon參數(shù)設(shè)為一個(gè)很小的值如0.001。
三、TensorFlow代碼實(shí)現(xiàn)
1. 完整代碼
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt ACTIVITION = tf.nn.relu N_LAYERS = 7 # 總共7層隱藏層 N_HIDDEN_UNITS = 30 # 每層包含30個(gè)神經(jīng)元 def fix_seed(seed=1): # 設(shè)置隨機(jī)數(shù)種子 np.random.seed(seed) tf.set_random_seed(seed) def plot_his(inputs, inputs_norm): # 繪制直方圖函數(shù) for j, all_inputs in enumerate([inputs, inputs_norm]): for i, input in enumerate(all_inputs): plt.subplot(2, len(all_inputs), j*len(all_inputs)+(i+1)) plt.cla() if i == 0: the_range = (-7, 10) else: the_range = (-1, 1) plt.hist(input.ravel(), bins=15, range=the_range, color='#FF5733') plt.yticks(()) if j == 1: plt.xticks(the_range) else: plt.xticks(()) ax = plt.gca() ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') plt.title("%s normalizing" % ("Without" if j == 0 else "With")) plt.draw() plt.pause(0.01) def built_net(xs, ys, norm): # 搭建網(wǎng)絡(luò)函數(shù) # 添加層 def add_layer(inputs, in_size, out_size, activation_function=None, norm=False): Weights = tf.Variable(tf.random_normal([in_size, out_size], mean=0.0, stddev=1.0)) biases = tf.Variable(tf.zeros([1, out_size]) + 0.1) Wx_plus_b = tf.matmul(inputs, Weights) + biases if norm: # 判斷是否是Batch Normalization層 # 計(jì)算均值和方差,axes參數(shù)0表示batch維度 fc_mean, fc_var = tf.nn.moments(Wx_plus_b, axes=[0]) scale = tf.Variable(tf.ones([out_size])) shift = tf.Variable(tf.zeros([out_size])) epsilon = 0.001 # 定義滑動平均模型對象 ema = tf.train.ExponentialMovingAverage(decay=0.5) def mean_var_with_update(): ema_apply_op = ema.apply([fc_mean, fc_var]) with tf.control_dependencies([ema_apply_op]): return tf.identity(fc_mean), tf.identity(fc_var) mean, var = mean_var_with_update() Wx_plus_b = tf.nn.batch_normalization(Wx_plus_b, mean, var, shift, scale, epsilon) if activation_function is None: outputs = Wx_plus_b else: outputs = activation_function(Wx_plus_b) return outputs fix_seed(1) if norm: # 為第一層進(jìn)行BN fc_mean, fc_var = tf.nn.moments(xs, axes=[0]) scale = tf.Variable(tf.ones([1])) shift = tf.Variable(tf.zeros([1])) epsilon = 0.001 ema = tf.train.ExponentialMovingAverage(decay=0.5) def mean_var_with_update(): ema_apply_op = ema.apply([fc_mean, fc_var]) with tf.control_dependencies([ema_apply_op]): return tf.identity(fc_mean), tf.identity(fc_var) mean, var = mean_var_with_update() xs = tf.nn.batch_normalization(xs, mean, var, shift, scale, epsilon) layers_inputs = [xs] # 記錄每一層的輸入 for l_n in range(N_LAYERS): # 依次添加7層 layer_input = layers_inputs[l_n] in_size = layers_inputs[l_n].get_shape()[1].value output = add_layer(layer_input, in_size, N_HIDDEN_UNITS, ACTIVITION, norm) layers_inputs.append(output) prediction = add_layer(layers_inputs[-1], 30, 1, activation_function=None) cost = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction), reduction_indices=[1])) train_op = tf.train.GradientDescentOptimizer(0.001).minimize(cost) return [train_op, cost, layers_inputs] fix_seed(1) x_data = np.linspace(-7, 10, 2500)[:, np.newaxis] np.random.shuffle(x_data) noise =np.random.normal(0, 8, x_data.shape) y_data = np.square(x_data) - 5 + noise plt.scatter(x_data, y_data) plt.show() xs = tf.placeholder(tf.float32, [None, 1]) ys = tf.placeholder(tf.float32, [None, 1]) train_op, cost, layers_inputs = built_net(xs, ys, norm=False) train_op_norm, cost_norm, layers_inputs_norm = built_net(xs, ys, norm=True) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) cost_his = [] cost_his_norm = [] record_step = 5 plt.ion() plt.figure(figsize=(7, 3)) for i in range(250): if i % 50 == 0: all_inputs, all_inputs_norm = sess.run([layers_inputs, layers_inputs_norm], feed_dict={xs: x_data, ys: y_data}) plot_his(all_inputs, all_inputs_norm) sess.run([train_op, train_op_norm], feed_dict={xs: x_data[i*10:i*10+10], ys: y_data[i*10:i*10+10]}) if i % record_step == 0: cost_his.append(sess.run(cost, feed_dict={xs: x_data, ys: y_data})) cost_his_norm.append(sess.run(cost_norm, feed_dict={xs: x_data, ys: y_data})) plt.ioff() plt.figure() plt.plot(np.arange(len(cost_his))*record_step, np.array(cost_his), label='Without BN') # no norm plt.plot(np.arange(len(cost_his))*record_step, np.array(cost_his_norm), label='With BN') # norm plt.legend() plt.show()
2. 實(shí)驗(yàn)結(jié)果
輸入數(shù)據(jù)分布:
批標(biāo)準(zhǔn)化BN效果對比:
感謝各位的閱讀!關(guān)于“TensorFlow如何實(shí)現(xiàn)Batch Normalization”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。