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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:09:25