Transformers 4.37 中文文档(二)(3)https://developer.aliyun.com/article/1563284
评估
在训练过程中包含一个度量通常有助于评估模型的性能。您可以使用 🤗 Evaluate 库快速加载一个评估方法。对于这个任务,加载 accuracy 度量(查看 🤗 Evaluate 快速导览 以了解如何加载和计算度量):
>>> import evaluate >>> accuracy = evaluate.load("accuracy")
然后创建一个函数,将您的预测和标签传递给 compute
来计算准确率:
>>> import numpy as np >>> def compute_metrics(eval_pred): ... predictions, labels = eval_pred ... predictions = np.argmax(predictions, axis=1) ... return accuracy.compute(predictions=predictions, references=labels)
您的 compute_metrics
函数现在已经准备就绪,当您设置训练时会返回到它。
训练
在开始训练模型之前,使用 id2label
和 label2id
创建预期 id 到标签的映射:
>>> id2label = {0: "NEGATIVE", 1: "POSITIVE"} >>> label2id = {"NEGATIVE": 0, "POSITIVE": 1}
Pytorch 隐藏 Pytorch 内容
如果您不熟悉如何使用 Trainer 对模型进行微调,请查看这里的基本教程!
现在您已经准备好开始训练您的模型了!加载 DistilBERT 与 AutoModelForSequenceClassification 以及预期标签的数量和标签映射:
>>> from transformers import AutoModelForSequenceClassification, TrainingArguments, Trainer >>> model = AutoModelForSequenceClassification.from_pretrained( ... "distilbert-base-uncased", num_labels=2, id2label=id2label, label2id=label2id ... )
此时,只剩下三个步骤:
- 在 TrainingArguments 中定义您的训练超参数。唯一必需的参数是
output_dir
,指定保存模型的位置。通过设置push_to_hub=True
将此模型推送到 Hub(您需要登录 Hugging Face 以上传您的模型)。在每个 epoch 结束时,Trainer 将评估准确率并保存训练检查点。 - 将训练参数传递给 Trainer,以及模型、数据集、标记器、数据整理器和
compute_metrics
函数。 - 调用 train() 来微调您的模型。
>>> training_args = TrainingArguments( ... output_dir="my_awesome_model", ... learning_rate=2e-5, ... per_device_train_batch_size=16, ... per_device_eval_batch_size=16, ... num_train_epochs=2, ... weight_decay=0.01, ... evaluation_strategy="epoch", ... save_strategy="epoch", ... load_best_model_at_end=True, ... push_to_hub=True, ... ) >>> trainer = Trainer( ... model=model, ... args=training_args, ... train_dataset=tokenized_imdb["train"], ... eval_dataset=tokenized_imdb["test"], ... tokenizer=tokenizer, ... data_collator=data_collator, ... compute_metrics=compute_metrics, ... ) >>> trainer.train()
当您将 tokenizer
传递给 Trainer 时,默认情况下会应用动态填充。在这种情况下,您不需要显式指定数据整理器。
训练完成后,使用 push_to_hub() 方法将您的模型分享到 Hub,这样每个人都可以使用您的模型:
>>> trainer.push_to_hub()
TensorFlow 隐藏 TensorFlow 内容
如果您不熟悉如何使用 Keras 对模型进行微调,请查看这里的基本教程!
要在 TensorFlow 中微调模型,请首先设置优化器函数、学习率调度和一些训练超参数:
>>> from transformers import create_optimizer >>> import tensorflow as tf >>> batch_size = 16 >>> num_epochs = 5 >>> batches_per_epoch = len(tokenized_imdb["train"]) // batch_size >>> total_train_steps = int(batches_per_epoch * num_epochs) >>> optimizer, schedule = create_optimizer(init_lr=2e-5, num_warmup_steps=0, num_train_steps=total_train_steps)
然后,您可以加载 DistilBERT 与 TFAutoModelForSequenceClassification,以及预期标签的数量和标签映射:
>>> from transformers import TFAutoModelForSequenceClassification >>> model = TFAutoModelForSequenceClassification.from_pretrained( ... "distilbert-base-uncased", num_labels=2, id2label=id2label, label2id=label2id ... )
将您的数据集转换为tf.data.Dataset
格式,使用 prepare_tf_dataset():
>>> tf_train_set = model.prepare_tf_dataset( ... tokenized_imdb["train"], ... shuffle=True, ... batch_size=16, ... collate_fn=data_collator, ... ) >>> tf_validation_set = model.prepare_tf_dataset( ... tokenized_imdb["test"], ... shuffle=False, ... batch_size=16, ... collate_fn=data_collator, ... )
使用compile
为训练配置模型。请注意,Transformers 模型都有一个默认的与任务相关的损失函数,因此除非您想要,否则不需要指定一个:
>>> import tensorflow as tf >>> model.compile(optimizer=optimizer) # No loss argument!
在开始训练之前设置的最后两件事是从预测中计算准确率,并提供一种将模型推送到 Hub 的方法。这两个都可以通过使用 Keras callbacks 来完成。
将您的compute_metrics
函数传递给 KerasMetricCallback:
>>> from transformers.keras_callbacks import KerasMetricCallback >>> metric_callback = KerasMetricCallback(metric_fn=compute_metrics, eval_dataset=tf_validation_set)
指定在 PushToHubCallback 中推送模型和分词器的位置:
>>> from transformers.keras_callbacks import PushToHubCallback >>> push_to_hub_callback = PushToHubCallback( ... output_dir="my_awesome_model", ... tokenizer=tokenizer, ... )
然后将您的回调捆绑在一起:
>>> callbacks = [metric_callback, push_to_hub_callback] • 1
最后,您已经准备好开始训练您的模型了!使用您的训练和验证数据集、时代数和回调来微调模型调用fit
:
>>> model.fit(x=tf_train_set, validation_data=tf_validation_set, epochs=3, callbacks=callbacks)
训练完成后,您的模型会自动上传到 Hub,以便每个人都可以使用它!
有关如何为文本分类微调模型的更深入示例,请查看相应的PyTorch 笔记本或TensorFlow 笔记本。
推理
很好,现在您已经对模型进行了微调,可以用它进行推理!
获取一些您想要进行推理的文本:
>>> text = "This was a masterpiece. Not completely faithful to the books, but enthralling from beginning to end. Might be my favorite of the three."
尝试使用您微调的模型进行推理的最简单方法是在 pipeline()中使用它。用您的模型实例化一个情感分析的pipeline
,并将文本传递给它:
>>> from transformers import pipeline >>> classifier = pipeline("sentiment-analysis", model="stevhliu/my_awesome_model") >>> classifier(text) [{'label': 'POSITIVE', 'score': 0.9994940757751465}]
如果您愿意,也可以手动复制pipeline
的结果:
Pytorch 隐藏 Pytorch 内容
对文本进行标记化并返回 PyTorch 张量:
>>> from transformers import AutoTokenizer >>> tokenizer = AutoTokenizer.from_pretrained("stevhliu/my_awesome_model") >>> inputs = tokenizer(text, return_tensors="pt")
将您的输入传递给模型并返回logits
:
>>> from transformers import AutoModelForSequenceClassification >>> model = AutoModelForSequenceClassification.from_pretrained("stevhliu/my_awesome_model") >>> with torch.no_grad(): ... logits = model(**inputs).logits
获取具有最高概率的类,并使用模型的id2label
映射将其转换为文本标签:
>>> predicted_class_id = logits.argmax().item() >>> model.config.id2label[predicted_class_id] 'POSITIVE'
TensorFlow 隐藏 TensorFlow 内容
对文本进行标记化并返回 TensorFlow 张量:
>>> from transformers import AutoTokenizer >>> tokenizer = AutoTokenizer.from_pretrained("stevhliu/my_awesome_model") >>> inputs = tokenizer(text, return_tensors="tf")
将您的输入传递给模型并返回logits
:
>>> from transformers import TFAutoModelForSequenceClassification >>> model = TFAutoModelForSequenceClassification.from_pretrained("stevhliu/my_awesome_model") >>> logits = model(**inputs).logits
获取具有最高概率的类,并使用模型的id2label
映射将其转换为文本标签:
>>> predicted_class_id = int(tf.math.argmax(logits, axis=-1)[0]) >>> model.config.id2label[predicted_class_id] 'POSITIVE'
标记分类
原文链接:
huggingface.co/docs/transformers/v4.37.2/en/tasks/token_classification
www.youtube-nocookie.com/embed/wVHdVlPScxA
标记分类为句子中的每个单词分配一个标签。最常见的标记分类任务之一是命名实体识别(NER)。NER 试图为句子中的每个实体找到一个标签,比如人名、地点或组织。
本指南将向您展示如何:
- 在 WNUT 17 数据集上对DistilBERT进行微调,以检测新实体。
- 使用您微调的模型进行推断。
本教程中演示的任务由以下模型架构支持:
ALBERT, BERT, BigBird, BioGpt, BLOOM, BROS, CamemBERT, CANINE, ConvBERT, Data2VecText, DeBERTa, DeBERTa-v2, DistilBERT, ELECTRA, ERNIE, ErnieM, ESM, Falcon, FlauBERT, FNet, Funnel Transformer, GPT-Sw3, OpenAI GPT-2, GPTBigCode, GPT Neo, GPT NeoX, I-BERT, LayoutLM, LayoutLMv2, LayoutLMv3, LiLT, Longformer, LUKE, MarkupLM, MEGA, Megatron-BERT, MobileBERT, MPNet, MPT, MRA, Nezha, Nyströmformer, Phi, QDQBert, RemBERT, RoBERTa, RoBERTa-PreLayerNorm, RoCBert, RoFormer, SqueezeBERT, XLM, XLM-RoBERTa, XLM-RoBERTa-XL, XLNet, X-MOD, YOSO
在开始之前,请确保已安装所有必要的库:
pip install transformers datasets evaluate seqeval
我们鼓励您登录您的 Hugging Face 账户,这样您就可以上传和分享您的模型给社区。在提示时,输入您的令牌以登录:
>>> from huggingface_hub import notebook_login >>> notebook_login()
加载 WNUT 17 数据集
首先从🤗数据集库中加载 WNUT 17 数据集:
>>> from datasets import load_dataset >>> wnut = load_dataset("wnut_17")
然后看一个例子:
>>> wnut["train"][0] {'id': '0', 'ner_tags': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0], 'tokens': ['@paulwalk', 'It', "'s", 'the', 'view', 'from', 'where', 'I', "'m", 'living', 'for', 'two', 'weeks', '.', 'Empire', 'State', 'Building', '=', 'ESB', '.', 'Pretty', 'bad', 'storm', 'here', 'last', 'evening', '.'] }
ner_tags
中的每个数字代表一个实体。将数字转换为它们的标签名称,以找出这些实体是什么:
>>> label_list = wnut["train"].features[f"ner_tags"].feature.names >>> label_list [ "O", "B-corporation", "I-corporation", "B-creative-work", "I-creative-work", "B-group", "I-group", "B-location", "I-location", "B-person", "I-person", "B-product", "I-produ
每个ner_tag
前缀的字母表示实体的标记位置:
B-
表示一个实体的开始。I-
表示一个单词包含在同一个实体中(例如,State
单词是Empire State Building
这样一个实体的一部分)。0
表示该标记不对应任何实体。
预处理
www.youtube-nocookie.com/embed/iY2AZYdZAr0
下一步是加载一个 DistilBERT 分词器来预处理tokens
字段:
>>> from transformers import AutoTokenizer >>> tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
正如您在上面的示例 tokens
字段中看到的,看起来输入已经被标记化了。但实际上输入还没有被标记化,您需要设置 is_split_into_words=True
将单词标记化为子词。例如:
>>> example = wnut["train"][0] >>> tokenized_input = tokenizer(example["tokens"], is_split_into_words=True) >>> tokens = tokenizer.convert_ids_to_tokens(tokenized_input["input_ids"]) >>> tokens ['[CLS]', '@', 'paul', '##walk', 'it', "'", 's', 'the', 'view', 'from', 'where', 'i', "'", 'm', 'living', 'for', 'two', 'weeks', '.', 'empire', 'state', 'building', '=', 'es', '##b', '.', 'pretty', 'bad', 'storm', 'here', 'last', 'evening', '.', '[SEP]']
然而,这会添加一些特殊标记 [CLS]
和 [SEP]
,子词标记化会导致输入和标签之间的不匹配。现在,一个对应于单个标签的单词可能会被拆分为两个子词。您需要通过以下方式重新对齐标记和标签:
- 使用
word_ids
方法将所有标记映射到它们对应的单词。 - 将标签
-100
分配给特殊标记[CLS]
和[SEP]
,以便它们被 PyTorch 损失函数忽略(参见 CrossEntropyLoss)。 - 仅标记给定单词的第一个标记。将其他来自同一单词的子标记分配为
-100
。
以下是如何创建一个函数来重新对齐标记和标签,并截断序列,使其不超过 DistilBERT 的最大输入长度:
>>> def tokenize_and_align_labels(examples): ... tokenized_inputs = tokenizer(examples["tokens"], truncation=True, is_split_into_words=True) ... labels = [] ... for i, label in enumerate(examples[f"ner_tags"]): ... word_ids = tokenized_inputs.word_ids(batch_index=i) # Map tokens to their respective word. ... previous_word_idx = None ... label_ids = [] ... for word_idx in word_ids: # Set the special tokens to -100. ... if word_idx is None: ... label_ids.append(-100) ... elif word_idx != previous_word_idx: # Only label the first token of a given word. ... label_ids.append(label[word_idx]) ... else: ... label_ids.append(-100) ... previous_word_idx = word_idx ... labels.append(label_ids) ... tokenized_inputs["labels"] = labels ... return tokenized_inputs
要在整个数据集上应用预处理函数,请使用 🤗 Datasets map 函数。您可以通过设置 batched=True
来加速 map
函数,以一次处理数据集的多个元素:
>>> tokenized_wnut = wnut.map(tokenize_and_align_labels, batched=True)
现在使用 DataCollatorWithPadding 创建一批示例。在整理过程中,将句子动态填充到批次中的最大长度,而不是将整个数据集填充到最大长度。
PytorchHide Pytorch 内容
>>> from transformers import DataCollatorForTokenClassification >>> data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer)
TensorFlowHide TensorFlow 内容
>>> from transformers import DataCollatorForTokenClassification >>> data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer, return_tensors="tf")
Transformers 4.37 中文文档(二)(5)https://developer.aliyun.com/article/1563286