批量归一化不适合非高斯输入吗?

人工智能 神经网络 深度学习 深度神经网络 批量标准化
2021-10-30 01:06:27

我生成了一些非高斯数据,并使用了两种 DNN 模型,一种有 BN,另一种没有 BN。

我发现带有BN的模型DNN不能很好地预测。

代码如下所示:

import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense,Dropout,Activation, BatchNormalization

np.random.seed(1)

# generate non-gaussian data
def generate_data():
    distribution = scipy.stats.gengamma(1, 70, loc=10, scale=100)
    x = distribution.rvs(size=10000)
    # plt.hist(x)
    # plt.show()
    print ('[mean, var, skew, kurtosis]', distribution.stats('mvsk'))

    y = np.sin(x) + np.cos(x) + np.sqrt(x)
    plt.hist(y)
    # plt.show()
    # print(y)
    return x ,y 

x, y = generate_data()

x_train = x[:int(len(x)*0.8)]
y_train = y[:int(len(y)*0.8)]
x_test = x[int(len(x)*0.8):]
y_test = y[int(len(y)*0.8):]


def DNN(input_dim, output_dim, useBN = True):
    '''
    定义一个DNN model
    '''
    model=Sequential()

    model.add(Dense(128,input_dim= input_dim))
    if useBN:
        model.add(BatchNormalization())
    model.add(Activation('tanh'))
    model.add(Dropout(0.5))

    model.add(Dense(50))
    if useBN:
        model.add(BatchNormalization())
    model.add(Activation('tanh'))
    model.add(Dropout(0.5))

    model.add(Dense(output_dim))
    if useBN:
        model.add(BatchNormalization())
    model.add(Activation('relu'))

    model.compile(loss= 'mse', optimizer= 'adam')
    return model

clf = DNN(1, 1, useBN = True)
clf.fit(x_train, y_train, epochs= 30, batch_size = 100, verbose=2, validation_data = (x_test, y_test))

y_pred = clf.predict(x_test)
def mse(y_pred, y_test):
    return np.mean(np.square(y_pred - y_test))
print('final result', mse(y_pred, y_test))

输入x是这样的形状:

在此处输入图像描述

如果我添加BN层,结果如下所示:

Epoch 27/30
 - 0s - loss: 56.2231 - val_loss: 47.5757
Epoch 28/30
 - 0s - loss: 55.1271 - val_loss: 60.4838
Epoch 29/30
 - 0s - loss: 53.9937 - val_loss: 87.3845
Epoch 30/30
 - 0s - loss: 52.8232 - val_loss: 47.4544
final result 48.204881459013244

如果我不添加BN层,预测结果会更好:

Epoch 27/30
 - 0s - loss: 2.6863 - val_loss: 0.8924
Epoch 28/30
 - 0s - loss: 2.6562 - val_loss: 0.9120
Epoch 29/30
 - 0s - loss: 2.6440 - val_loss: 0.9027
Epoch 30/30
 - 0s - loss: 2.6225 - val_loss: 0.9022
final result 0.9021717561981543

任何人都知道为什么 BN 不适合非高斯数据的理论?

1个回答

因此,批量归一化有助于基于下降的学习更轻松地遍历损失流形,但在您的情况下,您将它与 relu 一起使用,因为最终激活是有问题的,这意味着输出与批次中的其他样本相对相关。

删除最后一个 BN,你会得到更好的结果,但也要理解 BN 对于这项任务本身就是有问题的。将 DNN 视为特征化器,在这种情况下,BN 会取出 2 个批次范围的统计数据,如果它们与初始分布不一致,则会导致错误,从而导致输出错误。从理论上讲,如果 BN 获得了完美的高斯统计数据,它应该不会太重要,所以我用你的代码尝试的一件事是删除最后一个 BN 并将 N 增加到 100,000,同时将批量大小增加到 10000,你会看到性能的巨大提升.