簡體   English   中英

為什么重塑我的數據會完全改變 Keras 中全連接神經網絡的行為?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM