Keras中向损失函数传入权重图时y_true形状异常问题
解决方案
1. 修复验证数据格式不匹配问题
根本原因:训练时传入的是通道数为2的合并张量,但验证数据validation_data=(x_val, y_val)中的y_val仅为单通道掩码,导致损失函数在验证阶段接收到的y_true通道数为1,无法执行拆分操作。
修正步骤:
- 将验证集掩码
y_val与对应的验证权重图weightmap_val合并为通道数2的张量:
import numpy as np # 假设weightmap_val为验证集权重图,形状与y_val一致:(val_samples,256,256,1) new_y_val = np.concatenate([y_val, weightmap_val], axis=-1)
- 更新
model.fit()调用,传入格式匹配的验证数据:
history3 = model.fit( x=x_train, y=new_y_train, validation_data=(x_val, new_y_val), # 使用合并后的验证标签 epochs=50, batch_size=16, callbacks=callbacks )
2. 优化损失与准确率函数(可选)
移除调试打印语句,并用直接索引替代tf.unstack,简化逻辑:
import tensorflow.keras.backend as K def custom_loss_wrapper2(y_true, y_pred): # 直接索引通道,替代unstack操作 target = y_true[..., 0:1] weight = y_true[..., 1:2] y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon()) term_0 = (1 - target) * K.log(1 - y_pred + K.epsilon()) term_1 = target * K.log(y_pred + K.epsilon()) return -K.mean(weight * (term_0 + term_1), axis=-1) def custom_binary_accuracy(y_true, y_pred): target = y_true[..., 0:1] return K.mean(K.equal(target, K.round(y_pred)))
3. 替代方案:将权重图作为模型额外输入
如果不想合并掩码与权重图,可修改模型结构,将权重图作为独立输入传入,逻辑更清晰:
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Dropout, UpSampling2D from tensorflow.keras.models import Model def weighted_fcn(n=32): # 定义两个输入:图像和权重图 input_img = Input(shape=(256, 256, 1)) input_weight = Input(shape=(256, 256, 1)) # 编码器部分 x = Conv2D(n, kernel_size=3, activation='relu', padding='same')(input_img) x = MaxPooling2D(pool_size=2, padding='same')(x) x = Dropout(0.1)(x) x = Conv2D(n*2, kernel_size=3, activation='relu', padding='same')(x) x = MaxPooling2D(pool_size=2, padding='same')(x) x = Dropout(0.1)(x) x = Conv2D(n*4, kernel_size=3, activation='relu', padding='same')(x) x = MaxPooling2D(pool_size=2, padding='same')(x) x = Dropout(0.1)(x) x = Conv2D(n*8, kernel_size=3, activation='relu', padding='same')(x) x = MaxPooling2D(pool_size=2, padding='same')(x) x = Dropout(0.1)(x) x = Conv2D(n*16, kernel_size=3, activation='relu', padding='same')(x) x = MaxPooling2D(pool_size=2, padding='same')(x) x = Dropout(0.1)(x) # 解码器部分 x = UpSampling2D(size=2)(x) x = Dropout(0.1)(x) x = Conv2D(n*8, kernel_size=3, activation='relu', padding='same')(x) x = UpSampling2D(size=2)(x) x = Dropout(0.1)(x) x = Conv2D(n*4, kernel_size=3, activation='relu', padding='same')(x) x = UpSampling2D(size=2)(x) x = Dropout(0.1)(x) x = Conv2D(n*2, kernel_size=3, activation='relu', padding='same')(x) x = UpSampling2D(size=2)(x) x = Dropout(0.1)(x) x = Conv2D(n, kernel_size=3, activation='relu', padding='same')(x) x = UpSampling2D(size=2)(x) outputs = Conv2D(1, kernel_size=3, activation='sigmoid', padding='same')(x) # 定义带权重的损失函数,直接使用输入的权重图 def weighted_loss(y_true, y_pred): y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon()) term_0 = (1 - y_true) * K.log(1 - y_pred + K.epsilon()) term_1 = y_true * K.log(y_pred + K.epsilon()) return -K.mean(input_weight * (term_0 + term_1), axis=-1) model = Model(inputs=[input_img, input_weight], outputs=outputs) model.compile(optimizer='adam', loss=weighted_loss, metrics=[custom_binary_accuracy]) return model # 训练时传入图像和权重图两个输入 history3 = model.fit( x=[x_train, weightmap], y=y_train, validation_data=([x_val, weightmap_val], y_val), epochs=50, batch_size=16, callbacks=callbacks )
内容的提问来源于stack exchange,提问作者Eleanor1118
相关产品推荐
相关产品推荐

