Buckets:

rtrm's picture
|
download
raw
4.74 kB

Ajuste de un modelo de lenguaje enmascarado[[fine-tuning-a-masked-language-model]]

{#if fw === 'pt'}

{:else}

{/if}

En muchas aplicaciones de PLN, basta con tomar un modelo preentrenado y ajustarlo para una tarea concreta. Pero si tus datos pertenecen a un dominio muy específico, como textos legales o artículos científicos, suele ser útil adaptar primero el modelo de lenguaje a ese dominio.

Este proceso se conoce como adaptación de dominio. En esta sección ajustaremos DistilBERT sobre el conjunto IMDb para crear un modelo de lenguaje enmascarado más cercano al dominio de las reseñas de películas.

Elegir un modelo base[[picking-a-pretrained-model-for-masked-language-modeling]]

Usaremos DistilBERT, que es más pequeño que BERT y, por tanto, más rápido de entrenar.

{#if fw === 'pt'}

from transformers import AutoModelForMaskedLM

model_checkpoint = "distilbert-base-uncased"
model = AutoModelForMaskedLM.from_pretrained(model_checkpoint)

{:else}

from transformers import TFAutoModelForMaskedLM

model_checkpoint = "distilbert-base-uncased"
model = TFAutoModelForMaskedLM.from_pretrained(model_checkpoint)

{/if}

El conjunto de datos IMDb[[the-dataset]]

from datasets import load_dataset

imdb_dataset = load_dataset("imdb")
imdb_dataset
DatasetDict({
    train: Dataset({
        features: ['text', 'label'],
        num_rows: 25000
    })
    test: Dataset({
        features: ['text', 'label'],
        num_rows: 25000
    })
    unsupervised: Dataset({
        features: ['text', 'label'],
        num_rows: 50000
    })
})

Nos interesan sobre todo los textos, ya que para modelado de lenguaje no necesitamos las etiquetas de sentimiento.

Preprocesamiento[[preprocessing-the-data]]

Primero tokenizamos sin truncar para no perder información y, si el tokenizador lo permite, guardamos también word_ids para poder aplicar whole word masking:

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)

def tokenize_function(examples):
    result = tokenizer(examples["text"])
    if tokenizer.is_fast:
        result["word_ids"] = [result.word_ids(i) for i in range(len(result["input_ids"]))]
    return result

tokenized_datasets = imdb_dataset.map(
    tokenize_function, batched=True, remove_columns=["text", "label"]
)

Luego concatenamos todos los ejemplos y los dividimos en fragmentos de tamaño fijo:

chunk_size = 128

def group_texts(examples):
    concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
    total_length = len(concatenated_examples["input_ids"])
    total_length = (total_length // chunk_size) * chunk_size
    result = {
        k: [t[i : i + chunk_size] for i in range(0, total_length, chunk_size)]
        for k, t in concatenated_examples.items()
    }
    return result

lm_datasets = tokenized_datasets.map(group_texts, batched=True)

Enmascarado dinámico[[data-collation]]

Para MLM usamos DataCollatorForLanguageModeling, que aplica máscaras de forma aleatoria durante el entrenamiento:

{#if fw === 'pt'}

from transformers import DataCollatorForLanguageModeling

data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm_probability=0.15)

{:else}

from transformers import DataCollatorForLanguageModeling

data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer, mlm_probability=0.15, return_tensors="tf"
)

{/if}

Entrenamiento[[fine-tuning-the-model]]

{#if fw === 'pt'}

En PyTorch podemos entrenar con Trainer, igual que en capítulos anteriores. La diferencia es que el modelo ahora predice los tokens enmascarados en lugar de una clase:

from transformers import Trainer, TrainingArguments

args = TrainingArguments(
    output_dir="distilbert-base-uncased-finetuned-imdb",
    evaluation_strategy="epoch",
    learning_rate=2e-5,
    weight_decay=0.01,
)

{:else}

En TensorFlow preparamos un tf.data.Dataset y entrenamos con model.fit(), apoyándonos en la pérdida interna del modelo:

tf_train_dataset = model.prepare_tf_dataset(
    lm_datasets["train"], collate_fn=data_collator, shuffle=True, batch_size=32
)

{/if}

¿Qué obtenemos?[[what-do-we-get]]

Tras el ajuste, el modelo sustituye [MASK] por palabras más apropiadas para reseñas de películas que para el inglés general de Wikipedia. Esa es precisamente la idea de la adaptación de dominio: acercar el modelo al vocabulario y a los patrones reales de tu corpus.

Si luego entrenas una tarea específica, por ejemplo clasificación de sentimiento, partirás de una base más adecuada al dominio.

Xet Storage Details

Size:
4.74 kB
·
Xet hash:
78d21f80866362599a2d53dcfca6aa32cb4a1842ccb9414c534073062fe83fd0

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.