【问题标题】:batch normalization, yes or no?批量标准化,是或否?
【发布时间】:2020-02-25 00:13:21
【问题描述】:

我使用 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 个 epoch 后的最终 val_loss 为 0.7751。当我取消注释添加批量标准化层的唯一注释行时,val_loss 更改为 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

【问题讨论】:

  • 我似乎无法用 tensorflow 2.0 重现相同的行为。你使用的是 tensorflow 1.x 吗?
  • @kluu 是的,我使用 Tensorflow 1.14.0 和 Keras 2.2.4。你得到什么结果? BN 对你来说更好吗?
  • 是的,BN 更好。使用完全相同的代码(除了 tensorflow 的种子设置器),我得到一个不带 BN 的 val_loss: 1.1346 和带 BN 层的 val_loss: 1.0833
  • 与该问题无关 (?),但仅由线性激活组成的 NN 没有多大意义(我非常怀疑是否有人尝试过使用这种配置的 BN)。
  • @desertnaut 我强烈反对。具有一个隐藏层和线性激活的 NN 有点像 PCA。有很多关于这方面的论文。对我来说,这个设置在隐藏层和输出的所有激活函数组合中给出了最小的 MSE。

标签: python keras neural-network batch-normalization


【解决方案1】:

是的。

您观察到的行为是一个错误 - 您不需要 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')

显然是荒谬的,因为activation=None (=='linear') 的层之后的Activation('linear') 是一个身份model.layers[1].output.name == 'activation/activation/Identity:0'。这可以通过获取和绘制中间层输出来进一步确认,'dense''activation' 的输出相同 - 此处将省略。

所以,激活实际上什么都不做,除了它没有 - 在 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 中仍然是一个“有争议”的层,尚未完全修复 - 请参阅 Relevant Git;我计划最终自己调查它,但为了您的目的,这个答案的修复应该足够了。

我还建议您熟悉 BN 的基本理论,特别是关于它的训练与推理操作;简而言之,小于 32 的批量大小是一个非常糟糕的主意,并且数据集应该足够大以允许 BN 准确地逼近测试集 gammabeta


使用的代码:

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

【讨论】:

  • 非常感谢您对此进行调查,感谢您抽出宝贵时间。我不知道这个错误。真奇怪。我赞成你的回答。我也想看看其他人的回答。
  • @Albert 你几乎没有机会看到任何接近这个答案的深度和质量的东西,即使是远程;请务必查看 OP 对 TensorFlow 2 vs TensorFlow 1 performance issues 的令人难以置信的调查。
  • @desertnaut 谢谢。
  • @desertnaut 介意我在简历中使用您的评论吗?类似于 - [为什么是 TF2...] - “令人难以置信的调查”,C. I. Tsatsoulis,Nodalpoint Systems 的首席数据科学家。 -- 可以通过这个获得一些分数 - 怀疑有人会打扰你
  • @OverLordGoldDragon 一定要!虽然 SO cmets 是“二等公民”,他们可能会在没有警告的情况下被移除;所以,我刚刚为你发了一个tweet ;)
猜你喜欢
  • 2019-11-13
  • 2017-02-17
  • 2017-10-21
  • 2017-03-03
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 2022-01-21
  • 2018-06-05
相关资源
最近更新 更多