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

Python 为什么重塑我的数据会完全改变Keras中完全连接的神经网络的行为?,python,tensorflow,keras,neural-network,Python,Tensorflow,Keras,Neural Network,我想了解一下这方面的情况。我正在用一个简单的神经网络研究Keras中的回归问题。我有训练和测试数据,训练数据由33230个样本和20020个特征组成(对于这一数量的数据来说,这是一大堆特征,但这是另一回事——这些特征只是各种测量)。测试集是8308个具有相同数量特征的样本。我的数据位于pandas数据框中,我将其转换为numpy数组,看起来与预期一致: X_train = np.array(X_train_df) X_train.shape (33230, 20020) X_test = n

我想了解一下这方面的情况。我正在用一个简单的神经网络研究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'])
适合:

5个时期后的结果(此后没有实质性变化,培训损失下降,验证损失上升):

但是,如果我重塑数据:

X_test = X_test.reshape(8308, 20020, 1)
X_train = X_train.reshape(33230, 20020, 1)
然后在第一层之后使用相同的模型,并使用展平()

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倍,但在测试集上表现良好。我不明白为什么会这样。有人能解释一下吗?我猜我遗漏了一些非常基本的东西,但我不知道是什么。

一个非常好的问题。首先,你必须了解网络是如何工作的<代码>密集层是一个完全连接的层,因此每个神经元将与前一层的神经元连接。现在,您提到的网络性能是
1000x
时间变慢,这与您的训练数据无关,而是与您的网络有关。你的第二个网络太大了,我无法将它安装在我的RAM中,也无法安装在Google Colab中。因此,出于演示目的,我将假定您的培训数据为
(500100)
形状

对于您发布的第一个采用上述形状的网络,您的模型网络如下所示:

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
_________________________________________________________________
记下总参数,它是
150801
。 现在我们来看你的第二个例子

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
_________________________________________________________________
您的总参数增加到
9031101
。您可以在使用长度为
20020
的实际数据时进行成像。你的模型像任何东西一样增长,我甚至无法在我的内存中安装该模型

总之,与第一个模型相比,您的第二个模型具有大量的参数。这就是为什么训练速度慢,表现可能更好?参数越多,学习效果越好。如果不查看您的数据,就无法说明是什么让它变得更好。但更多的参数有助于提高性能

注意:如果删除
展平
层,网络参数将减少,如下示例

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
_________________________________________________________________
我希望我的回答能帮助你理解什么是Haping以及两种模型之间的区别

更新:20/07 对于你的评论,我认为最好更新答案,以便更清楚。您的问题是--参数的数量与网络的形状有什么关系?

老实说,我不清楚你这是什么意思。我还是会尽力回答的。添加的层或神经元越多,网络和可训练参数的数量就会增加

因此,您的实际问题是,为什么层
变平
会增加您的参数。为此,您需要了解参数是如何计算的

model.add(Dense(300, activation="relu", input_shape=(100,)))
考虑到这是您的第一层,参数的数量将是
单位*(输入大小+1)
,即
30300
。现在,当您添加
展平
层时,这实际上不会增加参数本身,但
展平
层的输出会输入到下一层。请考虑下面的例子。

_________________________________________________________________
flatten_2 (Flatten)          (None, 30000)             0         
_________________________________________________________________
dense_15 (Dense)             (None, 300)               9000300   
_________________________________________________________________
在这里您可以看到
Flatten
层的输出大小是
30000
。现在考虑上述公式,您可以看到
300*(30000+1)
将产生
9000300
参数,这本身就是一个巨大的问题。更多的参数有助于了解更多的特性,并可能有助于获得更好的结果。但这总是取决于数据,你必须用它进行实验


我希望以上的解释能消除你的疑虑。

这是一个很好的问题。首先,你必须了解网络是如何工作的<代码>密集
层是一个完全连接的层,因此每个神经元将与前一层的神经元连接。现在,您提到的网络性能是
1000x
时间变慢,这与您的训练数据无关,而是与您的网络有关。你的第二个网络太大了,我无法将它安装在我的RAM中,也无法安装在Google Colab中。因此,出于演示目的,我将假定您的培训数据为
(500100)
形状

对于您发布的第一个采用上述形状的网络,您的模型网络如下所示:

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
_________________________________________________________________
记下总参数,它是
150801
。 现在我们来看你的第二个例子

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
_________________________________________________________________
您的总参数增加到
9031101
。您可以在使用长度为
20020
的实际数据时进行成像。你的模型像任何东西一样增长,我甚至无法在我的内存中安装该模型

总之,与第一个模型相比,您的第二个模型具有大量的参数。这就是为什么训练速度慢,表现可能更好?参数越多,学习效果越好。如果不查看您的数据,就无法说明是什么让它变得更好。但更多的参数有助于提高性能

注意:如果删除
展平
层,网络参数将减少,如下示例

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
_________________________________________________________________
我希望我的回答能帮助你理解什么是Haping以及两种模型之间的区别

更新:20/07 我想请你发表意见