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
相关产品推荐
相关产品推荐

