【问题标题】:Keras: simple neural network with simple data not workingKeras:简单数据的简单神经网络不起作用
【发布时间】:2020-12-09 05:27:01
【问题描述】:

我尝试创建一个非常简单的神经网络:一个隐藏层,两个神经元。对于一些非常简单的数据:只有一个特征。

import numpy as np
X=np.concatenate([np.linspace(0,10,100),np.linspace(11,20,100),np.linspace(21,30,100)])
y=np.concatenate([np.repeat(0,100),np.repeat(1,100),np.repeat(0,100)])

这是模型

from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(2, activation='sigmoid'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['accuracy'])
model.fit(X, y, epochs=200)

理论上,这个模型应该可行。但即使经过 1000 个 epoch,准确率仍然是 0.667。

Epoch 999/1000
10/10 [==============================] - 0s 1ms/step - loss: 0.5567 - accuracy: 0.6667
Epoch 1000/1000
10/10 [==============================] - 0s 2ms/step - loss: 0.5566 - accuracy: 0.6667

我认为我做错了什么。你能建议一些修改吗?

似乎有很多局部最小值,而初始化可以改变最终模型。在 R 中使用包 nnet 进行测试时就是这种情况。我必须测试很多种子,我发现了这个模型(以及其他模型)。

这就是我想用 keras 创建的结构:一个带有 2 个神经元的隐藏层。激活函数是sigmoid。

所以我想知道 keras 是否有同样的初始化问题。在 R 中使用这个包nnet,我认为它不是一个“完美”的包。我认为 keras 会更高效。如果初始化很重要,keras 会测试不同的初始化吗?如果不是为什么?也许是因为一般来说,使用更多数据(和更多功能),它会更好地工作(无需测试许多初始化)?

例如,使用 kmeans,似乎测试了不同的初始化。

【问题讨论】:

    标签: python tensorflow keras neural-network


    【解决方案1】:

    这个问题显示了输入数据归一化对于神经网络的重要性。如果没有归一化,训练神经网络有时会很困难,因为优化可能会卡在一些局部最小值。

    我想从数据集的可视化开始。数据集是一维的,在使用标准归一化进行归一化后如下所示。

    X_original = np.concatenate([np.linspace(0, 10, 100), np.linspace(
    11, 20, 100), np.linspace(21, 30, 100)])
    X = (X_original - X_original.mean())/X_original.std()
    
    y = np.concatenate(
            [np.repeat(0, 100), np.repeat(1, 100), np.repeat(0, 100)])
    plt.figure()
    plt.scatter(X, np.zeros(X.shape[0]), c=y)
    plt.show()
    

    将这些数据点分成各自的类的最佳方法是在输入空间上画两条线。由于输入空间是一维的,分类边界就是一维的点。

    这意味着单层网络(例如逻辑回归)无法对该数据集进行分类。但是具有两层后接非线性激活的神经网络应该能够对数据集进行分类。

    现在通过标准化和以下训练脚本,模型可以轻松学习对点进行分类。

    model = Sequential()
    model.add(Dense(2, activation='sigmoid'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy',
                      optimizer=keras.optimizers.Adam(1e-1), metrics=['accuracy'])
    model.fit(X, y, epochs=20)
    
    
    Train on 300 samples
    Epoch 1/20
    300/300 [==============================] - 1s 2ms/sample - loss: 0.6455 - accuracy: 0.6467
    Epoch 2/20
    300/300 [==============================] - 0s 79us/sample - loss: 0.6493 - accuracy: 0.6667
    Epoch 3/20
    300/300 [==============================] - 0s 85us/sample - loss: 0.6397 - accuracy: 0.6667
    Epoch 4/20
    300/300 [==============================] - 0s 100us/sample - loss: 0.6362 - accuracy: 0.6667
    Epoch 5/20
    300/300 [==============================] - 0s 115us/sample - loss: 0.6342 - accuracy: 0.6667
    Epoch 6/20
    300/300 [==============================] - 0s 96us/sample - loss: 0.6317 - accuracy: 0.6667
    Epoch 7/20
    300/300 [==============================] - 0s 93us/sample - loss: 0.6110 - accuracy: 0.6667
    Epoch 8/20
    300/300 [==============================] - 0s 110us/sample - loss: 0.5746 - accuracy: 0.6667
    Epoch 9/20
    300/300 [==============================] - 0s 142us/sample - loss: 0.5103 - accuracy: 0.6900
    Epoch 10/20
    300/300 [==============================] - 0s 124us/sample - loss: 0.4207 - accuracy: 0.9367
    Epoch 11/20
    300/300 [==============================] - 0s 124us/sample - loss: 0.3283 - accuracy: 0.9833
    Epoch 12/20
    300/300 [==============================] - 0s 124us/sample - loss: 0.2553 - accuracy: 0.9800
    Epoch 13/20
    300/300 [==============================] - 0s 138us/sample - loss: 0.2030 - accuracy: 1.0000
    Epoch 14/20
    300/300 [==============================] - 0s 124us/sample - loss: 0.1624 - accuracy: 1.0000
    Epoch 15/20
    300/300 [==============================] - 0s 150us/sample - loss: 0.1375 - accuracy: 1.0000
    Epoch 16/20
    300/300 [==============================] - 0s 122us/sample - loss: 0.1161 - accuracy: 1.0000
    Epoch 17/20
    300/300 [==============================] - 0s 115us/sample - loss: 0.1025 - accuracy: 1.0000
    Epoch 18/20
    300/300 [==============================] - 0s 126us/sample - loss: 0.0893 - accuracy: 1.0000
    Epoch 19/20
    300/300 [==============================] - 0s 121us/sample - loss: 0.0804 - accuracy: 1.0000
    Epoch 20/20
    300/300 [==============================] - 0s 132us/sample - loss: 0.0720 - accuracy: 1.0000
    

    由于模型非常简单,学习率和优化器的选择会影响学习的速度。使用 SGD 优化器和学习率 1e-1,模型的训练时间可能比学习率相同的 Adam 优化器要长。

    【讨论】:

    • 非常感谢您的回答,我们可以看到规范化的重要性。对于多元线性回归,似乎对数据进行归一化也很重要。 理论上没有影响,但在数值求解优化问题时很重要。
    • 你有更多关于标准化如何影响梯度下降的信息吗?我不明白为什么这是一个这么大的问题。我的意思是,我们可以让梯度下降“更强大”。因为理论上,我认为归一化不会减少局部最小值的数量,不是吗?
    • 通常,当您使用标准归一化进行归一化时,您会减少数据集的方差并将数据集集中在零附近。这将有助于更好地收敛。但理论上,你可以找到一组超参数和权重初始化,即使没有标准化也可以让你学习。
    • 使用 10 个数据点进行测试时,keras 无法(快速)收敛。我们应该为小数据集使用哪个优化器?我知道对于真实的用例,我们有更多的数据,但这只是为了说明目的。
    猜你喜欢
    • 1970-01-01
    • 2019-01-23
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 2016-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多