当前位置: 首页 > 知识库问答 >
问题:

批量规范化,是还是否?

阎丰
2023-03-14

我使用Tensorflow 1.14.0和Keras 2.2.4。以下代码实现了一个简单的神经网络:

import numpy as np
np.random.seed(1)
import random
random.seed(2)
import tensorflow as tf
tf.set_random_seed(3)

from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.layers import Input, Dense, Activation


x_train=np.random.normal(0,1,(100,12))

model = Sequential()
model.add(Dense(8, input_shape=(12,)))
# model.add(tf.keras.layers.BatchNormalization())
model.add(Activation('linear'))
model.add(Dense(12))
model.add(Activation('linear'))
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(x_train, x_train,epochs=20, validation_split=0.1, shuffle=False,verbose=2)

20个时代后的最终val\u损失为0.7751。当我取消注释添加批处理规范化层的唯一注释行时,val\u损失变为1.1230。

我的主要问题要复杂得多,但同样的事情也会发生。因为我的激活是线性的,所以我把批处理规范化放在激活之后还是之前并不重要。

问题:为什么批处理规范化帮不上忙?是否有什么可以更改的,以便在不更改激活函数的情况下,批量规范化可以改进结果?

收到评论后更新:

具有一个隐藏层和线性激活的NN有点像PCA。有很多关于这方面的论文。对我来说,在隐藏层和输出的所有激活函数组合中,此设置提供了最小的MSE。

一些状态线性激活的资源意味着PCA:

https://arxiv.org/pdf/1702.07800.pdf

https://link.springer.com/article/10.1007/BF00275687

https://www.quora.com/How-can-I-make-a-neural-network-to-work-as-a-PCA

共有1个答案

曾瀚昂
2023-03-14

你观察到的行为是一个bug,你不需要BN就能看到它;左侧的绘图用于V1,右侧的绘图用于V2:

#V1
model = Sequential()
model.add(Dense(8, input_shape=(12,)))
#model.add(Activation('linear')) <-- uncomment == #V2
model.add(Dense(12))
model.compile(optimizer='adam', loss='mean_squared_error')

。图层【1】。输出名称==“激活/激活/标识:0”。这可以通过获取和绘制中间层输出进一步确认,中间层输出与“密集”和“激活”相同,此处将省略。

因此,激活实际上什么都不做,除了它没有——在1.14.0和2.0.0之间的提交链的某个地方,这是固定的,尽管我不知道在哪里。使用TF 2.0.0和Keras 2.3.1得出的结果(含BN)如下:

val_loss = 0.840 # without BN
val_loss = 0.819 # with BN

解决方案:更新至TensorFlow 2.0.0、Keras 2.3.1。

提示:使用带有虚拟环境的Anaconda。如果您还没有任何虚拟环境,请运行:

conda create --name tf2_env --clone base
conda activate tf2_env
conda uninstall tensorflow-gpu
conda uninstall keras
conda install -c anaconda tensorflow-gpu==2.0.0
conda install -c conda-forge keras==2.3.1

可能比这更复杂,但这是另一个问题的主题。

更新:从keras导入,而不是从tf导入。keras也解决了这个问题。

免责声明:BN在Keras中仍然是一个“有争议的”层,尚未完全修复-请参阅相关Git;我计划最终自己调查一下,但为了你的目的,这个答案的修正应该足够了。

我还建议您熟悉BN的基本理论,尤其是关于它的训练与推理操作;简而言之,批量大小低于32是一个非常糟糕的主意,数据集应该足够大,以允许BN精确地近似测试集gamma和beta。

使用的代码:

x_train=np.random.normal(0, 1, (100, 12))

model = Sequential()
model.add(Dense(8, input_shape=(12,)))
#model.add(Activation('linear'))
#model.add(tf.keras.layers.BatchNormalization())
model.add(Dense(12))
model.compile(optimizer='adam', loss='mean_squared_error')

W_sum_all = []  # fit rewritten to allow runtime weight collection
for _ in range(20):
    for i in range(9):
        x = x_train[i*10:(i+1)*10]
        model.train_on_batch(x, x)

        W_sum_all.append([])
        for layer in model.layers:
            if layer.trainable_weights != []:
                W_sum_all[-1] += [np.sum(layer.get_weights()[0])]
model.evaluate(x[-10:], x[-10:])

plt.plot(W_sum_all)
plt.title("Sum of weights (#V1)", weight='bold', fontsize=14)
plt.legend(labels=["dense", "dense_1"], fontsize=14)
plt.gcf().set_size_inches(7, 4)

导入/预执行:

import numpy as np
np.random.seed(1)
import random
random.seed(2)
import tensorflow as tf
if tf.__version__[0] == '2':
    tf.random.set_seed(3)
else:
    tf.set_random_seed(3)

import matplotlib.pyplot as plt
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.layers import Input, Dense, Activation
 类似资料:
  • 我可以在输入层之后使用批处理规范化层而不规范化我的数据吗?我可以期望得到类似的效果/性能吗? 在keras函数中,它应该是这样的:

  • 在TensorFlow中执行批量规格化的正确方法是什么?(即,我不想计算连续均值和方差)。我当前的实现基于tf。nn。batch\u normalization(批次规格化),其中x是具有形状的卷积层的输出。[批次大小、宽度、高度、通道数]。我想在通道方面执行批处理规范。 但这种实施的结果非常糟糕。与tensorflow比较。承包商。苗条的batch\u norm显示其票价较低(同样糟糕的培训表现

  • BatchNormalization层 keras.layers.normalization.BatchNormalization(epsilon=1e-06, mode=0, axis=-1, momentum=0.9, weights=None, beta_init='zero', gamma_init='one') 该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接

  • BatchNormalization层 keras.layers.normalization.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer='zeros', gamma_initializer='ones', moving_mean_initia

  • 我了解批次归一化有助于更快的训练,将激活转向单位高斯分布,从而解决梯度消失问题。批次规范行为在训练(使用每个批次的平均值/var)和测试时间(使用训练阶段的最终运行平均值/var)中的应用不同。 另一方面,实例归一化作为对比度归一化,如本文所述https://arxiv.org/abs/1607.08022。作者提到,输出样式化的图像不应依赖于输入内容图像的对比度,因此实例规范化有助于实现。 但是

  • 但似乎每个tensorflow实现(包括这个和官方的tensorflow实现)都使用(指数)移动平均和方差。 请原谅我,但我不明白为什么。是不是因为使用移动平均值对性能更好?还是纯粹为了计算速度? 参考:原稿