fine-tune语义相似分类模型实践

完整代码参见:https://github.com/tdaajames/aitest/blob/main/fine_tune.py

首先要准备一些fine tune用的训练样本,这个可以通过tensorflow dataset获得,也可以自己解析文本获得。

glue_train = bert_encode(glue['train'], tokenizer)
glue_train_labels = glue['train']['label']

然后,设定一系列的训练参数

epochs = 3

batch_size = 32



train_data_size = len(glue_train_labels)

steps_per_epoch = int(train_data_size / batch_size)

num_train_steps = steps_per_epoch * epochs

warmup_steps = int(epochs * train_data_size * 0.1 / batch_size)



# creates an optimizer with learning rate schedule

optimizer = nlp.optimization.create_optimizer(

    2e-5, num_train_steps=num_train_steps, num_warmup_steps=warmup_steps)



metrics = [tf.keras.metrics.SparseCategoricalAccuracy('accuracy', dtype=tf.float32)]

loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

loss函数SparseCategoricalCrossentropy

Computes the crossentropy loss between the labels and predictions

https://www.tensorflow.org/api_docs/python/tf/keras/losses/SparseCategoricalCrossentropy

metrics:度量函数,计算预测正确率

Calculates how often predictions match integer labels.

https://www.tensorflow.org/api_docs/python/tf/keras/metrics/SparseCategoricalAccuracy

最最关键的,创建模型

def build_classifier_model():

    class Classifier(tf.keras.Model):

        def __init__(self, encoder_inputs, net, encoder):

            super(Classifier, self).__init__(inputs=encoder_inputs, outputs=net, name="prediction")

            self.encoder = encoder



        def call(self, preprocessed_text, training=False):

            x = super(Classifier, self).call(preprocessed_text)

            return x

    input_word_ids = tf.keras.layers.Input(

        shape=(None,), dtype=tf.int32, name='input_word_ids')

    input_mask = tf.keras.layers.Input(

        shape=(None,), dtype=tf.int32, name='input_mask')

    input_type_ids = tf.keras.layers.Input(

        shape=(None,), dtype=tf.int32, name='input_type_ids')

    encoder_inputs = {

        'input_word_ids': input_word_ids,

        'input_mask': input_mask,

        'input_type_ids': input_type_ids

    }

    encoder = hub.KerasLayer(hub_url_bert, trainable=True)

    outputs = encoder(encoder_inputs)

    net = outputs['pooled_output']

    net = tf.keras.layers.Dropout(0.1)(net)

    net = tf.keras.layers.Dense(2, activation=None, name='classifier')(net)

    tf.keras.Model()

    return Classifier(encoder_inputs, net, encoder)



classifier_model = build_classifier_model()
 

这里我遇到了两个坑:

  1. 一开始使用完全的子类来定义模型,类似官方的定义了里面一系列行为,那么fit以后拿的模型,会自动对input shape进行一个自动长度设定,我遇到的是(None,79),这样相当于对输入向量限定了最大长度,模型用起来很不方便。

    ——

    于是,我想办法将input shape设定成(None,None),发现定义encoder_inputs可以实现,但是,直接使用tf.keras.Model这个类来定义模型,那么训练出来模型后,我又无法访问里面的encoder,于是,我就通过扩展子类增加encoder,完全使用父类方法的这个方案来实现我既定义了input shape,又拿到了我想要的encoder方法。当然,我也尝试过其它像子类定义self.inputs来设定input shape的方法,但是,没有效果。

  2. 另外,还有一个注意的子类的call方法要定义个training的入参,def call(self, preprocessed_text, training=False),否则会报错。

最后,开始训练并保存模型

classifier_model = build_classifier_model()

classifier_model.compile(
    optimizer=optimizer,
    loss=loss,
    metrics=metrics)

classifier_model.fit(
    glue_train, glue_train_labels,
    batch_size=32,
    epochs=epochs)

export_dir = './exported_model'
tf.saved_model.save(classifier_model, export_dir=export_dir)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值