如何减少validation_loss并提高年龄预测的准确性?

时间:2021-04-09 13:28:49

标签: tensorflow machine-learning keras

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

欢迎提出任何建议。

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)

1 个答案:

答案 0 :(得分:0)

看起来您正在使用我创建的代码,我推测可能是从 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 来提供帮助。相关教程位于 here. 如果创建混淆矩阵,您可以了解更多有关模型性能的信息。如果您没有测试集,您可以使用验证集。您是否使用生成器将数据输入模型?下面的代码显示了如何创建混淆矩阵。我假设您可以在代码中的某处为验证或测试集提供标签。如果您使用了生成器并设置了 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()