前面三期都是在学习和理解,如果熟悉了头两期,这一期的实践将变得异常简单!
本期目标
- 了解BN的实现
- 观察BN的效果
- 知道BN在train和inference两个阶段的实现细节
系列目录
理解Batch Normalization系列1——原理
理解Batch Normalization系列2——训练及评估
理解Batch Normalization系列3——为什么有效及若干讨论
理解Batch Normalization系列4——实践
文章目录
基于tensorflow1.5.0,python3.6.8,试验数据集为mnist
import numpy as np, tensorflow as tf, tqdm
from tensorflow.examples.tutorials.mnist import input_data
import matplotlib.pyplot as plt
%matplotlib inline
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
print(tf.__version__)
import platform
print(platform.python_version())
Extracting MNIST_data\train-images-idx3-ubyte.gz
Extracting MNIST_data\train-labels-idx1-ubyte.gz
Extracting MNIST_data\t10k-images-idx3-ubyte.gz
Extracting MNIST_data\t10k-labels-idx1-ubyte.gz
1.5.0
3.6.8
构造网络
构建两个全连接神经网络:
- 一个是普通网络,包括2个隐层,1个输出层。
- 一个是有BN的网络,包括2个隐层,1个输出层。
第1层中的BN是我们自定义的,第2层和第3层中的BN是调用tensorflow实现。
定义输入占位符,定义三个层的权重,方便后面使用
w1_initial = np.random.normal(size=(784,100)).astype(np.float32)
w2_initial = np.random.normal(size=(100,100)).astype(np.float32)
w3_initial = np.random.normal(size=(100,10)).astype(np.float32)
# 为BN层准备一个非常小的数字,防止出现分母为0的极端情况。
epsilon = 1e-3
x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
Layer 1 层:无BN
w1 = tf.Variable(w1_initial)
b1 = tf.Variable(tf.zeros([100]))
z1 = tf.matmul(x,w1)+b1
l1 = tf.nn.sigmoid(z1)
Layer 1 层:有BN(自定义BN层)
w1_BN = tf.Variable(w1_initial)
# 因为BN的引入,b的作用被BN层替代,省略。
z1_BN = tf.matmul(x,w1_BN)
# 计算加权和的均值和方差,0是指batch这个维度
batch_mean1, batch_var1 = tf.nn.moments(z1_BN,[0])
# 正则化
z1_hat = (z1_BN - batch_mean1) / tf.sqrt(batch_var1 + epsilon)
# 新建两个变量scale and beta
scale1 = tf.Variable(tf.ones([100]))
beta1 = tf.Variable(tf.zeros([100]))
# 计算被还原的BN1,即BN文章里的y
BN1 = scale1 * z1_hat + beta1
# l1_BN = tf.nn.sigmoid(BN1)
l1_BN = tf.nn.relu(BN1)
Layer 2 层:无BN
w2 = tf.Variable(w2_initial)
b2 = tf.Variable(tf.zeros([100]))
z2 = tf.matmul(l1,w2)+b2
# l2 = tf.nn.sigmoid(z2)
l2 = tf.nn.relu(z2)
Layer 2 层:有BN(使用tensorflow创建BN层)
w2_BN = tf.Variable(w2_initial)
z2_BN = tf.matmul(l1_BN,w2_BN)
# 计算加权和的均值和方差,0是指batch这个维度
batch_mean2, batch_var2 = tf.nn.moments(z2_BN,[0])
# 新建两个变量scale and beta
scale2 = tf.Variable(tf.ones([100]))
beta2 = tf.Variable(tf.zeros([100]))
# 计算被还原的BN2,即BN文章里的y。使用
BN2 = tf.nn.batch_normalization(z2_BN,batch_mean2,batch_var2