You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

面部表情识别程序逻辑错误求助:模型准确率95%但预测异常

面部表情识别模型预测异常问题

模型训练准确率达95%,但对任意输入图像进行情绪预测时,总是输出同一种情绪。代码无语法错误,已尝试增加数据集、调整网络层等方法,问题仍未解决。

核心代码(省略数据预处理与导入部分)

classes = ['angry','disgust', 'fear', 'happy', 'neutral','sad', 'surprise']
training_data = []
x = []
y = []
for feature, label in training_data:
  x.append(feature)
  y.append(label)
X = np.array(x).reshape(-1,224,224,3)
Y = np.array(y)

model = tf.keras.applications.MobileNetV2()
base_input = model.layers[0].input
base_output = model.layers[-2].output
final_output = layers.Dense(128)(base_output)
final_output = layers.Activation("relu")(final_output)
final_output = layers.Dense(64)(final_output)
final_output = layers.Activation("relu")(final_output)
final_output = layers.Dense(7,activation="softmax")(final_output)
new_model = keras.Model(inputs = base_input, outputs = final_output)
new_model.summary()
new_model.compile(loss = 'sparse_categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
new_model.save("emotion_detection")

test_image = cv2.imread("/content/Happy image to test.jpg")
img_bcp = test_image.copy()

face_classifier = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

gray_img = cv2.cvtColor(test_image, cv2.COLOR_BGR2GRAY)

faces_coordinates = face_classifier.detectMultiScale(gray_img)

for (x, y, w, h) in faces_coordinates:
    # 绘制人脸框
    cv2.rectangle(test_image, (x, y), (x + w, y + h), (0, 255, 0), 2)
    # 裁剪人脸区域
    cropped_face = img_bcp[y:y+h, x:x+w]

plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(test_image, cv2.COLOR_BGR2RGB))

plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(cropped_face, cv2.COLOR_BGR2RGB))

class_dictionary = {0: 'angry', 1: 'fear', 2: 'happy', 3: 'neutral', 4: 'sad', 5: 'surprise'}
 
final_image = cv2.resize(cropped_face, (224,224))
final_image = np.expand_dims(final_image, axis=0) # 增加维度适配模型输入
final_image = final_image/255.0 # 归一化

new_model = tf.keras.models.load_model('emotion_detection')
prediction = new_model.predict(final_image)
class_dictionary[np.argmax(prediction)]

相关截图说明

  • 训练准确率截图:训练集准确率达到95%
  • 错误输出截图:所有测试图像的预测结果均为同一种情绪

问题排查与解决方案

1. 类别映射完全错误

原代码中classes定义了7类情绪,但class_dictionary只包含6类,且索引对应错误(跳过了disgust类别),这会导致预测结果的显示完全混乱,甚至出现“固定输出同一种情绪”的假象。

修正方案:
直接基于classes生成对应字典,保证索引与类别完全匹配:

class_dictionary = {i: cls for i, cls in enumerate(classes)}
# 对应关系:0:angry,1:disgust,2:fear,3:happy,4:neutral,5:sad,6:surprise

2. 输入预处理不符合预训练模型要求

MobileNetV2预训练模型的输入预处理要求将像素值缩放到[-1, 1]区间,而非代码中的[0, 1]。错误的归一化方式会导致输入特征分布与训练时完全偏离,模型无法正确提取特征,最终输出异常。

修正方案:
替换归一化代码为官方标准预处理:

final_image = cv2.resize(cropped_face, (224,224))
final_image = np.expand_dims(final_image, axis=0)
# 使用MobileNetV2专用预处理
final_image = tf.keras.applications.mobilenet_v2.preprocess_input(final_image)

3. 训练过程存在潜在问题

  • 类别不平衡: 若训练集中某类情绪样本占比极高,模型会倾向于预测该类,导致所有输入输出同一种情绪。可通过np.bincount(Y)查看标签分布,采用过采样、欠采样或训练时添加class_weight参数解决。
  • 预训练模型未冻结: 直接训练整个MobileNetV2会破坏预训练权重,导致模型泛化能力极差。建议先冻结base层训练头部,再解冻部分层微调:
    # 构建base模型时冻结所有层
    model = tf.keras.applications.MobileNetV2(weights='imagenet', include_top=False)
    for layer in model.layers:
        layer.trainable = False
    # 之后构建头部并训练,训练完成后可解冻部分顶层微调
    
  • 过拟合: 训练集95%准确率但测试异常,可能是训练集过拟合。需添加验证集监控,增加数据增强、Dropout层等抑制过拟合。

4. 人脸检测后的图像验证

检查裁剪后的人脸图像是否有效:打印cropped_face.shape确认是否成功裁剪到人脸,若人脸检测失败(返回空坐标),会导致输入无效图像,模型输出固定结果。

内容的提问来源于stack exchange,提问作者Veg Roast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 09:14:55