我想训练一个模型来预测物理信号中的一个人的情绪。我有一个物理信号并用它作为输入功能;
ECG(心电图)
在我的数据集中,共有312条记录属于参与者,每条记录中有18000行数据。因此,当我将它们组合成一个数据框时,总共有5616000行。
这是我的train_x
数据帧;
ecg
0 0.1912
1 0.3597
2 0.3597
3 0.3597
4 0.3597
5 0.3597
6 0.2739
7 0.1641
8 0.0776
9 0.0005
10 -0.0375
11 -0.0676
12 -0.1071
13 -0.1197
.. .......
.. .......
.. .......
5616000 0.0226
我有6个与情绪相对应的课程。我用数字编码了这些标签;
愤怒= 0,冷静= 1,厌恶= 2,恐惧= 3,幸福= 4,悲伤= 5
这是我的train_y;
emotion
0 0
1 0
2 0
3 0
4 0
. .
. .
. .
18001 1
18002 1
18003 1
. .
. .
. .
360001 2
360002 2
360003 2
. .
. .
. .
. .
5616000 5
为了给我的CNN提供信息,我正在重新训练train_x和一个热编码train_y数据。
train_x = train_x.values.reshape(312,18000,1)
train_y = train_y.values.reshape(312,18000)
train_y = train_y[:,:1] # truncated train_y to have single corresponding value to a complete signal.
train_y = pd.DataFrame(train_y)
train_y = pd.get_dummies(train_y[0]) #one hot encoded labels
在这些过程之后,这是它们的样子;重塑后的train_x;
[[[0.60399908]
[0.79763273]
[0.79763273]
...
[0.09779361]
[0.09779361]
[0.14732245]]
[[0.70386905]
[0.95101687]
[0.95101687]
...
[0.41530258]
[0.41728671]
[0.42261905]]
[[0.75008021]
[1. ]
[1. ]
...
[0.46412148]
[0.46412148]
[0.46412148]]
...
[[0.60977509]
[0.7756791 ]
[0.7756791 ]
...
[0.12725148]
[0.02755331]
[0.02755331]]
[[0.59939494]
[0.75514785]
[0.75514785]
...
[0.0391334 ]
[0.0391334 ]
[0.0578706 ]]
[[0.5786066 ]
[0.71539303]
[0.71539303]
...
[0.41355098]
[0.41355098]
[0.4112712 ]]]
train_y经过一次热编码;
0 1 2 3 4 5
0 1 0 0 0 0 0
1 1 0 0 0 0 0
2 0 1 0 0 0 0
3 0 1 0 0 0 0
4 0 0 0 0 0 1
5 0 0 0 0 0 1
6 0 0 1 0 0 0
7 0 0 1 0 0 0
8 0 0 0 1 0 0
9 0 0 0 1 0 0
10 0 0 0 0 1 0
11 0 0 0 0 1 0
12 0 0 0 1 0 0
13 0 0 0 1 0 0
14 0 1 0 0 0 0
15 0 1 0 0 0 0
16 1 0 0 0 0 0
17 1 0 0 0 0 0
18 0 0 1 0 0 0
19 0 0 1 0 0 0
20 0 0 0 0 1 0
21 0 0 0 0 1 0
22 0 0 0 0 0 1
23 0 0 0 0 0 1
24 0 0 0 0 0 1
25 0 0 0 0 0 1
26 0 0 1 0 0 0
27 0 0 1 0 0 0
28 0 1 0 0 0 0
29 0 1 0 0 0 0
.. .. .. .. .. .. ..
282 0 0 0 1 0 0
283 0 0 0 1 0 0
284 1 0 0 0 0 0
285 1 0 0 0 0 0
286 0 0 0 0 1 0
287 0 0 0 0 1 0
288 1 0 0 0 0 0
289 1 0 0 0 0 0
290 0 1 0 0 0 0
291 0 1 0 0 0 0
292 0 0 0 1 0 0
293 0 0 0 1 0 0
294 0 0 1 0 0 0
295 0 0 1 0 0 0
296 0 0 0 0 0 1
297 0 0 0 0 0 1
298 0 0 0 0 1 0
299 0 0 0 0 1 0
300 0 0 0 1 0 0
301 0 0 0 1 0 0
302 0 0 1 0 0 0
303 0 0 1 0 0 0
304 0 0 0 0 0 1
305 0 0 0 0 0 1
306 0 1 0 0 0 0
307 0 1 0 0 0 0
308 0 0 0 0 1 0
309 0 0 0 0 1 0
310 1 0 0 0 0 0
311 1 0 0 0 0 0
[312 rows x 6 columns]
重塑后,我创建了CNN模型;
model = Sequential()
model.add(Conv1D(100,700,activation='relu',input_shape=(18000,1))) #kernel_size is 700 because 18000 rows = 60 seconds so 700 rows = ~2.33 seconds and there is two heart beat peak in every 2 second for ecg signal.
model.add(Conv1D(50,700))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling1D(4))
model.add(Flatten())
model.add(Dense(6,activation='softmax'))
adam = keras.optimizers.Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
model.compile(optimizer = adam, loss = 'categorical_crossentropy', metrics = ['acc'])
model.fit(train_x,train_y,epochs = 50, batch_size = 32, validation_split=0.33, shuffle=False)
问题是,准确度不会超过0.2,而且会上下波动。看起来模型没有学到任何东西。我试图增加图层,使用学习速率,更改损失函数,更改优化器,缩放数据,规范化数据,但没有任何帮助我解决这个问题。我也尝试过更简单的Dense模型或LSTM模型,但我找不到一种有效的方法。
我怎么解决这个问题?提前致谢。
加成:
我希望在50个时期之后添加培训结果;
Epoch 1/80
249/249 [==============================] - 24s 96ms/step - loss: 2.3118 - acc: 0.1406 - val_loss: 1.7989 - val_acc: 0.1587
Epoch 2/80
249/249 [==============================] - 19s 76ms/step - loss: 2.0468 - acc: 0.1647 - val_loss: 1.8605 - val_acc: 0.2222
Epoch 3/80
249/249 [==============================] - 19s 76ms/step - loss: 1.9562 - acc: 0.1767 - val_loss: 1.8203 - val_acc: 0.2063
Epoch 4/80
249/249 [==============================] - 19s 75ms/step - loss: 1.9361 - acc: 0.2169 - val_loss: 1.8033 - val_acc: 0.1905
Epoch 5/80
249/249 [==============================] - 19s 74ms/step - loss: 1.8834 - acc: 0.1847 - val_loss: 1.8198 - val_acc: 0.2222
Epoch 6/80
249/249 [==============================] - 19s 75ms/step - loss: 1.8278 - acc: 0.2410 - val_loss: 1.7961 - val_acc: 0.1905
Epoch 7/80
249/249 [==============================] - 19s 75ms/step - loss: 1.8022 - acc: 0.2450 - val_loss: 1.8092 - val_acc: 0.2063
Epoch 8/80
249/249 [==============================] - 19s 75ms/step - loss: 1.7959 - acc: 0.2369 - val_loss: 1.8005 - val_acc: 0.2222
Epoch 9/80
249/249 [==============================] - 19s 75ms/step - loss: 1.7234 - acc: 0.2610 - val_loss: 1.7871 - val_acc: 0.2381
Epoch 10/80
249/249 [==============================] - 19s 75ms/step - loss: 1.6861 - acc: 0.2972 - val_loss: 1.8017 - val_acc: 0.1905
Epoch 11/80
249/249 [==============================] - 19s 75ms/step - loss: 1.6696 - acc: 0.3173 - val_loss: 1.7878 - val_acc: 0.1905
Epoch 12/80
249/249 [==============================] - 19s 75ms/step - loss: 1.5868 - acc: 0.3655 - val_loss: 1.7771 - val_acc: 0.1270
Epoch 13/80
249/249 [==============================] - 19s 75ms/step - loss: 1.5751 - acc: 0.3936 - val_loss: 1.7818 - val_acc: 0.1270
Epoch 14/80
249/249 [==============================] - 19s 75ms/step - loss: 1.5647 - acc: 0.3735 - val_loss: 1.7733 - val_acc: 0.1429
Epoch 15/80
249/249 [==============================] - 19s 75ms/step - loss: 1.4621 - acc: 0.4177 - val_loss: 1.7759 - val_acc: 0.1270
Epoch 16/80
249/249 [==============================] - 19s 75ms/step - loss: 1.4519 - acc: 0.4498 - val_loss: 1.8005 - val_acc: 0.1746
Epoch 17/80
249/249 [==============================] - 19s 75ms/step - loss: 1.4489 - acc: 0.4378 - val_loss: 1.8020 - val_acc: 0.1270
Epoch 18/80
249/249 [==============================] - 19s 75ms/step - loss: 1.4449 - acc: 0.4297 - val_loss: 1.7852 - val_acc: 0.1587
Epoch 19/80
249/249 [==============================] - 19s 75ms/step - loss: 1.3600 - acc: 0.5301 - val_loss: 1.7922 - val_acc: 0.1429
Epoch 20/80
249/249 [==============================] - 19s 75ms/step - loss: 1.3349 - acc: 0.5422 - val_loss: 1.8061 - val_acc: 0.2222
Epoch 21/80
249/249 [==============================] - 19s 75ms/step - loss: 1.2885 - acc: 0.5622 - val_loss: 1.8235 - val_acc: 0.1746
Epoch 22/80
249/249 [==============================] - 19s 75ms/step - loss: 1.2291 - acc: 0.5823 - val_loss: 1.8173 - val_acc: 0.1905
Epoch 23/80
249/249 [==============================] - 19s 75ms/step - loss: 1.1890 - acc: 0.6506 - val_loss: 1.8293 - val_acc: 0.1905
Epoch 24/80
249/249 [==============================] - 19s 75ms/step - loss: 1.1473 - acc: 0.6627 - val_loss: 1.8274 - val_acc: 0.1746
Epoch 25/80
249/249 [==============================] - 19s 75ms/step - loss: 1.1060 - acc: 0.6747 - val_loss: 1.8142 - val_acc: 0.1587
Epoch 26/80
249/249 [==============================] - 19s 75ms/step - loss: 1.0210 - acc: 0.7510 - val_loss: 1.8126 - val_acc: 0.1905
Epoch 27/80
249/249 [==============================] - 19s 75ms/step - loss: 0.9699 - acc: 0.7631 - val_loss: 1.8094 - val_acc: 0.1746
Epoch 28/80
249/249 [==============================] - 19s 75ms/step - loss: 0.9127 - acc: 0.8193 - val_loss: 1.8012 - val_acc: 0.1746
Epoch 29/80
249/249 [==============================] - 19s 75ms/step - loss: 0.9176 - acc: 0.7871 - val_loss: 1.8371 - val_acc: 0.1746
Epoch 30/80
249/249 [==============================] - 19s 75ms/step - loss: 0.8725 - acc: 0.8233 - val_loss: 1.8215 - val_acc: 0.1587
Epoch 31/80
249/249 [==============================] - 19s 75ms/step - loss: 0.8316 - acc: 0.8514 - val_loss: 1.8010 - val_acc: 0.1429
Epoch 32/80
249/249 [==============================] - 19s 75ms/step - loss: 0.7958 - acc: 0.8474 - val_loss: 1.8594 - val_acc: 0.1270
Epoch 33/80
249/249 [==============================] - 19s 75ms/step - loss: 0.7452 - acc: 0.8795 - val_loss: 1.8260 - val_acc: 0.1587
Epoch 34/80
249/249 [==============================] - 19s 75ms/step - loss: 0.7395 - acc: 0.8916 - val_loss: 1.8191 - val_acc: 0.1587
Epoch 35/80
249/249 [==============================] - 19s 75ms/step - loss: 0.6794 - acc: 0.9357 - val_loss: 1.8344 - val_acc: 0.1429
Epoch 36/80
249/249 [==============================] - 19s 75ms/step - loss: 0.6106 - acc: 0.9357 - val_loss: 1.7903 - val_acc: 0.1111
Epoch 37/80
249/249 [==============================] - 19s 75ms/step - loss: 0.5609 - acc: 0.9598 - val_loss: 1.7882 - val_acc: 0.1429
Epoch 38/80
249/249 [==============================] - 19s 75ms/step - loss: 0.5788 - acc: 0.9478 - val_loss: 1.8036 - val_acc: 0.1905
Epoch 39/80
249/249 [==============================] - 19s 75ms/step - loss: 0.5693 - acc: 0.9398 - val_loss: 1.7712 - val_acc: 0.1746
Epoch 40/80
249/249 [==============================] - 19s 75ms/step - loss: 0.4911 - acc: 0.9598 - val_loss: 1.8497 - val_acc: 0.1429
Epoch 41/80
249/249 [==============================] - 19s 75ms/step - loss: 0.4824 - acc: 0.9518 - val_loss: 1.8105 - val_acc: 0.1429
Epoch 42/80
249/249 [==============================] - 19s 75ms/step - loss: 0.4198 - acc: 0.9759 - val_loss: 1.8332 - val_acc: 0.1111
Epoch 43/80
249/249 [==============================] - 19s 75ms/step - loss: 0.3890 - acc: 0.9880 - val_loss: 1.9316 - val_acc: 0.1111
Epoch 44/80
249/249 [==============================] - 19s 75ms/step - loss: 0.3762 - acc: 0.9920 - val_loss: 1.8333 - val_acc: 0.1746
Epoch 45/80
249/249 [==============================] - 19s 75ms/step - loss: 0.3510 - acc: 0.9880 - val_loss: 1.8090 - val_acc: 0.1587
Epoch 46/80
249/249 [==============================] - 19s 75ms/step - loss: 0.3306 - acc: 0.9880 - val_loss: 1.8230 - val_acc: 0.1587
Epoch 47/80
249/249 [==============================] - 19s 75ms/step - loss: 0.2814 - acc: 1.0000 - val_loss: 1.7843 - val_acc: 0.2222
Epoch 48/80
249/249 [==============================] - 19s 75ms/step - loss: 0.2794 - acc: 1.0000 - val_loss: 1.8147 - val_acc: 0.2063
Epoch 49/80
249/249 [==============================] - 19s 75ms/step - loss: 0.2430 - acc: 1.0000 - val_loss: 1.8488 - val_acc: 0.1587
Epoch 50/80
249/249 [==============================] - 19s 75ms/step - loss: 0.2216 - acc: 1.0000 - val_loss: 1.8215 - val_acc: 0.1587
我建议采取几个步骤,并考虑一个更简单的方法。 基于以下内容......
我试图增加图层,使用学习速率,更改损失函数,更改优化器,缩放数据,规范化数据,但没有任何帮助我解决这个问题。我也尝试过更简单的Dense模型或LSTM模型,但我找不到一种有效的方法。
这听起来并不像你对数据和工具的理解那么强烈......这很好,因为这是一个学习的机会。
几个问题
我想如果你能回答这些问题,你将能够自己解决问题。
您实施中的当前问题是,因为您已经为模型使用了(312,18000,1)
形状的数据,您只有312个样本,并且您使用了0.33验证分割,因此,您仅使用209个样本进行培训。
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d_1 (Conv1D) (None, 17301, 100) 70100
_________________________________________________________________
conv1d_2 (Conv1D) (None, 16602, 50) 3500050
_________________________________________________________________
dropout_1 (Dropout) (None, 16602, 50) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 16602, 50) 200
_________________________________________________________________
activation_1 (Activation) (None, 16602, 50) 0
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 4150, 50) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 207500) 0
_________________________________________________________________
dense_1 (Dense) (None, 6) 1245006
=================================================================
Total params: 4,815,356
Trainable params: 4,815,256
Non-trainable params: 100
_________________________________________________________________
正如我所见,model.summary()
,你的模型总共有4,815,256个可训练参数。因此,您的模型很容易过度拟合训练数据。问题是,如果没有足够的样本,您需要学习很多参数。您可以尝试缩小模型大小,如下所示:
model = Sequential()
model.add(Conv1D(100,2,activation='relu',input_shape=(18000,1)))
model.add(Conv1D(10,2))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling1D(4))
model.add(Flatten())
model.add(Dense(6,activation='softmax'))
model.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d_1 (Conv1D) (None, 17999, 100) 300
_________________________________________________________________
conv1d_2 (Conv1D) (None, 17998, 10) 2010
_________________________________________________________________
dropout_1 (Dropout) (None, 17998, 10) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 17998, 10) 40
_________________________________________________________________
activation_1 (Activation) (None, 17998, 10) 0
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 4499, 10) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 44990) 0
_________________________________________________________________
dense_1 (Dense) (None, 6) 269946
=================================================================
Total params: 272,296
Trainable params: 272,276
Non-trainable params: 20
_________________________________________________________________
据我所知,你有3种类型的数据ecg,gsr,temp。所以,你可以使用train_x
作为(312,18000,3)。而你的train_y
将是(312,6)
。
如果以上解决方案不起作用,
我相信您的代码是正确的,但正如评论者所说,您可能会过度拟合您的数据。
您可能希望在时期内绘制验证准确性和训练准确性,以便将其可视化。
您应首先考虑使用更简单的模型来查看过度拟合问题是否有所改善。请注意,这不太可能提高您的所有性能,但您的验证准确性将更接近您的训练准确度。另一种选择是在卷积层之后立即添加池化层。
您可以尝试添加正规分子(L1或L2),检查kernel_initializer
和/或在训练期间通过回调调整学习率。以下示例来自回归模型。
model = Sequential()
model.add(Dense(128, input_dim=dims, activation='relu'))
model.add(Dropout(0.2))
model.add(layers.BatchNormalization())
model.add(Dense(16, activation='relu', kernel_initializer='normal', kernel_regularizer=regularizers.l1(x)))
model.add(Dropout(0.2))
model.add(layers.BatchNormalization())
model.add(Dense(1, kernel_initializer='normal'))
model.compile(optimizer=optimizers.adam(lr=l), loss='mean_squared_error')
reduce_lr = ReduceLROnPlateau(monitor='val_loss', mode='min', factor=0.5, patience=3, min_lr=0.000001, verbose=1, cooldown=0)
history = model.fit(xtrain, ytrain, epochs=epochs, batch_size=batch_size, validation_split=0.3, callbacks=[reduce_lr])
我怀疑train_y的预处理方式,它无法与您的train_x正确同步。我的问题是,你是否按照基于频率的技术压缩你的y_train? 我认为如果您通过某种基于频率的技术压缩了标签(每行),您已经对数据引入了高偏差。请告诉我压缩是如何完成的!谢谢
我建议如下:
一年前,当我在大学完成最后一次任务时,我面临着心电图问题,但使用不同的方法和数据(MIT-BIH)。
看来你用的是单引线,不是吗?您是否尝试过准备数据(如清理心跳噪音)?我的建议是,尽量不将所有数据合并到一个单一的训练列表中,由于人类心跳的性质,可能会发生过度拟合,尝试根据性别或年龄进行训练。在一些文献中,它非常有帮助。
模型不能正常工作,不是因为错误的实现,而是有时我们如何准备好数据。
您的模型显然过度拟合数据集。在评论者中没有人考虑过的一个建议是增加步伐。在这里你有kernel size = 700
,没有填充和stride = 1
。因此,您将从第一个Conv层获得具有形状(None, 17301, 100)
的输出。
我会尝试将步幅增加到50到100的数量(将内核移动一小部分2.33/(700/stride)
秒)或在每个Conv层之后插入Pooling层。