Мультиклассовая классификация Keras всегда предсказывает одну и ту же метку

#python #tensorflow #keras

#питон #тензорный поток #keras

Вопрос:

Я хочу обучить модель предсказывать эмоции человека по физическим сигналам. У меня есть три физических сигнала, и я использую их в качестве входных функций;

экг (электрокардиография), gsr (кожно-гальваническая реакция), temp (температура)

В моем наборе данных всего 312 записей, принадлежащих участникам, и в каждой записи содержится 18000 строк данных. Поэтому, когда я объединяю их в один фрейм данных, всего получается 5616000 строк.

Вот мой фрейм данных x_train ;

            ecg     gsr   temp
0        0.1912  0.0000  40.10
1        0.3597  0.0000  40.26
2        0.3597  0.0000  40.20
3        0.3597  0.0000  40.20
4        0.3597  0.0000  40.33
5        0.3597  0.0000  40.03
6        0.2739  0.0039  40.13
7        0.1641  0.0031  40.20
8        0.0776  0.0025  40.20
9        0.0005  0.0020  40.26
10      -0.0375  0.0016  40.03
11      -0.0676  0.0013  40.16
12      -0.1071  0.0010  40.20
13      -0.1197  0.0047  40.20
..      .......  ......  .....
..      .......  ......  .....
..      .......  ......  .....
5616000 0.0226  0.1803  38.43
 

И у меня есть 6 классов, которые соответствуют эмоциям. Я закодировал эти метки цифрами;

гнев = 0, спокойствие = 1, отвращение = 2, страх = 3, счастье = 4, печаль = 5

Вот мой y_train;

          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,3) #because I have 18000 rows in each record and 3 input features
train_y = train_y.values.reshape(312,18000)

trunc_train_y = train_y[:,:1] # to get 1 label for every 18000 column vector of signal
train_y_enc = pd.DataFrame(trunc_train_y) 
train_y_enc = pd.get_dummies(train_y_enc[0]) # one hot encoded labels
 

После изменения формы я создал свою модель CNN;

 model = Sequential()
model.add(Conv1D(2,700,activation='relu',input_shape=(18000,3)))
model.add(Conv1D(2,700,activation='relu'))
model.add(MaxPooling1D(4))
model.add(Conv1D(2,700,activation='relu'))
model.add(Conv1D(2,700,activation='relu'))
model.add(GlobalAveragePooling1D())
model.add(Dropout(0.5))
model.add(Dense(6,activation='softmax'))

model.compile(optimizer = sgd, loss = 'categorical_crossentropy', metrics = ['acc'])
model.fit(train_x,train_y_enc,epochs = 300, batch_size = 32, validation_split=0.33, shuffle=False)
 

Проблема в том, что точность не превышает 0,2, и когда я проверяю прогнозы, они всегда предсказывают один и тот же класс. Я пытался увеличить уровни, поиграть со скоростью обучения, изменить функцию потерь, изменить оптимизатор, но ничто не помогло мне решить эту проблему.

Вот матрица путаницы;

введите описание изображения здесь

Как я могу решить эту проблему? Заранее спасибо.

Комментарии:

1. Ваша обработка данных выглядит очень странно. Я думаю, так и должно быть (train_sample_length, num_features) . Кроме того, почему ваша train_y форма (312,18000) ? Должно быть (train_sample_length, num_classes). , я вижу в вашем случае num_features=3 и num_classes=5 .

2. @Anakin, потому что у меня всего 312 разных записей. Я переношу сигналы так, чтобы каждая последовательность сигналов соответствовала одной строке. Таким образом, в каждой строке имеется 18006 столбцов (длина сигнала одна метка с горячим кодированием). Я выполняю операцию транспонирования, потому что я не хочу помечать каждую миллисекунду сигнала, лучше транспонировать его и помечать только один раз.

3. Получил часть 312. Возможно, вам следует рассмотреть все 5616000 строк, перетасовать данные и разделить их на обучение и проверку

4. @Anakin, если я собираюсь перетасовать его в форме с 5616000 строк, тогда вся структура сигналов будет нарушена.

5. Возможно, я неправильно понял вашу проблему. Хорошо, скажите мне: для прогнозирования вы хотите ввести 3D-вектор [ecg gsr temp] и предсказать emotion ?

Ответ №1:

В определении уровня Conv1D допущена ошибка. Из кода очевидно, что вы определили 2 фильтра и ядро размером 700, однако обычно используется около 3 фильтров и большое количество фильтров. Попробуйте использовать это и обучаться без разделения проверки.

 `model = Sequential() 
 model.add(Conv1D(64, 3, activation='relu', input_shape=(18000, 3))) 
 model.add(Conv1D(64, 3, activation='relu')) 
 model.add(MaxPooling1D(3)) 
 model.add(Conv1D(128, 3, activation='relu')) 
 model.add(Conv1D(128, 3, activation='relu')) 
 model.add(GlobalAveragePooling1D()) 
 model.add(Dropout(0.5)) 
 model.add(Dense(6, activation='softmax')) `
 

Комментарии:

1. Это скорее комментарий, чем ответ.

2. Если я удалю GlobalAvaragePoolling1D(), это приведет к ошибке. Error when checking target: expected dense_9 to have 3 dimensions, but got array with shape (312, 6)