首页 > 解决方案 > 如何减少验证损失并提高年龄预测的准确性?

问题描述

我是机器学习的新手,我尝试训练一个模型来预测图像中人的年龄。我在 4 个年龄段(0-18、18-40、40-65、65+)上训练了我的模型。我最大的问题是我不知道如何优化。我把代码和一些结果放在下面。我在 10k 图像上训练了模型,验证集有大约 3.5k 图像,测试集有大约 3k 图像。我使用预学习模型作为基础模型,即“Mobilenet”,批量大小 = 32,时期 = 100,辍学 =.4。我尝试更新学习率,每 10 个时期模型未能减少验证损失,学习率减半(我们从值 0.001 开始)。我希望这种预测的准确性会更好,validation_loss 会低得多(validation_loss 对我来说约为 1)。带结果的图像

欢迎任何建议。

if self.model_type == 'Mobilenet':
            base_model = tf.keras.applications.mobilenet.MobileNet(include_top=False, input_shape=img_shape,
                                                                   pooling='max', weights='imagenet', dropout=.4)
        x = base_model.output
        x = keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001)(x)
        x = Dense(self.neurons_a, activation='relu', kernel_initializer=tf.keras.initializers.GlorotUniform(seed=123))(x)
        x = Dropout(rate=dropout, seed=123)(x)
        output = Dense(self.class_count, activation='softmax',
                       kernel_initializer=tf.keras.initializers.GlorotUniform(seed=123))(x)
        model = Model(inputs=base_model.input, outputs=output)
        model.compile(Adamax(lr=self.lr), loss='categorical_crossentropy', metrics=self.metrics)

标签: tensorflowmachine-learningkeras

解决方案


看起来你正在使用我创建的代码,我猜可能是从 Kaggle 那里得到的。该模型似乎表现良好,训练精度非常高,没有过度拟合的迹象。如您的图所示,验证损失通常会稳定在某个值附近。我能想到的唯一另一件事是评估数据集的平衡。我的意思是查看每个类的训练集中的样本数量。我预计您会出现严重的不平衡,65 岁以上的样本很少。在这种情况下,有几种缓解策略。最简单的是使用model.fit中的class_weights参数。为此,您需要创建一个 class_weights 字典。执行此操作的过程概述如下

Lets say your class distribution is
 0-18 - 500 samples
 18-40- 2000 samples
 40-65 - 1500 samples
 65+ - 200 samples
Then your dictionary would be
class_weights={0: 2000/500, 1:2000/2000, 2: 2000/1500, 3: 2000/200}
in model.fit set class_weight=class_weights

我的经验是,这通常只会带来轻微的改善。还有其他几种方法,例如使用 cv2 或 PIL 创建“增强”图像并将这些增强图像存储在表示不足的类目录中。如果您有不平衡的数据集,您可能需要使用模块 smote 来提供帮助。相关教程位于此处。如果您创建混淆矩阵,您可以更多地了解模型的性能。如果您没有测试集,则可以使用验证集。您是否使用生成器将数据输入到模型中?下面的代码展示了如何创建混淆矩阵。我假设在您的代码中的某个地方,您可以为您的验证或测试集提供标签。如果您使用生成器并设置 shuffle=False,您可以从 labels-gen.labels 从生成器中获取标签。然后使用下面的代码

preds=model.predict(test_gen, batch_size=test_batch_size, verbose=0, steps=None)
labels=test_gen.labels # make sure shuffle=False in the generator
y_pred=[]
classes=['0-18', '18-40', '40-65', '65+']
for i, p in enumerate(preds):
    pred_index=np.argmax(p)
    y_pred.append(pred_index)
y_true= np.array(labels)        
y_pred=np.array(y_pred)   
cm = confusion_matrix(y_true, y_pred )
plt.figure(figsize=(10, 10))
sns.heatmap(cm, annot=True, vmin=0, fmt='g', cmap='Blues', cbar=False)       
plt.xticks(np.arange(length)+.5, classes, rotation= 90)
plt.yticks(np.arange(length)+.5, classes, rotation=0)
plt.xlabel("Predicted")
plt.ylabel("Actual")
plt.title("Confusion Matrix")
plt.show()  

推荐阅读