TensorFlow BatchNormal

本文介绍Batch Normalization在深度学习中的应用,通过TensorFlow实现并详细解释了tf.layers.batch_normalization接口的使用,包括training参数的作用及如何正确计算loss。通过在波士顿房价数据集上的实验,展示了使用BN层对模型训练的影响。

原理篇可以参考这几个:

https://www.cnblogs.com/guoyaohua/p/8724433.html

https://www.cnblogs.com/makefile/p/batch-norm.html

https://blog.youkuaiyun.com/qq_25737169/article/details/79048516        

本文调用的batch normal接口是 tf.layers.batch_normalization,需要注意的是tf.layers.batch_normalization中的training参数,因为在正态归一化后,还有两个变量用来放缩和位移,这两个变量在需要训练。所以training这个参数在训练阶段需要为True,在预测阶段为False。另外,计算loss时,要添加以下代码(即添加update_ops到最后的train_op中),tf.layers.batch_normalization 会自动将 update_ops 添加到 tf.GraphKeys.UPDATE_OPS 这个 collection 中(注:training 参数为 True 时,才会添加,False 时不添加)

extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(extra_update_ops):
        self.train_op = tf.train.AdamOptimizer(self.lr).minimize(self.loss)

完整代码:

import tensorflow as tf
import numpy as np
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split


class NN_BN:
    def __init__(self, in_dim, lr=0.01):
        self.in_dim = in_dim
        self.lr = lr
        self.X = tf.placeholder(dtype=tf.float32, shape=[None, self.in_dim], name='input_x')
        self.y = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='input_y')
        self.training = tf.placeholder_with_default(False, shape=(), name='training')
        self.yhat = self._build_graph()
        self.loss = tf.reduce_mean(tf.square(self.y - self.yhat))
        extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
        with tf.control_dependencies(extra_update_ops):
            self.train_op = tf.train.AdamOptimizer(self.lr).minimize(self.loss)
        self.sess = tf.Session()
        self.sess.run(tf.global_variables_initializer())

    def _build_graph(self):
        l1 = tf.layers.dense(self.X, 256, activation=tf.nn.relu)
        bn1 = tf.layers.batch_normalization(l1, training=self.training)
        l2 = tf.layers.dense(bn1, 128, activation=tf.nn.relu)
        bn2 = tf.layers.batch_normalization(l2, training=self.training)
        l3 = tf.layers.dense(bn2, 64, activation=tf.nn.relu)
        output = tf.layers.dense(l3, 1)
        return output

    def fit(self, X, y, epoch):
        for i in range(epoch):
            loss = self.sess.run(self.loss, feed_dict={self.X: X, self.y: y, self.training: True})
            print('Epoch', i, ', loss:', loss)
            self.sess.run(self.train_op, feed_dict={self.X: X, self.y: y, self.training: True})

    def predict(self, X):
        return self.sess.run(self.yhat, feed_dict={self.X: X, self.training: False})


def run():
    X, y = load_boston(return_X_y=True)
    y = y.reshape(-1, 1)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
    print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
    model = NN_BN(X.shape[1])
    model.fit(X_train, y_train, epoch=256)
    y_pred = model.predict(X_test)
    loss = np.mean(np.square(y_pred - y_test))
    print('Test loss:', loss)


if __name__ == '__main__':
    run()

使用公开数据集:波士顿房价,一共354条数据,按7 : 3 随机划分训练集和测试集。

测试:

与不使用batch normal相比,训练误差明显降低。但测试误差多次测试发现并不稳定,与不使用BN没有明显的提升(猜测原因:一是可能与训练数据量有关,这个数据集太小,在训练集正态归一化的时候,可能存在误差;二是网络结构比较简单,层数太少,本来就基本不存在梯度消失或梯度爆炸问题,所以加上BN的效果也不是很大)。

<think>好的,我现在要帮用户理解神经网络中的Batch Normalization(批归一化)。首先,我需要回顾一下自己对这个概念的理解,并参考用户提供的资料。 根据引用[1],Batch Norm是在神经网络的层之间进行的归一化技术,针对小批量数据而不是整个数据集,目的是加速训练和使用更高的学习率。引用[2]提到,它通过标准化层的输入来缓解内部协变量偏移,提高训练稳定性。而引用[3]则比较了批归一化和白化的关系,指出BN通过缩放激活值到零均值和单位方差来提升性能,并且平滑了优化环境。 用户的问题是关于BN的概念和使用方法,我需要从这些信息中提炼出关键点。首先解释BN的基本概念,然后说明其工作原理,接着可能涉及实现步骤或代码示例,再讨论其优点和适用场景,最后回答相关问题。 需要确保使用正确的中文表达,行内公式用$...$,独立公式用$$...$$。例如,归一化的公式应该用独立公式展示。同时,注意引用标记的位置,比如在解释内部协变量偏移时,引用[2]和[3]。 接下来,用户可能想知道BN的具体操作步骤,比如如何计算均值和方差,如何进行缩放和偏移。这部分需要详细说明,并可能给出一个简单的代码示例,比如使用PyTorch或TensorFlow的实现。但用户提供的引用中没有代码,但根据引用[2]的标题,可能有代码实例讲解,可以假设代码部分需要展示BN层的应用。 另外,用户可能会对BN的优点和常见问题感兴趣,比如为什么能加速训练、与Dropout的关系、在训练和测试阶段的区别等。需要结合引用中的信息,例如引用[3]提到BN减少了内部协变量偏移,而引用[1]提到允许更高的学习率。 还需要注意BN在不同网络结构中的应用,比如卷积网络中的处理方式,可能需要调整维度。比如在CNN中,BN会按通道进行归一化,每个通道有自己的均值和方差,这可能需要解释清楚。 最后,生成的相关问题需要围绕BN的机制、优点、实现细节、与其他技术的比较等,比如与Layer Normalization的区别,训练和测试阶段的差异,或者如何与Dropout结合使用。 检查是否所有数学表达式都正确使用LaTeX格式,例如均值μ和方差σ²的计算,缩放参数γ和β的引入。确保没有使用Markdown格式,而是纯文本,但代码块需要用三个反引号包裹,并标明语言。 总结回答的结构:概念、工作原理、实现步骤、代码示例、优点、应用场景、注意事项,最后相关问题。确保每个部分引用正确的来源,比如提到内部协变量偏移时引用[2]和[3],提到训练加速时引用[1]和[3]。</think>### Batch Normalization(批归一化)概念与使用方法 #### 1. **基本概念** Batch Normalization(BN)是一种神经网络中的标准化技术,通过对每层输入的**小批量数据**进行归一化处理,缓解**内部协变量偏移**(Internal Covariate Shift)[^2][^3],从而提升模型训练速度和稳定性。其核心思想是将每层的输入分布调整为**零均值和单位方差**,并通过可学习的参数进行缩放和平移,保留网络的表达能力。 #### 2. **工作原理** 1. **归一化计算**: 对于每个小批量数据$B = \{x_1, x_2, ..., x_m\}$,计算该批次的均值$\mu_B$和方差$\sigma_B^2$: $$ \mu_B = \frac{1}{m} \sum_{i=1}^m x_i $$ $$ \sigma_B^2 = \frac{1}{m} \sum_{i=1}^m (x_i - \mu_B)^2 $$ 然后将输入数据归一化为: $$ \hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} $$ 其中$\epsilon$是为防止除零的小常数(如$10^{-5}$)。 2. **缩放与平移**: 引入可学习的参数$\gamma$(缩放因子)和$\beta$(平移因子),输出为: $$ y_i = \gamma \hat{x}_i + \beta $$ 这一步骤使网络能够恢复因归一化而丢失的非线性特性[^2]。 #### 3. **实现步骤** - **训练阶段**: 使用当前批次的统计量(均值、方差)进行归一化,并更新全局移动平均的均值和方差,用于推理阶段。 - **推理阶段**: 使用训练阶段积累的全局均值和方差,而非当前批次数据,保证输出稳定[^1][^3]。 #### 4. **代码示例(PyTorch)** ```python import torch.nn as nn # 定义包含BN的神经网络层 model = nn.Sequential( nn.Linear(784, 256), nn.BatchNorm1d(256), # 全连接层的BN nn.ReLU(), nn.Linear(256, 10) ) # 卷积网络中的BN(按通道归一化) conv_model = nn.Sequential( nn.Conv2d(3, 16, kernel_size=3), nn.BatchNorm2d(16), # 对16个通道分别归一化 nn.ReLU() ) ``` #### 5. **核心优势** - **加速训练**:允许使用更高的学习率,减少梯度消失/爆炸问题[^1][^4]。 - **正则化效果**:通过引入噪声(小批量统计量的波动),减少对Dropout的依赖。 - **平滑损失曲面**:使优化过程更稳定,模型对参数初始化的敏感性降低[^3]。 #### 6. **应用场景** - **深层网络**:如ResNet、Transformer等,BN是标准组件。 - **高学习率训练**:避免因学习率过大导致的震荡。 - **对抗过拟合**:与小批量数据结合,提供轻微正则化效果。 #### 7. **注意事项** - **批量大小限制**:小批量(如batch size < 16)可能导致统计量估计不准确。 - **与Dropout的配合**:部分研究表明二者可能相互干扰,需谨慎使用[^3]。 - **测试阶段处理**:需关闭训练模式(`model.eval()`),固定全局统计量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值