为什么重塑我的数据会完全改变 Keras 中完全连接的神经网络的行为?

我希望对此有所了解。我正在使用简单的神经网络处理 Keras 中的回归问题。我有训练和测试数据,训练数据由 33230 个样本组成,具有 20020 个特征(对于这个数据量来说,这是一大堆特征,但那是另一回事了——特征只是各种测量)。测试集是 8308 个具有相同数量特征的样本。我的数据在 pandas 数据框中,我将其转换为看起来符合预期的 numpy 数组:


X_train = np.array(X_train_df)

X_train.shape


(33230, 20020)


X_test = np.array(X_test_df)

X_test.shape


(8308, 20020)

如果我将其传递到以下完全连接的模型中,它会非常快速地训练,并在测试集上产生糟糕的结果:


模型:


model = Sequential()

model.add(Dense(300, activation="relu", input_shape=(20020,)))

model.add(Dense(300, activation="relu"))

model.add(Dense(100, activation="relu"))

model.add(Dense(1, activation='linear'))

model.compile(optimizer='adam', loss='mse',  metrics=['mean_absolute_error'])

合身:


model.fit(x=X_train, y=y_train, validation_data=(X_test,  y_test), batch_size=128, shuffle=True, epochs=100)

5 个 epoch 后的结果(此后基本没有变化,训练损失下降,验证损失猛增):


Train on 33230 samples, validate on 8308 samples

Epoch 1/100

33230/33230 [==============================] - 11s 322us/sample - loss: 217.6460 - mean_absolute_error: 9.6896 - val_loss: 92.2517 - val_mean_absolute_error: 7.6400

Epoch 2/100

33230/33230 [==============================] - 10s 308us/sample - loss: 70.0501 - mean_absolute_error: 7.0170 - val_loss: 90.1813 - val_mean_absolute_error: 7.5721

Epoch 3/100

33230/33230 [==============================] - 10s 309us/sample - loss: 62.5253 - mean_absolute_error: 6.6401 - val_loss: 104.1333 - val_mean_absolute_error: 8.0131

Epoch 4/100

33230/33230 [==============================] - 11s 335us/sample - loss: 55.6250 - mean_absolute_error: 6.2346 - val_loss: 142.8665 - val_mean_absolute_error: 9.3112

Epoch 5/100

33230/33230 [==============================] - 10s 311us/sample - loss: 51.7378 - mean_absolute_error: 5.9570 - val_loss: 208.8995 - val_mean_absolute_error: 11.4158

但是,如果我重塑数据:


X_test = X_test.reshape(8308, 20020, 1)

X_train = X_train.reshape(33230, 20020, 1)


狐的传说
浏览 73回答 1
1回答

一只名叫tom的猫

一个很好的问题。首先,您必须了解网络的实际工作原理。Dense层是一个完全连接的层,因此每个神经元都将与前一层的神经元建立连接。现在您提到的网络性能变慢1000x与您的训练数据无关,而与您的网络有关。你的第二个网络太大了,我无法将它放入我的 RAM 中,也无法放入 Google Colab 中。因此,出于演示目的,我会认为您的训练数据是有(500, 100)形状的。对于您发布的采用上述形状的第一个网络,您的模型网络如下所示:model = Sequential()model.add(Dense(300, activation="relu", input_shape=(100,)))model.add(Dense(300, activation="relu"))model.add(Dense(100, activation="relu"))model.add(Dense(1, activation='linear'))model.compile(optimizer='adam', loss='mse',  metrics=['mean_absolute_error'])Model: "sequential_1"_________________________________________________________________Layer (type)                 Output Shape              Param #   =================================================================dense_2 (Dense)              (None, 300)               30300     _________________________________________________________________dense_3 (Dense)              (None, 300)               90300     _________________________________________________________________dense_4 (Dense)              (None, 100)               30100     _________________________________________________________________dense_5 (Dense)              (None, 1)                 101       =================================================================Total params: 150,801Trainable params: 150,801Non-trainable params: 0_________________________________________________________________记下 Total 参数,它是150,801. 现在,如果我们以你的第二个例子为例。model1 = Sequential()model1.add(Dense(300, activation="relu", input_shape=(100,1)))model1.add(Flatten())model1.add(Dense(300, activation="relu"))model1.add(Dense(100, activation="relu"))model1.add(Dense(1, activation='linear'))model1.compile(optimizer='adam', loss='mse',  metrics=['mean_absolute_error'])Model: "sequential_4"_________________________________________________________________Layer (type)                 Output Shape              Param #   =================================================================dense_14 (Dense)             (None, 100, 300)          600       _________________________________________________________________flatten_2 (Flatten)          (None, 30000)             0         _________________________________________________________________dense_15 (Dense)             (None, 300)               9000300   _________________________________________________________________dense_16 (Dense)             (None, 100)               30100     _________________________________________________________________dense_17 (Dense)             (None, 1)                 101       =================================================================Total params: 9,031,101Trainable params: 9,031,101Non-trainable params: 0_________________________________________________________________您的总参数增加到9,031,101. 当您使用具有 length 的实际数据时,您可以想象20020。你的模型像任何东西一样增加,我什至无法在我的 RAM 中安装该模型。因此总而言之,与第一个模型相比,您的第二个模型具有大量参数。这可能是训练缓慢而性能更好的原因?更多的参数使学习更好。如果不实际查看您的数据,就不能说是什么让它变得更好。但是更多的参数可以带来更好的性能。注意:如果您删除该Flatten层,您的网络参数将减少,这是示例。model1 = Sequential()model1.add(Dense(300, activation="relu", input_shape=(100,1)))model1.add(Dense(300, activation="relu"))model1.add(Dense(100, activation="relu"))model1.add(Dense(1, activation='linear'))model1.compile(optimizer='adam', loss='mse',  metrics=['mean_absolute_error'])Model: "sequential_5"_________________________________________________________________Layer (type)                 Output Shape              Param #   =================================================================dense_18 (Dense)             (None, 100, 300)          600       _________________________________________________________________dense_19 (Dense)             (None, 100, 300)          90300     _________________________________________________________________dense_20 (Dense)             (None, 100, 100)          30100     _________________________________________________________________dense_21 (Dense)             (None, 100, 1)            101       =================================================================Total params: 121,101Trainable params: 121,101Non-trainable params: 0_________________________________________________________________我希望我的回答能帮助您了解正在发生的事情以及两种模型之间的区别。更新:20/07 对于您的评论,我认为最好更新答案以便更清楚。您的问题是——参数的数量与网络的形状有何关系?老实说,我不太清楚你的意思。我仍然会尝试回答它。添加的层或神经元越多,网络和可训练参数的数量就会增加。所以你的实际问题是为什么层会Flatten增加你的参数。为此,您需要了解如何计算参数。model.add(Dense(300, activation="relu", input_shape=(100,)))units *(input_size + 1)考虑这是你的第一层参数的数量30300。现在你加层的时候Flatten,其实这本身并没有增加你的参数,而是层的输出Flatten输入到下一层。因此请考虑以下示例。_________________________________________________________________flatten_2 (Flatten)          (None, 30000)             0         _________________________________________________________________dense_15 (Dense)             (None, 300)               9000300   _________________________________________________________________在这里你可以看到层的输出大小Flatten是30000. 现在考虑上面的公式,您可以看到300 *(30000 + 1)将产生9000300本身很重要的参数。更多数量的参数可以帮助学习更多的特征,并可能有助于获得更好的结果。但这始终取决于数据,您将不得不对其进行试验。我希望以上解释可能已经消除了您的疑虑。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python