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

Siamese网络训练随机报错:[16,48]与[0]形状不兼容排查

问题描述

我实现了如下Siamese网络代码片段:

def build_sequential_model(input_shape, embedding_dim=16):
    model = Sequential()
    model.add(Input(shape=(input_shape,)))
    model.add(Dense(embedding_dim, activation='tanh'))    
    return model


sample_a = Input(shape=ftrSize)
sample_b = Input(shape=ftrSize)

feature_extractor = build_sequential_model(ftrSize, embedding_dim=embDim)

feats_a = feature_extractor(sample_a)
feats_b = feature_extractor(sample_b)
# feature_extractor.summary()
distance = Lambda(utils.euclidean_distance)([feats_a, feats_b])
outputs = Dense(1, activation="sigmoid")(distance)
model = Model(inputs=[sample_a, sample_b], outputs=outputs)
model.compile(loss=utils.contrastive_loss, optimizer=Adam(learning_rate=0.0007),
              metrics=["accuracy"])  # optimizer="adam", optimizer=Adam(lr=0.001)

checkpoint_path = 'siamese/1D/db' + str(dBthresh) + '_' + 'emb' + str(embDim) + '_' + excludeName + '.ckpt'

checkpoint = ModelCheckpoint(checkpoint_path, monitor='val_loss', save_best_only=True, mode='min',
                             save_weights_only=True,
                             verbose=1,
                             )
callback_list = [checkpoint]#, early_stop, reduce_lr]

history = model.fit(
    [pairs_train[:, 0], pairs_train[:, 1]], labels_train[:],
    validation_data=([pairs_val[:, 0], pairs_val[:, 1]], labels_val[:]),
    batch_size=16,
    epochs=20,
    callbacks=callback_list,
    # verbose=0,
    )

其中ftrSize = 56,embDim = 48。我在循环中用不同数据集测试该架构10次,会随机出现如下错误:

Incompatible shapes: [16,48] vs. [0]
     [[{{node model/lambda/sub}}]] [Op:__inference_test_function_182379]

错误指向作为Lambda层使用的euclidean_distance函数中的sum_squared行:

def euclidean_distance(vectors):
    feats_a, feats_b = vectors
    sum_squared = K.sum(K.square(feats_a - feats_b), axis=1,
                        keepdims=True)
    return K.sqrt(K.maximum(sum_squared, K.epsilon()))

[16,48]是合理的形状([batch size, embDim]),但第二个向量形状为[0]。排查报错时的训练/验证对数据集,未发现错误或缺失值(数据为numpy数组)。请问形状[0]可能代表什么?还有哪些原因会导致该错误?类似问题通常源于重塑或输入形状不一致,但本案例不存在该情况。

使用环境:Python 3.11.4、tensorflow-macos==2.14.0、numpy==1.25.2


问题分析与解决思路

形状[0]的含义

形状[0]表示该张量是空的一维张量,即不包含任何元素的数组,对应numpy中np.array([], dtype=np.float32)这类空数组的TensorFlow张量形状。

可能的错误原因

  • 数据集生成的随机异常:循环测试中,某次数据集生成时可能出现边缘情况——比如随机采样得到空特征数组,或numpy数组维度被错误压缩,导致某组样本对的其中一个样本为空张量。即使排查了报错时的数据集,也可能遗漏生成过程中的瞬时异常。
  • TensorFlow上下文残留问题:在循环创建模型时,前一次模型的张量上下文未完全清理,导致当前模型的输入张量形状被错误继承,触发空形状异常。macOS版本的TensorFlow 2.14可能存在这类动态图执行的小概率bug。
  • ModelCheckpoint回调冲突:若循环中checkpoint_path生成逻辑存在重复(比如excludeName为空或重复),save_weights_only=True的设置可能导致权重加载/保存时张量形状不匹配,进而引发计算错误。
  • Lambda层的轴计算异常:虽然代码指定了axis=1,但当输入张量形状动态变化时(比如某次batch实际有效样本数为0,尽管batch_size设为16,仍可能存在数据生成器的逻辑漏洞),K.sum计算可能返回空张量,触发形状不匹配。

验证与修复建议

  • 清理TensorFlow上下文:在每次循环创建模型前添加tf.keras.backend.clear_session(),彻底清除前一次模型的资源残留:
    for _ in range(10):
        tf.keras.backend.clear_session()
        # 后续创建模型、训练的代码
    
  • 添加数据形状断言:在生成训练/验证数据后,强制验证样本对的形状,提前拦截异常:
    assert pairs_train[:,0].shape == (len(pairs_train), ftrSize), "训练样本对A形状不匹配"
    assert pairs_train[:,1].shape == (len(pairs_train), ftrSize), "训练样本对B形状不匹配"
    assert pairs_val[:,0].shape == (len(pairs_val), ftrSize), "验证样本对A形状不匹配"
    assert pairs_val[:,1].shape == (len(pairs_val), ftrSize), "验证样本对B形状不匹配"
    
  • 调试Lambda层输入:在euclidean_distance函数中添加形状打印,定位异常发生时的实际张量情况:
    def euclidean_distance(vectors):
        feats_a, feats_b = vectors
        print("feats_a形状:", K.int_shape(feats_a))
        print("feats_b形状:", K.int_shape(feats_b))
        sum_squared = K.sum(K.square(feats_a - feats_b), axis=1, keepdims=True)
        return K.sqrt(K.maximum(sum_squared, K.epsilon()))
    
  • 检查样本数与batch_size适配:确保训练/验证集样本数不为0,若使用自定义数据生成器,需确认drop_remainder参数的设置是否合理,避免出现空batch。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:24:50