Keras+Transformers 模型上的"saved_model_cli显示"显示用于训练的不同输入和形状



我使用transformersTFBertForSequenceClassification.from_pretrained(带有"bert base multilanguage uncased"(和keras来构建我的模型。

loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
# metric
metric = tf.keras.metrics.SparseCategoricalAccuracy('accuracy')
# optimizer
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate, epsilon=epsilon)
# create and compile the Keras model in the context of strategy.scope
model = TFBertForSequenceClassification.from_pretrained(pretrained_weights,
num_labels=num_labels,
cache_dir=pretrained_model_dir)
model._name = 'tf_bert_classification'
# compile Keras model
model.compile(optimizer=optimizer,
loss=loss,
metrics=[metric])

我正在使用SST2数据,这些数据是标记化的,并且是用于训练的模型的提要。数据具有以下形状:

shape: (32,)
dict structure
dim: 3
[input_ids       / attention_mask  / token_type_ids ]
[(32, 128)       / (32, 128)       / (32, 128)      ]
[ndarray         / ndarray         / ndarray        ]

这里有一个例子:

({'input_ids': <tf.Tensor: shape=(32, 128), dtype=int32, numpy=
array([[  101, 21270, 94696, ...,     0,     0,     0],
[  101,   143, 45100, ...,     0,     0,     0],
[  101, 24220,   102, ...,     0,     0,     0],
...,
[  101, 11008, 10346, ...,     0,     0,     0],
[  101, 43062, 15648, ...,     0,     0,     0],
[  101, 13178, 18418, ...,     0,     0,     0]], dtype=int32)>, 'attention_mask': ....

正如我们所看到的,我们有形状为(32128(的input_ids,其中32是批量大小,128是字符串的最大长度(BERT的最大值为512(。我们还有结构相同的attention_masktoken_type_ids

我能够训练模型并使用model.evaluate(test_dataset)进行预测。一切都很好。

我遇到的问题是,当我在GCP上提供模型时,它需要不同输入形状和结构的数据!如果我在保存的模型上运行cli,我也看到了同样的情况:

saved_model_cli show --dir $MODEL_LOCAL --tag_set serve --signature_def serving_default
The given SavedModel SignatureDef contains the following input(s):
inputs['input_ids'] tensor_info:
dtype: DT_INT32
shape: (-1, 5)
name: serving_default_input_ids:0
The given SavedModel SignatureDef contains the following output(s):
outputs['output_1'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 2)
name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict

正如我们所看到的,我们只需要给出input_ids而不需要(attention_masktoken_type_ids(,并且sape是不同的。虽然未按预期定义批次大小(-1(,但最大长度为5,而不是128!它在两个月前就开始工作了,我可能会介绍一些导致这个问题的东西。

我尝试了几个版本的Tensorfow(2.2.02.3.0(和变压器(2.8.02.9.03.0.2(。我看不到Kera的模型输入和输出形状(无(:

model.inputs

model.outputs

model.summary()
Model: "tf_bert_classification"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
bert (TFBertMainLayer)       multiple                  167356416 
_________________________________________________________________
dropout_37 (Dropout)         multiple                  0         
_________________________________________________________________
classifier (Dense)           multiple                  1538      
=================================================================
Total params: 167,357,954
Trainable params: 167,357,954
Non-trainable params: 0

有什么可以解释保存的模型需要与用于训练的输入不同的输入吗!我可以使用Keras函数API并定义输入形状,但我很确定这段代码以前是有效的。

当模型从预先训练的模型实例化,然后加载权重,然后以完全保证的keras格式保存时,我看到了这样的行为。当我后来加载后者时,它无法发布正确的预测,因为它的签名变成了垃圾:attention\ymask消失了,seq_length变了,dummy None输入突然出现。因此,如果是这样的话,可能会尝试在拟合后立即将模型保存为keras格式(没有来自权重的中间加载(。

最新更新