Keras:CNN模型不是在学习

问题描述 投票:3回答:8

我想训练一个模型来预测物理信号中的一个人的情绪。我有一个物理信号并用它作为输入功能;

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
python tensorflow keras neural-network deep-learning
8个回答
3
投票

我建议采取几个步骤,并考虑一个更简单的方法。 基于以下内容......

我试图增加图层,使用学习速率,更改损失函数,更改优化器,缩放数据,规范化数据,但没有任何帮助我解决这个问题。我也尝试过更简单的Dense模型或LSTM模型,但我找不到一种有效的方法。

这听起来并不像你对数据和工具的理解那么强烈......这很好,因为这是一个学习的机会。

几个问题

  1. 你有基线模型吗?您是否尝试过运行多项Logistic回归?如果不是,我强烈建议从那里开始。当您增加模型的复杂性时,完成制作此类模型所需的特征工程将是非常宝贵的。
  2. 你检查了课堂失衡吗?
  3. 你为什么使用CNN?你想用卷积层完成什么?对我来说,当我构建一个视觉模型,让我说在我的壁橱里对鞋子进行分类时,我会使用几个卷积层来提取边缘和曲线等空间特征。
  4. 与第三个问题相关...你从哪里获得这个架构?它来自出版物吗?这是ECG迹线的现有技术模型吗?或者这是最容易获得的模型?有时两者不一样。我会深入研究文献并在网上搜索更多有关神经网络和分析心电图痕迹的更多信息。

我想如果你能回答这些问题,你将能够自己解决问题。


1
投票

您实施中的当前问题是,因为您已经为模型使用了(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)

如果以上解决方案不起作用,

  1. 从数据集中绘制类分布,并检查数据中是否存在任何类不平衡。
  2. 由于您的模型过度拟合数据,请尝试创建更多数据(如果您创建此数据集)或为此找到一些数据增强技术。

0
投票

我相信您的代码是正确的,但正如评论者所说,您可能会过度拟合您的数据。

您可能希望在时期内绘制验证准确性和训练准确性,以便将其可视化。

您应首先考虑使用更简单的模型来查看过度拟合问题是否有所改善。请注意,这不太可能提高您的所有性能,但您的验证准确性将更接近您的训练准确度。另一种选择是在卷积层之后立即添加池化层。


0
投票

您可以尝试添加正规分子(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])

0
投票

我怀疑train_y的预处理方式,它无法与您的train_x正确同步。我的问题是,你是否按照基于频率的技术压缩你的y_train? 我认为如果您通过某种基于频率的技术压缩了标签(每行),您已经对数据引入了高偏差。请告诉我压缩是如何完成的!谢谢


0
投票

我建议如下:

  1. 我看到数据点的数量较少。问题越复杂,深度学习模型需要更多的数据点才能学习。查找包含大量数据的类似数据集。在该数据集上训练您的网络并将其转移到您的问题。
  2. 有没有办法增加数据?我看到你的信号长度为18000.你可以使用不同的技术将数据下采样一半并增加数据集。您将使用长度为9000的信号。
  3. 尝试将卷积核心长度减少到3或5,并通过添加另一个转换层来增加模型深度。
  4. 我强烈建议尝试随机森林梯度提升树木,看看它们是如何表现的。

0
投票

一年前,当我在大学完成最后一次任务时,我面临着心电图问题,但使用不同的方法和数据(MIT-BIH)。

看来你用的是单引线,不是吗?您是否尝试过准备数据(如清理心跳噪音)?我的建议是,尽量不将所有数据合并到一个单一的训练列表中,由于人类心跳的性质,可能会发生过度拟合,尝试根据性别或年龄进行训练。在一些文献中,它非常有帮助。

模型不能正常工作,不是因为错误的实现,而是有时我们如何准备好数据。


0
投票

您的模型显然过度拟合数据集。在评论者中没有人考虑过的一个建议是增加步伐。在这里你有kernel size = 700,没有填充和stride = 1。因此,您将从第一个Conv层获得具有形状(None, 17301, 100)的输出。

我会尝试将步幅增加到50到100的数字(将内核移动一小部分2.33/(700/stride)秒)或在每个Conv层之后插入Pooling层。