Keras多输出人脸属性预测模型输出负概率、概率和不为1问题求助
问题原因
- 你编译模型时设置了
SparseCategoricalCrossentropy(from_logits=True),这个参数表示模型输出层不需要加softmax激活,直接输出未归一化的logits值,所以predict得到的结果本身就不是概率,自然不满足总和为1、非负的要求。 - 模型结构不匹配输入数据:输入是48*48的二维人脸图像,你使用了一维卷积
Conv1D做特征提取,完全无法正确提取图像的二维空间特征,导致模型训练效果极差、每次重新初始化参数后结果波动很大。 - 卷积层输出没有做拉平处理就直接接全连接层,存在维度不匹配问题,进一步干扰模型训练。
修正方案
方案1:直接转换现有输出为概率
如果你不需要修改已训练的模型,只需对输出的logits做softmax转换,即可得到符合要求的归一化概率:
import tensorflow as tf # 转换性别输出为概率 gender_prob = tf.nn.softmax(predictions[0]).numpy() # 转换族裔输出为概率 ethnicity_prob = tf.nn.softmax(predictions[1]).numpy()
转换后两类输出的概率和均为1,取值范围在0-1之间。
方案2:修正模型结构,直接输出概率
如果要从模型结构层面解决问题,同时提升训练稳定性,修改代码如下:
# 输入层增加灰度图通道维度,适配二维卷积要求 input_layer = keras.Input(shape=(48,48,1),name='img') # 替换为二维卷积提取图像特征 x = keras.layers.Conv2D(128, kernel_size=3, activation='relu')(input_layer) x = keras.layers.MaxPooling2D(pool_size=2)(x) # 拉平卷积输出为一维张量适配全连接层 x = keras.layers.Flatten()(x) # 性别输出分支添加softmax激活,直接输出概率 y1_output = keras.layers.Dense(units=2, activation='softmax', name='genderoutput')(x) # 族裔输出分支 x_eth = keras.layers.Dense(units=64, activation='relu')(x) y2_output = keras.layers.Dense(units=5, activation='softmax', name='ethnicityoutput')(x_eth) model = keras.Model(inputs=input_layer, outputs=[y1_output, y2_output]) # 输出层已加softmax,所以from_logits设置为False model.compile(optimizer='adam', loss={ 'genderoutput': tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), 'ethnicityoutput': tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False) }, metrics=['accuracy'])
调整后model.predict()直接输出的就是符合要求的分类概率,同时特征提取层适配图像结构,训练稳定性会大幅提升,重复初始化的结果波动问题也会得到解决。
内容的提问来源于stack exchange,提问作者dabo1
相关产品推荐
相关产品推荐

