Keras Transformers实现NER时维度不匹配问题求助
核心问题分析
报错ValueError: Dimensions must be equal, but are 516 and 7本质是模型某层的输入维度与前一层输出/输入数据的维度不匹配。结合你添加了5类额外特征(pageIndex、X/Y坐标、宽高、ocrScore)的场景,大概率是额外特征的维度与Transformer输出的embedding维度未对齐,或者模型结构未适配多特征输入。
具体解决方向
1. 先明确输入数据的维度
先打印输入数据的形状,确认维度是否符合预期:
print("x_train shape:", x_train.shape) print("x_val shape:", x_val.shape)
正常情况下,添加额外特征后,输入应该满足:
- 如果是单输入拼接:
(样本数, 序列长度, Transformer_embedding_dim + 5)(比如BERT-base的话是768+5=773) - 如果是多输入:一个是token ids的
(样本数, 序列长度),另一个是额外特征的(样本数, 序列长度, 5)
如果你的x_train是(样本数, 7, ...)或者(样本数, 序列长度,7),那说明额外特征的维度计算错误,或者序列长度和Transformer的输入序列长度(比如516)不匹配。
2. 调整模型结构适配多特征输入
原模型只处理Transformer的token embedding,现在需要把额外特征和Transformer的输出拼接,或者作为独立输入传入模型。这里提供两种常见方案:
方案A:多输入模型(推荐,更清晰)
将token ids和额外特征作为两个独立输入,在Transformer输出后拼接特征:
from tensorflow.keras.layers import Input, Concatenate, Dense from transformers import TFAutoModel # 定义输入层 max_len = 516 # 你的Transformer输入序列长度 num_tags = 你的标签数量 input_ids = Input(shape=(max_len,), dtype='int32') extra_features = Input(shape=(max_len, 5), dtype='float32') # 5个额外特征 # 获取Transformer的token embedding transformer_model = TFAutoModel.from_pretrained("bert-base-chinese") transformer_embedding = transformer_model(input_ids)[0] # shape: (None, max_len, 768) # 拼接Transformer embedding和额外特征 concat_features = Concatenate(axis=-1)([transformer_embedding, extra_features]) # shape: (None, max_len, 773) # 后续分类层 x = Dense(128, activation='relu')(concat_features) output = Dense(num_tags, activation='softmax')(x) # 构建模型 model = Model(inputs=[input_ids, extra_features], outputs=output) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
训练时需要传入两个输入:
model.fit( [x_train_ids, x_train_extra], # x_train_ids是token ids数组,x_train_extra是额外特征数组 y_train, validation_data=([x_val_ids, x_val_extra], y_val), epochs=10 )
方案B:单输入拼接特征
如果已经将额外特征和Transformer的embedding提前拼接成一个数组(比如x_train是(样本数, max_len, 773)),则需要修改原模型的输入层和后续Dense层的适配:
input_layer = Input(shape=(max_len, 773)) # 768+5=773 x = Dense(128, activation='relu')(input_layer) output = Dense(num_tags, activation='softmax')(x) model = Model(inputs=input_layer, outputs=output)
3. 检查序列长度一致性
确保额外特征的序列长度和Transformer的输入序列长度完全一致(比如都是516)。如果你的额外特征序列长度是7,而Transformer用的是516,就会出现维度不匹配——每个token必须对应一组额外特征,序列长度必须对齐。
4. 用model.summary()定位问题层
执行model.summary(),查看每一层的Input Shape和Output Shape,找到哪一层的输入维度和前一层输出维度不匹配。比如某层期望输入是(None, 516, 768),但实际传入的是(None, 516,7),那就是拼接步骤出错了。
内容的提问来源于stack exchange,提问作者MHogge

