【问题标题】:Getting constant accuracies for training and validation sets despite their losses are changing during CNN training?在 CNN 训练期间,尽管有损失,但仍能获得持续的训练和验证集准确度?
【发布时间】:2021-04-05 19:13:06
【问题描述】:

正如标题清楚地描述了我在训练我的 CNN 模型期间遇到的问题,训练集和验证集的准确性是恒定的,尽管它们的损失在变化。我在下面包含了有关模型及其训练设置的详细信息。什么可能导致此问题?

以下是训练(X_train & y_train)、验证和测试集(X_testy_test)使用的数据:

df = pd.read_csv(CSV_PATH, sep=',', header=None)
print(f'Shape of all data: {df.shape}')
    
y = df.iloc[:, -1].values
X = df.iloc[:, :-1].values

encoder = LabelEncoder()
encoder.fit(y)
encoded_Y = encoder.transform(y)
dummy_y = to_categorical(encoded_Y)

X_train, X_test, y_train, y_test = train_test_split(X, dummy_y, test_size=0.3, random_state=RANDOM_STATE)

X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], 1))
X_test = X_test.reshape((X_test.shape[0], X_test.shape[1], 1))

以下是训练集和测试集的形状:

Shape of X_train: (1322, 10800, 1)
Shape of Y_train: (1322, 3)
Shape of X_test: (567, 10800, 1)
Shape of y_test: (567, 3)

这是我的 CNN 模型:

# Model hyper-parameters
activation_fn = 'relu'
n_lr = 1e-4
weight_decay = 1e-4
batch_size = 64
num_epochs = 200*10*10
num_classes = 3
n_dropout = 0.6
n_momentum = 0.5
n_kernel = 5
n_reg = 1e-5

# the sequential model
model = Sequential()
model.add(Conv1D(128, n_kernel, input_shape=(10800, 1)))
model.add(BatchNormalization())
model.add(Activation(activation_fn))
model.add(MaxPooling1D(pool_size=2, strides=2))

model.add(Dropout(n_dropout))

model.add(Conv1D(256, n_kernel))
model.add(BatchNormalization())
model.add(Activation(activation_fn))
model.add(MaxPooling1D(pool_size=2, strides=2))

model.add(Dropout(n_dropout))

model.add(GlobalAveragePooling1D()) # have tried model.add(Flatten()) as well

model.add(Dense(256, activation=activation_fn))
model.add(Dropout(n_dropout))
model.add(Dense(64, activation=activation_fn))
model.add(Dropout(n_dropout))
model.add(Dense(num_classes, activation='softmax'))

adam = Adam(lr=n_lr, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=weight_decay)
model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['acc'])

这是我评估模型的方式:

Y_pred = model.predict(X_test, verbose=0)
y_pred = np.argmax(Y_pred, axis=1)
y_test_int = np.argmax(y_test, axis=1)

而且,我的模型在模型评估过程中总是预测三个类的同一类,从下面的分类结果可以看出(通过classification_result(y_test_int, y_pred)函数):

          precision    recall  f1-score   support

  normal      0.743     1.000     0.852       421
     apb      0.000     0.000     0.000        45
     pvc      0.000     0.000     0.000       101

使用KerasEarlyStopping 回调训练模型。因此,训练持续了4,173 epochs。以下是训练集和验证集在训练过程中获得的损失:

以下是在训练和验证集的训练过程中获得的准确度:

该模型使用 Keras 实现并托管在 Google Colab 上。

【问题讨论】:

  • 你为什么将 to_categorical 应用于预测?
  • 出于与训练数据相同的原因:将标签、整数转换为虚拟数据。我不应该应用这种转换吗? @史努比博士
  • 不,我们正在为您的标签讨论 argmax(训练后)。
  • 我们的意思是,您的 真实标签 仍然是 one-hot-encoded,对它们应用 argmax 以便与预测进行比较。
  • 我明白了,我也会尝试使用 RNN 来查看预测是否会发生变化。如果它们仍然没有改变,我会开始认为数据可能有问题。因为我看不到 CNN 模型有任何错误

标签: tensorflow keras deep-learning neural-network conv-neural-network


【解决方案1】:

虽然没有数据很难解决此类问题,但有一些通用规则适用。

当模型似乎没有学到任何东西时,我们要做的第一件事就是移除所有 dropout

事实上,dropout 是不应该被默认使用的;它名义上的功能是防止过拟合——当然,在开始担心过拟合之前,你必须首先在拟合方面取得一些成功,这显然不会发生这里。事实上,由于n_dropout = 0.6 的退出率,您在使用它时似乎也过于激进,这也无济于事。

【讨论】:

  • 我已经删除了所有Dropout层,但情况还是一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
  • 1970-01-01
  • 2018-07-13
相关资源
最近更新 更多