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

Unet模型训练sample_weight维度不匹配致Data cardinality错误排查

解决Unet分割模型样本权重数据基数不匹配问题

问题场景

训练用于冬季卫星图像道路网络识别的Unet模型时,使用compute_sample_weight分配样本权重阶段触发数据基数不匹配错误,训练数据X、Y的样本量为10216,但样本权重数组长度仅为2,无法匹配。

报错信息

Traceback (most recent call last):
  File "D:/Practise/Scripts/4_Multiclass_unet_sandstone.py", line 84, in <module>
    shuffle=False)
  File "C:\Users\User\anaconda3\envs\python_3_6\lib\site-packages\keras\engine\training.py", line 1148, in fit
    steps_per_execution=self._steps_per_execution)
  File "C:\Users\User\anaconda3\envs\python_3_6\lib\site-packages\keras\engine\data_adapter.py", line 1383, in get_data_handler
    return DataHandler(*args, **kwargs)
  File "C:\Users\User\anaconda3\envs\python_3_6\lib\site-packages\keras\engine\data_adapter.py", line 1150, in __init__
    model=model)
  File "C:\Users\User\anaconda3\envs\python_3_6\lib\site-packages\keras\engine\data_adapter.py", line 241, in __init__
    _check_data_cardinality(inputs)
  File "C:\Users\User\anaconda3\envs\python_3_6\lib\site-packages\keras\engine\data_adapter.py", line 1649, in _check_data_cardinality
    raise ValueError(msg)
ValueError: Data cardinality is ambiguous:
  x sizes: 10216
  y sizes: 10216
  sample_weight sizes: 2
Make sure all arrays contain the same number of samples.

Process finished with exit code 1

问题根源

  1. compute_sample_weight调用错误:传入np.unique(train_masks_reshaped_encoded)作为第二个参数,导致函数返回的是2个类别的全局权重,而非每个像素对应的权重数组,长度与训练数据不匹配。
  2. sample_weight_mode设置错误:使用'temporal'适用于序列任务,而图像分割需要逐像素的权重匹配,应设置为'elementwise'。
  3. 数据泄露风险:基于全量掩码计算权重,而非训练集掩码,违反训练/测试分离原则。

修正方案

1. 修正样本权重计算逻辑

基于训练集掩码生成逐像素的权重数组,确保形状与训练标签匹配:

# 提取训练集掩码并展平,仅基于训练集计算权重避免泄露
y_train_flat = y_train.reshape(-1)
# 直接传入训练集展平后的标签,生成每个像素的权重
sample_weights_flat = compute_sample_weight('balanced', y_train_flat)
# 将权重恢复为与训练掩码一致的形状,再扩展维度匹配one-hot编码后的标签
sample_weights = sample_weights_flat.reshape(y_train.shape[0], y_train.shape[1], y_train.shape[2])
sample_weights = np.expand_dims(sample_weights, axis=-1)

2. 调整模型编译参数

修改sample_weight_mode为适合分割任务的逐像素模式:

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'], sample_weight_mode='elementwise')

3. 完整修正后的关键代码片段

# 创建测试子集,取10%数据测试,剩余用于训练
X_train, X_test, y_train, y_test = train_test_split(train_images, train_masks_input, test_size=0.10, random_state=0)
print('数据集中的类别值: ', np.unique(y_train))                     # 0为背景

train_masks_cat = to_categorical(y_train, num_classes=n_classes)
y_train_cat = train_masks_cat.reshape((y_train.shape[0], y_train.shape[1], y_train.shape[2], n_classes))

test_masks_cat = to_categorical(y_test, num_classes=n_classes)
y_test_cat = test_masks_cat.reshape((y_test.shape[0], y_test.shape[1], y_test.shape[2], n_classes))

# 修正后的样本权重计算
y_train_flat = y_train.reshape(-1)
sample_weights_flat = compute_sample_weight('balanced', y_train_flat)
sample_weights = sample_weights_flat.reshape(y_train.shape[0], y_train.shape[1], y_train.shape[2])
sample_weights = np.expand_dims(sample_weights, axis=-1)
print('权重数组形状:', sample_weights.shape)

IMG_HEIGHT = X_train.shape[1]
IMG_WIDTH = X_train.shape[2]
IMG_CHANNELS = X_train.shape[3]

def get_model():
    return multiclass_unet_model(n_classes=n_classes, IMG_HEIGHT=IMG_HEIGHT, IMG_WIDTH=IMG_WIDTH,
                                 IMG_CHANNELS=IMG_CHANNELS)

model = get_model()
# 修正sample_weight_mode参数
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'], sample_weight_mode='elementwise')
model.summary()

history = model.fit(X_train, y_train_cat,
                    batch_size=16,
                    verbose=1,
                    epochs=10,
                    validation_data=(X_test, y_test_cat),
                    sample_weight=sample_weights,
                    shuffle=False)
model.save('CNN.hdf5')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:57:36