我使用transformers
TFBertForSequenceClassification.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_mask
和token_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_mask
和token_type_ids
(,并且sape是不同的。虽然未按预期定义批次大小(-1(,但最大长度为5,而不是128!它在两个月前就开始工作了,我可能会介绍一些导致这个问题的东西。
我尝试了几个版本的Tensorfow
(2.2.0
和2.3.0
(和变压器(2.8.0
、2.9.0
和3.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格式(没有来自权重的中间加载(。