Правильная предварительная обработка csv-данных для 1D CNN

#python #tensorflow #keras #conv-neural-network #convolution

#python #тензорный поток #keras #conv-нейронная сеть #свертка

Вопрос:

У меня проблема с подготовкой моего набора данных для подачи 1D CNN.

В моем CSV-файле 3025 столбцов, представляющих один байт последний столбец в качестве строковой метки.

Возможно, проблема не в предварительной обработке, а в моей сетевой модели.

Это моя модель:

 def cnn_1d(num_classes):
    model = models.Sequential()
    model.add(Conv1D(16, kernel_size=3, strides=1, activation="relu", input_shape=(3025, 1)))
    model.add(Conv1D(16, kernel_size=3, strides=1, activation="relu"))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Dropout(0.2))
    model.add(Conv1D(32, kernel_size=3, strides=1, activation="relu"))
    model.add(Conv1D(32, kernel_size=3, strides=1, activation="relu"))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Dropout(0.2))
    model.add(Dense(500, activation="relu"))
    model.add(Dense(300, activation="relu"))
    model.add(Dense(num_classes, activation="softmax"))
    model.compile(
        optimizer=keras.optimizers.Adam(1e-3),
        loss="categorical_crossentropy",
        metrics=["accuracy"],
    )
    model.summary()
    return model
  

Это то, что я пытался предварительно обработать данные:

 num_classes = 4
df = pd.read_csv("test.csv", header=0)

df["label"] = pd.Categorical(df["label"])
df["label"] = df.label.cat.codes

Y = df.pop("label")
X = df.copy()

x_train, x_test, y_train, y_test = train_test_split(np.asarray(X), np.asarray(Y), test_size=0.33, shuffle=True)

x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))

model = cnn_1d(num_classes)
model.fit(x_train, y_train, epochs=100, batch_size=64, validation_data=(x_test, y_test))
  

Я думаю, что я получаю ошибку на последнем плотном слое из-за неправильно предварительно обработанных меток. Это я

  ValueError: Shapes (None, 1) and (None, 753, 4) are incompatible
  

Чего мне не хватает? Я знаю, что последний плотный слой должен иметь числовые классы в качестве единицы измерения (4 в моем примере).

Ответ №1:

Это краткое изложение модели кода, представленного выше:

 Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv1d (Conv1D)              (None, 3023, 16)          64        
_________________________________________________________________
conv1d_1 (Conv1D)            (None, 3021, 16)          784       
_________________________________________________________________
max_pooling1d (MaxPooling1D) (None, 1510, 16)          0         
_________________________________________________________________
dropout (Dropout)            (None, 1510, 16)          0         
_________________________________________________________________
conv1d_2 (Conv1D)            (None, 1508, 32)          1568      
_________________________________________________________________
conv1d_3 (Conv1D)            (None, 1506, 32)          3104      
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 753, 32)           0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 753, 32)           0         
_________________________________________________________________
dense (Dense)                (None, 753, 500)          16500     
_________________________________________________________________
dense_1 (Dense)              (None, 753, 300)          150300    
_________________________________________________________________
dense_2 (Dense)              (None, 753, 4)            1204      
=================================================================
Total params: 173,524
Trainable params: 173,524
Non-trainable params: 0
  

Выходной слой имеет размеры (пакет, длина последовательности, 4 класса). Вероятно, вы хотели сгладить матрицу после второго слоя max_pooling.

Если я это сделаю, я получу модель с меньшим количеством параметров и выведу один из 4 классов…

 def cnn_1d(num_classes):
    model = models.Sequential()
    model.add(Conv1D(16, kernel_size=3, strides=1, activation="relu", input_shape=(3025, 1)))
    model.add(Conv1D(16, kernel_size=3, strides=1, activation="relu"))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Dropout(0.2))
    model.add(Conv1D(32, kernel_size=3, strides=1, activation="relu"))
    model.add(Conv1D(32, kernel_size=3, strides=1, activation="relu"))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Flatten())
    model.add(Dropout(0.2))
    model.add(Dense(500, activation="relu"))
    model.add(Dense(300, activation="relu"))
    model.add(Dense(num_classes, activation="softmax"))
    model.compile(
        optimizer=keras.optimizers.Adam(1e-3),
        loss="categorical_crossentropy",
        metrics=["accuracy"],
    )
    model.summary()
    return model
  
cnn_1d(4)

Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv1d_4 (Conv1D)            (None, 3023, 16)          64        
_________________________________________________________________
conv1d_5 (Conv1D)            (None, 3021, 16)          784       
_________________________________________________________________
max_pooling1d_2 (MaxPooling1 (None, 1510, 16)          0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 1510, 16)          0         
_________________________________________________________________
conv1d_6 (Conv1D)            (None, 1508, 32)          1568      
_________________________________________________________________
conv1d_7 (Conv1D)            (None, 1506, 32)          3104      
_________________________________________________________________
max_pooling1d_3 (MaxPooling1 (None, 753, 32)           0         
_________________________________________________________________
flatten (Flatten)            (None, 24096)             0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 24096)             0         
_________________________________________________________________
dense_3 (Dense)              (None, 500)               12048500  
_________________________________________________________________
dense_4 (Dense)              (None, 300)               150300    
_________________________________________________________________
dense_5 (Dense)              (None, 4)                 1204      
=================================================================
Total params: 12,205,524
Trainable params: 12,205,524
Non-trainable params: 0
  

В качестве бонуса эта модель имеет значительно меньше обучаемых параметров.

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

1. Да, я понял, что мне не хватает слоя выравнивания после последнего MaxPool1D, моя ошибка. И, похоже, мне нужно также принудительно использовать to_categorical для переменной y_ * для работы с последним плотным слоем

Ответ №2:

Я понял, чего мне не хватало:

  1. Я пропустил использование to_categorical для переменной y_*. Я думал, что это уже категорично df["label"] = pd.Categorical(df["label"]) . Итак, перед моделью я добавил:
     y_train = to_categorical(y_train, 4)
    y_test = to_categorical(y_test, 4)
      
  2. Я забыл выровнять вывод после последнего слоя MaxPool1D.

Теперь он работает правильно.