我正在开发一个深度学习分类器,处理两个类别。我使用的数据集是不平衡的。我通过下采样来解决这个问题。然后,我创建了两个类别的小样本数据,并构建了如下深度学习模型:
dl_model = Sequential()n_cols = X_train.shape[1]dl_model.add(Dense(1024, activation='relu', input_shape=(n_cols,)))dl_model.add(Dense(512, activation='relu'))dl_model.add(Dense(256, activation='relu'))dl_model.add(Dense(256, activation='relu'))dl_model.add(Dense(128, activation='relu'))dl_model.add(Dense(64, activation='relu'))dl_model.add(Dense(2, activation='softmax'))adam= optimizers.Adam(lr=0.001)dl_model.compile(optimizer=adam, loss='sparse_categorical_crossentropy', metrics=['accuracy'])early_stopping_monitor = EarlyStopping(patience=3)dl_model.fit(X_train, y_train, epochs=10, validation_split=0.2, batch_size=1000,callbacks=[early_stopping_monitor], shuffle=True)model_json = dl_model.to_json()with open("model.json", "w") as json_file: json_file.write(model_json)dl_model.save_weights("model.h5")
在不同的超参数调优下,我得到了如下结果:
模型1 – train_loss: 7.7971 - train_acc: 0.5160 - val_loss: 9.6992 - val_acc: 0.3982
模型2 – train_loss: 2.8257 - train_acc: 0.8201 - val_loss: 2.9312 - val_acc: 0.8160
模型3 – train_loss: 3.1887 - train_acc: 0.8002 - val_loss: 3.5195 - val_acc: 0.7808
我保存了这些模型,然后在另一个文件中加载它们,并将模型应用于整个数据集,计算指标如下:
sc = MinMaxScaler()X = sc.fit_transform(X)json_file = open('model.json', 'r')loaded_model_json = json_file.read()json_file.close()loaded_model = model_from_json(loaded_model_json)loaded_model.load_weights("model.h5")loaded_model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])score = loaded_model.evaluate(X, y, verbose=0)print("Deep learning accuracy %s: %.2f%%" % (loaded_model.metrics_names[1], score[1]*100))
上述三个模型都给出了相同的准确率。甚至混淆矩阵也相同。原因可能是什么?三个模型的训练准确率/指标不同,不应该给出不同的结果吗?
更新:
加载任何一个模型时,我得到的准确率都是97.82%
,混淆矩阵如下:
[[143369 0] [ 2958 0]]
回答:
您遇到的问题是所有训练的 neural networks 都无法正确学习到第二个类别,即较少表示的那个类别。
测试集上的准确率相同是因为 model_1、model_2 和 model_3 都无法区分类别1和类别2,因此它们都能识别类别1,但无法识别类别2。换句话说,当您在测试集上进行测试时,结果是相同的,尽管训练过程中看到了差异。
这一观察可以从您展示的混淆矩阵中轻松推断出来。
假设您不知道上述观察,让我们做一些简单的数学计算:
- 143369 + 2958 = 146327。
- (143369/146327) * 100 = 97.97%(与您报告的准确率略有不同,但大致相同——小的差异来自于
evaluate_score
在keras
中的计算)
您也可以从这里推断出(不仅仅是视觉上看到没有类别2的TP(真阳性))您有问题。
现在让我们继续解决这个问题!
既然我们已经提到了这一观察,您需要采取以下措施来解决这个问题(或结合其中的一些措施):
首先,从较低的学习率开始(0.0001是一个更好的起始选择)。
其次,参考以下程序以获得一个好的模型:
- 移除
EarlyStopping(patience=3)
。 - 根据不同于准确率的指标保存最佳模型(例如F1-Score)。
- 在训练过程中降低学习率(ReduceLROnPlateau)。您可以使用以下回调,这在您的案例中比EarlyStopping更合适:https://keras.io/callbacks/#reducelronplateau
- 使用数据集增强。处理不平衡数据集的最佳方法是使用过采样。与其通过下采样来减少数据集的方差,不如通过添加更多的少数类示例来平衡类别的支持度。