TensorFlow衣物分类模型对非训练类图像误预测的解决求助
解决衣物分类模型对非目标图像输出高置信度预测的问题
你的核心问题是模型训练阶段未接触“非衣物”类样本,无法区分目标衣物与无关图像,即使切换到sigmoid激活也无法解决本质问题。以下是具体解决思路与实现方案:
一、添加未知类别样本训练(最根本方案)
让模型学习区分“衣物类”和“非衣物类”的特征差异:
- 收集人脸、风景、日常物品等非衣物图像作为第14类(命名为
unknown),加入训练集与验证集 - 重新训练模型,后续输入非衣物图像时,模型会将其预测为
unknown类
修改后的模型输出层(softmax更适合单分类场景):
# 假设categorys_size更新为14(13类衣物+1类未知) tf.keras.layers.Dense(categorys_size, activation='softmax')
二、设置置信度阈值过滤(快速临时方案)
若暂时无法收集未知类样本,可在预测阶段加入阈值判断:
- 针对softmax输出:取最高置信度,仅当该值超过设定阈值(如0.8)时,返回对应衣物类别;否则返回“无法识别”
- 针对sigmoid输出:因属于多标签输出逻辑,需判断最高置信度是否远高于其他类,且超过阈值(如0.7)
修改Android端预测代码,加入阈值判断:
val outputs = aiModel.process(input) val outputFeature0 = outputs.outputFeature0AsTensorBuffer val confidences = outputFeature0.floatArray var maxPos = 0 var maxConfidence = 0f for (i in confidences.indices) { Log.d("Debug","Ai $i: ${confidences[i]}") if (confidences[i] > maxConfidence) { maxConfidence = confidences[i] maxPos = i } } // 添加阈值判断逻辑 val confidenceThreshold = 0.8f if (maxConfidence >= confidenceThreshold) { Log.d("Prediction", "类别: $maxPos, 置信度: $maxConfidence") } else { Log.d("Prediction", "无法识别该图像") }
三、优化模型结构,增强泛化能力
你的模型全连接层存在冗余(512→256→512),易导致过拟合,对未知图像产生错误高置信度:
- 简化全连接层结构,加入L2正则化与更高比例Dropout:
model = tf.keras.Sequential([ base_model, tf.keras.layers.BatchNormalization(renorm=True), tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(512, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01)), tf.keras.layers.Dropout(0.3), tf.keras.layers.Dense(256, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01)), tf.keras.layers.Dropout(0.3), tf.keras.layers.Dense(categorys_size, activation='softmax') ])
- 若训练数据充足,可微调
base_model的顶部几层(设置base_model.trainable=True后冻结底层,仅训练顶部部分层),让模型更精准学习衣物特征
四、用温度系数调整softmax输出(可选优化)
若坚持使用softmax,可通过温度系数调整输出分布,放大正确类与错误类的置信度差异:
- 训练时保持原结构,预测时对logit层(输出层前一层)结果除以温度系数T(T越小,分布越陡峭),再应用softmax
示例代码:
# 修改模型,拆分输出层为logit与softmax model = tf.keras.Sequential([ base_model, tf.keras.layers.BatchNormalization(renorm=True), tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(512, activation='relu'), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(256, activation='relu'), tf.keras.layers.Dense(categorys_size), # 无激活函数,输出logit ]) # 预测时应用温度系数 def predict_with_temperature(model, input_data, temperature=0.5): logits = model.predict(input_data) probabilities = tf.nn.softmax(logits / temperature).numpy() return probabilities
内容的提问来源于stack exchange,提问作者YOUSEF -ELSAYED
相关产品推荐
相关产品推荐

