Transformers documentation

Classificação de tokens

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v4.46.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Classificação de tokens

A classificação de tokens atribui um rótulo a tokens individuais em uma frase. Uma das tarefas de classificação de tokens mais comuns é o Reconhecimento de Entidade Nomeada, também chamada de NER (sigla em inglês para Named Entity Recognition). O NER tenta encontrar um rótulo para cada entidade em uma frase, como uma pessoa, local ou organização.

Este guia mostrará como realizar o fine-tuning do DistilBERT no conjunto de dados WNUT 17 para detectar novas entidades.

Consulte a página de tarefas de classificação de tokens para obter mais informações sobre outras formas de classificação de tokens e seus modelos, conjuntos de dados e métricas associadas.

Carregando o conjunto de dados WNUT 17

Carregue o conjunto de dados WNUT 17 da biblioteca 🤗 Datasets:

>>> from datasets import load_dataset

>>> wnut = load_dataset("wnut_17")

E dê uma olhada em um exemplo:

>>> 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', '.']
}

Cada número em ner_tags representa uma entidade. Converta o número em um rótulo para obter mais informações:

>>> 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-product",
]

O ner_tag descreve uma entidade, como uma organização, local ou pessoa. A letra que prefixa cada ner_tag indica a posição do token da entidade:

  • B- indica o início de uma entidade.
  • I- indica que um token está contido dentro da mesma entidade (por exemplo, o token State pode fazer parte de uma entidade como Empire State Building).
  • 0 indica que o token não corresponde a nenhuma entidade.

Pré-processamento

Carregue o tokenizer do DistilBERT para processar os tokens:

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")

Como a entrada já foi dividida em palavras, defina is_split_into_words=True para tokenizar as palavras em subpalavras:

>>> 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]']

Ao adicionar os tokens especiais [CLS] e [SEP] e a tokenização de subpalavras uma incompatibilidade é gerada entre a entrada e os rótulos. Uma única palavra correspondente a um único rótulo pode ser dividida em duas subpalavras. Você precisará realinhar os tokens e os rótulos da seguinte forma:

  1. Mapeie todos os tokens para a palavra correspondente com o método word_ids.
  2. Atribuindo o rótulo -100 aos tokens especiais [CLS] e [SEP] para que a função de loss do PyTorch ignore eles.
  3. Rotular apenas o primeiro token de uma determinada palavra. Atribuindo -100 a outros subtokens da mesma palavra.

Aqui está como você pode criar uma função para realinhar os tokens e rótulos e truncar sequências para não serem maiores que o comprimento máximo de entrada do 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

Use a função map do 🤗 Datasets para tokenizar e alinhar os rótulos em todo o conjunto de dados. Você pode acelerar a função map configurando batched=True para processar vários elementos do conjunto de dados de uma só vez:

>>> tokenized_wnut = wnut.map(tokenize_and_align_labels, batched=True)

Use o DataCollatorForTokenClassification para criar um batch de exemplos. Ele também preencherá dinamicamente seu texto e rótulos para o comprimento do elemento mais longo em seu batch, para que tenham um comprimento uniforme. Embora seja possível preencher seu texto na função tokenizer configurando padding=True, o preenchimento dinâmico é mais eficiente.

Pytorch
Hide Pytorch content
>>> from transformers import DataCollatorForTokenClassification

>>> data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer)
TensorFlow
Hide TensorFlow content
>>> from transformers import DataCollatorForTokenClassification

>>> data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer, return_tensors="tf")

Treinamento

Pytorch
Hide Pytorch content

Carregue o DistilBERT com o AutoModelForTokenClassification junto com o número de rótulos esperados:

>>> from transformers import AutoModelForTokenClassification, TrainingArguments, Trainer

>>> model = AutoModelForTokenClassification.from_pretrained("distilbert/distilbert-base-uncased", num_labels=14)

Se você não estiver familiarizado com o fine-tuning de um modelo com o Trainer, dê uma olhada no tutorial básico aqui!

Nesse ponto, restam apenas três passos:

  1. Definir seus hiperparâmetros de treinamento em TrainingArguments.
  2. Passar os argumentos de treinamento para o Trainer junto com o modelo, conjunto de dados, tokenizador e o data collator.
  3. Chamar a função train() para executar o fine-tuning do seu modelo.
>>> training_args = TrainingArguments(
...     output_dir="./results",
...     eval_strategy="epoch",
...     learning_rate=2e-5,
...     per_device_train_batch_size=16,
...     per_device_eval_batch_size=16,
...     num_train_epochs=3,
...     weight_decay=0.01,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     train_dataset=tokenized_wnut["train"],
...     eval_dataset=tokenized_wnut["test"],
...     processing_class=tokenizer,
...     data_collator=data_collator,
... )

>>> trainer.train()
TensorFlow
Hide TensorFlow content

Para executar o fine-tuning de um modelo no TensorFlow, comece convertendo seu conjunto de dados para o formato tf.data.Dataset com to_tf_dataset. Nessa execução você deverá especificar as entradas e rótulos (no parâmetro columns), se deseja embaralhar o conjunto de dados, o tamanho do batch e o data collator:

>>> tf_train_set = tokenized_wnut["train"].to_tf_dataset(
...     columns=["attention_mask", "input_ids", "labels"],
...     shuffle=True,
...     batch_size=16,
...     collate_fn=data_collator,
... )

>>> tf_validation_set = tokenized_wnut["validation"].to_tf_dataset(
...     columns=["attention_mask", "input_ids", "labels"],
...     shuffle=False,
...     batch_size=16,
...     collate_fn=data_collator,
... )

Se você não estiver familiarizado com o fine-tuning de um modelo com o Keras, dê uma olhada no tutorial básico aqui!

Configure o otimizador e alguns hiperparâmetros de treinamento:

>>> from transformers import create_optimizer

>>> batch_size = 16
>>> num_train_epochs = 3
>>> num_train_steps = (len(tokenized_wnut["train"]) // batch_size) * num_train_epochs
>>> optimizer, lr_schedule = create_optimizer(
...     init_lr=2e-5,
...     num_train_steps=num_train_steps,
...     weight_decay_rate=0.01,
...     num_warmup_steps=0,
... )

Carregue o DistilBERT com o TFAutoModelForTokenClassification junto com o número de rótulos esperados:

>>> from transformers import TFAutoModelForTokenClassification

>>> model = TFAutoModelForTokenClassification.from_pretrained("distilbert/distilbert-base-uncased", num_labels=2)

Configure o modelo para treinamento com o método compile:

>>> import tensorflow as tf

>>> model.compile(optimizer=optimizer)

Chame o método fit para executar o fine-tuning do modelo:

>>> model.fit(x=tf_train_set, validation_data=tf_validation_set, epochs=3)

Para obter um exemplo mais aprofundado de como executar o fine-tuning de um modelo para classificação de tokens, dê uma olhada nesse notebook utilizando PyTorch ou nesse notebook utilizando TensorFlow.

< > Update on GitHub