![](/img/trans.png)
[英]Why does the last fully-connected/dense layer in a keras neural network expect to have 2 dim even if its input has more dimensions?
[英]Why does reshaping my data completely change the behaviour of a fully connected neural network in Keras?
我很想對此有所了解。 我正在使用簡單的神經網絡解決 Keras 中的回歸問題。 我有訓練和測試數據,訓練數據由 33230 個樣本和 20020 個特征組成(對於這個數據量來說,這是一大堆特征,但那是另一回事——這些特征只是各種測量值)。 測試集是具有相同數量特征的 8308 個樣本。 我的數據在 pandas dataframe 中,我將其轉換為 numpy ZA3CBC3F9D0CE2F2C15954E1 看起來像預期的那樣:DCZE1
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,它會很快訓練,並在測試集上產生糟糕的結果:
Model:
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)
然后在第一層之后使用相同的 model 和 Flatten():
model = Sequential()
model.add(Dense(300, activation="relu", input_shape=(20020,1)))
model.add(Flatten())
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'])
然后我的結果看起來非常不同,而且好多了:
Train on 33230 samples, validate on 8308 samples
Epoch 1/100
33230/33230 [==============================] - 1117s 34ms/sample - loss: 112.4860 - mean_absolute_error: 7.5939 - val_loss: 59.3871 - val_mean_absolute_error: 6.2453
Epoch 2/100
33230/33230 [==============================] - 1112s 33ms/sample - loss: 4.7877 - mean_absolute_error: 1.6323 - val_loss: 23.8041 - val_mean_absolute_error: 3.8226
Epoch 3/100
33230/33230 [==============================] - 1116s 34ms/sample - loss: 2.3945 - mean_absolute_error: 1.1755 - val_loss: 14.9597 - val_mean_absolute_error: 2.8702
Epoch 4/100
33230/33230 [==============================] - 1113s 33ms/sample - loss: 1.5722 - mean_absolute_error: 0.9616 - val_loss: 15.0566 - val_mean_absolute_error: 2.9075
Epoch 5/100
33230/33230 [==============================] - 1117s 34ms/sample - loss: 1.4161 - mean_absolute_error: 0.9179 - val_loss: 11.5235 - val_mean_absolute_error: 2.4781
它也需要 1000 倍的時間,但在測試集上表現良好。 我不明白為什么會這樣。 有人可以解釋一下嗎? 我猜我錯過了一些非常基本的東西,但我不知道是什么。
一個非常好的問題。 首先,您必須了解網絡的實際工作方式。 Dense
層是一個完全連接的層,因此每個神經元都將與前一層的神經元連接。 現在,您提到的網絡性能要慢1000x
,這與您的訓練數據無關,而是與您的網絡有關。 您的第二個網絡太大了,我無法將它放入我的 RAM 中,也無法放入 Google Colab 中。 因此,出於演示目的,我將假設您的訓練數據為(500, 100)
形狀。
對於您發布的采用上述形狀的第一個網絡,您的 model 網絡如下所示:
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,801
Trainable params: 150,801
Non-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,101
Trainable params: 9,031,101
Non-trainable params: 0
_________________________________________________________________
您的總參數增加到9,031,101
。 當您使用長度為20020
的實際數據時,您可以進行映像。 你的 model 像任何東西一樣增加,我什至無法在我的 RAM 中安裝 model。
總而言之,與第一個 model 相比,您的第二個 model 具有大量參數。 這可能是訓練慢而性能更好的原因嗎? 更多的參數使學習更好。 如果不實際查看您的數據,就無法說出是什么讓它變得更好。 但是更多的參數可以有助於更好的性能。
注意:如果您刪除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,101
Trainable params: 121,101
Non-trainable params: 0
_________________________________________________________________
我希望我的回答能幫助您了解什么是 hapening 以及兩種模型之間的區別。
更新:20/07對於您的評論,我認為最好更新答案以更清晰。 你的問題是——參數的數量與網絡的形狀有什么關系?
老實說,我不太清楚你的意思。 我仍然會嘗試回答它。 添加的層或神經元越多,網絡和可訓練參數的數量就會增加。
所以你的實際問題是為什么層Flatten
會增加你的參數。 為此,您需要了解如何計算參數。
model.add(Dense(300, activation="relu", input_shape=(100,)))
考慮這是您的第一層,參數的數量將是units *(input_size + 1)
達到30300
。 現在當你添加Flatten
層的時候,這實際上並沒有自己增加你的參數,而是將Flatten
層的output輸入到下一層。 所以考慮下面的例子。
_________________________________________________________________
flatten_2 (Flatten) (None, 30000) 0
_________________________________________________________________
dense_15 (Dense) (None, 300) 9000300
_________________________________________________________________
在這里可以看到Flatten
層的 output 大小為30000
。 現在考慮上面的公式,您可以看到300 *(30000 + 1)
將產生9000300
參數,這本身就是一筆巨大的交易。 更多數量的參數可以幫助學習更多特征,並可能有助於獲得更好的結果。 但這始終取決於數據,您將不得不對其進行試驗。
我希望以上解釋可以消除您的疑慮。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.