Huggingface 微调 - 如何在预训练的基础上构建自定义模型

Posted

技术标签:

【中文标题】Huggingface 微调 - 如何在预训练的基础上构建自定义模型【英文标题】:Huggingface fine-tuning - how to build a custom model on top of pre-trained 【发布时间】:2021-09-14 21:14:19 【问题描述】:

问题

请帮助了解以下问题的原因,以及如何构建 Keras 模型,以便在来自拥抱脸的预训练模型之上进行微调。

目标

在来自 Huggingface 的 TFDistilBertForSequenceClassification 之上为 DistilBERT 微调创建自定义模型。

向模型输入形状

从标记器输出的形状来看,我假设它是 (2, None, 256),因为 [input_ids, attention_mask] 会进入模型。

分词器的输出。

from transformers import DistilBertTokenizerFast
tokenizer = DistilBertTokenizerFast.from_pretrained('distilbert-base-uncased')

max_sequence_length = 256
tokens = tokenizer(
    " ".join(["token"] * max_sequence_length), 
    truncation=True,
    padding=True,
    max_length=max_sequence_length,
    return_tensors="tf"
)
print(tokens)
---

  'input_ids':      <tf.Tensor: shape=(1, 256), dtype=int32, numpy=array([[  101, 19204, 19204, 19204, 19204, 19204, 19204, 19204, 19204, ...]], dtype=int32)>, 
  'attention_mask': <tf.Tensor: shape=(1, 256), dtype=int32, numpy=array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...]], dtype=int32)>

预训练模型

model = TFDistilBertForSequenceClassification.from_pretrained('distilbert-base-uncased')
for layer in model.layers:
    if layer.name == "distilbert":
        layer.trainable = False
model.summary()
---
Model: "tf_distil_bert_for_sequence_classification_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
distilbert (TFDistilBertMain multiple                  66362880  
_________________________________________________________________
pre_classifier (Dense)       multiple                  590592    
_________________________________________________________________
classifier (Dense)           multiple                  1538      
_________________________________________________________________
dropout_99 (Dropout)         multiple                  0         
=================================================================
Total params: 66,955,010
Trainable params: 592,130
Non-trainable params: 66,362,880

自定义模型

在使用 Sequential 的预训练模型之上添加了 Keras Dense 层。

seq = Sequential([
   model,
   Dense(
       name="output_softmax", 
       units=2, 
       activation="softmax"
   )
])
seq.compile(
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    optimizer=tf.keras.optimizers.Adam()
)

问题

The base Layer class 表示 build 方法创建权重。

build(self, input_shape):此方法可用于创建取决于输入形状的权重,使用 add_weight()。 call() 将通过调用 build() 自动构建层(如果尚未构建)。

运行该方法但得到错误。

seq.build(input_shape=(2, None, max_sequence_length))
---
...
ValueError: You cannot build your model by calling `build` if your layers do not support float-type inputs. Instead, in order to instantiate and build your model, `call` your model on real tensor data (of the correct type).

根据错误消息,将标记器输出提供给模型并得到另一个错误。

seq(tokens)
---
TypeError: Failed to convert 'TFSequenceClassifierOutput(loss=None, logits=TensorShape([1, 2]), hidden_states=None, attentions=None)' to a shape: ''logits''could not be converted to a dimension. A shape should either be single dimension (e.g. 10), or an iterable of dimensions (e.g. [1, 10, None]).

环境

python --version
---
Python 3.7.10

print(tf.__version__)
---
2.5.0

print(transformers.__version__)
---
4.8.2

【问题讨论】:

【参考方案1】:

在没有使用 Sequential 或 build 方法的情况下,您是否尝试过 Keras 功能 API?-(我已尝试并使用其他预训练模型)s.a:-(伪代码)

def custom():
   x=Input(shape=(256,))
   y=Input(shape=(256,))
   out=distilbertlayer([x,y])
   out=Dense(2,activation='softmax')(out)
   mod=tf.keras.models.Model([x,y],out)
   return mod

custommodel=custom()

在这里,在给定的信息中。我认为该错误是由于传递给自定义密集层的错误类型的输出所致。作为建议,您可以尝试将 distilbertlayer 的不同输出传递给自定义密集层,例如

out=distilbertlayer([x,y])
out=Dense(2,activation='softmax')(out[:,0])

不过,首先要了解 distilbertlayer 的输出格式。

【讨论】:

以上是关于Huggingface 微调 - 如何在预训练的基础上构建自定义模型的主要内容,如果未能解决你的问题,请参考以下文章

如何微调 HuggingFace BERT 模型以进行文本分类 [关闭]

使用 HuggingFace 微调 ALBERT 问答

微调 HuggingFace NLI 模型(RoBERTa/BART)时,损失为“nan”

使用 Huggingface TFTrainer 类微调模型时如何指定损失函数?

如何获得 Hugging Face 预训练模型的大小?

Huggingface Transformer - GPT2 从保存的检查点恢复训练