Transformers documentation
Reconocimiento automático del habla
Reconocimiento automático del habla
El reconocimiento automático del habla (ASR) convierte una señal de voz en texto, mapeando una secuencia de entradas de audio a salidas de texto. Asistentes virtuales como Siri y Alexa utilizan modelos de ASR para ayudar a los usuarios a diario, y existen muchas otras aplicaciones útiles orientadas al usuario, como los subtítulos en vivo y la toma de notas durante reuniones.
Esta guía le mostrará cómo:
- Ajusta Wav2Vec2 sobre el conjunto de datos MInDS-14 para transcribir audio a texto.
- Usa tu modelo afinado para la inferencia.
Para ver todas las arquitecturas y puntos de control compatibles con esta tarea, recomendamos consultar la página de la tarea
Antes de comenzar, asegúrate de tener instaladas todas las bibliotecas necesarias:
pip install transformers datasets evaluate jiwer soundfile librosa torchcodec
Te animamos a iniciar sesión en tu cuenta de Hugging Face para que puedas subir y compartir tu modelo con la comunidad. Cuando se te solicite, introduce tu token para iniciar sesión:
>>> from huggingface_hub import notebook_login
>>> notebook_login()Cargar el conjunto de datos MInDS-14
Comience cargando un subconjunto más pequeño del conjunto de datos MInDS-14 desde la biblioteca 🤗 Datasets. Esto le dará la oportunidad de experimentar y asegurarse de que todo funcione correctamente antes de dedicar más tiempo a entrenar con el conjunto de datos completo.
>>> from datasets import load_dataset, Audio
>>> minds = load_dataset("PolyAI/minds14", name="en-US", split="train[:100]")Divide la partición train del conjunto de datos en un conjunto de entrenamiento y uno de prueba con el método ~Dataset.train_test_split:
>>> minds = minds.train_test_split(test_size=0.2)Luego, echa un vistazo al conjunto de datos:
>>> minds
DatasetDict({
train: Dataset({
features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
num_rows: 16
})
test: Dataset({
features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
num_rows: 4
})
})Aunque el conjunto de datos contiene mucha información útil, como lang_id y english_transcription, esta guía se centra en audio y transcription. Elimina las demás columnas con el método remove_columns:
>>> minds = minds.remove_columns(["english_transcription", "intent_class", "lang_id"])Vuelva a revisar el ejemplo:
>>> minds["train"][0]
{'audio': {'array': array([-0.00024414, 0. , 0. , ..., 0.00024414,
0.00024414, 0.00024414], dtype=float32),
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'sampling_rate': 8000},
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'transcription': "hi I'm trying to use the banking app on my phone and currently my checking and savings account balance is not refreshing"}Hay dos campos:
audio: unarrayunidimensional de la señal de voz que debe ser llamado para cargar y re-muestrear el archivo de audio.transcription: el texto objetivo.
Preprocesar
El siguiente paso es cargar un procesador de Wav2Vec2 para procesar la señal de audio:
>>> from transformers import AutoProcessor
>>> processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base")El conjunto de datos MInDS-14 tiene una frecuencia de muestreo de 8000Hz (puede encontrar esta información en su ficha del conjunto de datos), lo que significa que deberá remuestrear el conjunto de datos a 16000Hz para utilizar el modelo Wav2Vec2 preentrenado:
>>> minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
>>> minds["train"][0]
{'audio': {'array': array([-2.38064706e-04, -1.58618059e-04, -5.43987835e-06, ...,
2.78103951e-04, 2.38446111e-04, 1.18740834e-04], dtype=float32),
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'sampling_rate': 16000},
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'transcription': "hi I'm trying to use the banking app on my phone and currently my checking and savings account balance is not refreshing"}Como puede verse en la transcription anterior, el texto contiene una mezcla de caracteres en mayúsculas y minúsculas. El tokenizador de Wav2Vec2 solo se ha entrenado con caracteres en mayúsculas, por lo que debe asegurarse de que el texto coincida con el vocabulario del tokenizador:
>>> def uppercase(example):
... return {"transcription": example["transcription"].upper()}
>>> minds = minds.map(uppercase)Ahora crea una función de preprocesamiento que:
- Llama a la columna
audiopara cargar y re-muestrear el archivo de audio. - Extrae
input_valuesdel archivo de audio y tokeniza la columnatranscriptioncon el procesador.
>>> def prepare_dataset(batch):
... audio = batch["audio"]
... batch = processor(audio["array"], sampling_rate=audio["sampling_rate"], text=batch["transcription"])
... batch["input_length"] = len(batch["input_values"][0])
... return batchPara aplicar la función de preprocesamiento a todo el conjunto de datos, utiliza la función map de 🤗 Datasets. Puedes acelerar map aumentando el número de procesos con el parámetro num_proc. Elimina las columnas que no necesites con el método remove_columns:
>>> encoded_minds = minds.map(prepare_dataset, remove_columns=minds.column_names["train"], num_proc=4)🤗 Transformers no incluye un data collator para ASR, por lo que deberá adaptar DataCollatorWithPadding para crear un batch de ejemplos. Además, rellenará dinámicamente su texto y etiquetas hasta la longitud del elemento más largo de su batch (en lugar de la del conjunto de datos completo) para que tengan una longitud uniforme. Si bien es posible rellenar su texto en la función tokenizer estableciendo padding=True, el relleno dinámico es más eficiente.
A diferencia de otros collators de datos, este collator de datos específico necesita aplicar un método de relleno diferente a input_values y labels:
>>> import torch
>>> from dataclasses import dataclass, field
>>> from typing import Any, Dict, List, Optional, Union
>>> @dataclass
... class DataCollatorCTCWithPadding:
... processor: AutoProcessor
... padding: Union[bool, str] = "longest"
... def __call__(self, features: list[dict[str, Union[list[int], torch.Tensor]]]) -> dict[str, torch.Tensor]:
... # split inputs and labels since they have to be of different lengths and need
... # different padding methods
... input_features = [{"input_values": feature["input_values"][0]} for feature in features]
... label_features = [{"input_ids": feature["labels"]} for feature in features]
... batch = self.processor.pad(input_features, padding=self.padding, return_tensors="pt")
... labels_batch = self.processor.pad(labels=label_features, padding=self.padding, return_tensors="pt")
... # replace padding with -100 to ignore loss correctly
... labels = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100)
... batch["labels"] = labels
... return batchAhora instancie su DataCollatorCTCWithPadding:
>>> data_collator = DataCollatorCTCWithPadding(processor=processor, padding="longest")Evaluar
Incluir una métrica durante el entrenamiento suele ser útil para evaluar el rendimiento de tu modelo. Puedes cargar rápidamente un método de evaluación con la biblioteca 🤗 Evaluate. Para esta tarea, carga la métrica de word error rate (WER) (consulta el quick tour de 🤗 Evaluate para obtener más información sobre cómo cargar y calcular métricas):
>>> import evaluate
>>> wer = evaluate.load("wer")Luego, crea una función que pase tus predicciones y etiquetas a compute para calcular el WER:
>>> import numpy as np
>>> def compute_metrics(pred):
... pred_logits = pred.predictions
... pred_ids = np.argmax(pred_logits, axis=-1)
... pred.label_ids[pred.label_ids == -100] = processor.tokenizer.pad_token_id
... pred_str = processor.batch_decode(pred_ids)
... label_str = processor.batch_decode(pred.label_ids, group_tokens=False)
... wer_score = wer.compute(predictions=pred_str, references=label_str)
... return {"wer": wer_score}Tu función compute_metrics ya está lista y volverás a ella cuando configures el entrenamiento.
Entrenar
Si no está familiarizado con el ajuste fino de un modelo con Trainer, ¡eche un vistazo al tutorial básico aquí!
¡Ahora está listo para comenzar a entrenar su modelo! Cargue Wav2Vec2 con AutoModelForCTC. Especifique la reducción a aplicar con el parámetro ctc_loss_reduction. A menudo es mejor usar el promedio en lugar de la suma predeterminada:
>>> from transformers import AutoModelForCTC, TrainingArguments, Trainer
>>> model = AutoModelForCTC.from_pretrained(
... "facebook/wav2vec2-base",
... ctc_loss_reduction="mean",
... pad_token_id=processor.tokenizer.pad_token_id,
... )En este punto, solo quedan tres pasos:
- Defina los hiperparámetros de entrenamiento en TrainingArguments. El único parámetro obligatorio es
output_dir, que especifica dónde se guardará su modelo. Subirá este modelo al Hub configurandopush_to_hub=True(debe iniciar sesión en Hugging Face para subir su modelo). Al final de cada época, Trainer evaluará el WER y guardará el punto de control de entrenamiento. - Pasa los argumentos de entrenamiento a Trainer junto con el modelo, el conjunto de datos, el tokenizador, el data collator y la función
compute_metrics. - Llama a train() para ajustar tu modelo.
>>> training_args = TrainingArguments(
... output_dir="my_awesome_asr_mind_model",
... per_device_train_batch_size=8,
... gradient_accumulation_steps=2,
... learning_rate=1e-5,
... warmup_steps=500,
... max_steps=2000,
... gradient_checkpointing=True,
... fp16=True,
... train_sampling_strategy="group_by_length",
... eval_strategy="steps",
... per_device_eval_batch_size=8,
... save_steps=1000,
... eval_steps=1000,
... logging_steps=25,
... load_best_model_at_end=True,
... metric_for_best_model="wer",
... greater_is_better=False,
... push_to_hub=True,
... report_to="trackio",
... )
>>> trainer = Trainer(
... model=model,
... args=training_args,
... train_dataset=encoded_minds["train"],
... eval_dataset=encoded_minds["test"],
... processing_class=processor,
... data_collator=data_collator,
... compute_metrics=compute_metrics,
... )
>>> trainer.train()Una vez completado el entrenamiento, comparte tu modelo en el Hub con el método push_to_hub() para que esté accesible a todos:
>>> trainer.push_to_hub()Para un ejemplo más detallado sobre cómo ajustar un modelo para el reconocimiento automático del habla, consulte esta publicación sobre ASR en inglés y esta publicación sobre ASR multilingüe.
Inferencia
Genial, ahora que has ajustado un modelo, ¡puedes usarlo para inferencia!
Cargue un archivo de audio en el que desee ejecutar inferencia. Recuerde re-muestrear la tasa de muestreo del archivo de audio para que coincida con la tasa de muestreo del modelo si es necesario.
>>> from datasets import load_dataset, Audio
>>> dataset = load_dataset("PolyAI/minds14", "en-US", split="train")
>>> dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
>>> sampling_rate = dataset.features["audio"].sampling_rate
>>> audio_file = dataset[0]["audio"]["path"]La forma más sencilla de probar tu modelo afinado para inferencia es usarlo en un pipeline(). Instancia un pipeline para el reconocimiento automático de voz con tu modelo y pásale tu archivo de audio:
>>> from transformers import pipeline
>>> transcriber = pipeline("automatic-speech-recognition", model="stevhliu/my_awesome_asr_minds_model")
>>> transcriber(audio_file)
{'text': 'I WOUD LIKE O SET UP JOINT ACOUNT WTH Y PARTNER'}La transcripción es aceptable, ¡pero podría ser mejor! Prueba a hacer un ajuste fino de tu modelo con más ejemplos para obtener resultados aún mejores.
También puedes replicar manualmente los resultados de pipeline si lo deseas:
Carga un procesador para preprocesar el archivo de audio y la transcripción y devuelve la input como tensores de PyTorch:
>>> from transformers import AutoProcessor
>>> processor = AutoProcessor.from_pretrained("stevhliu/my_awesome_asr_mind_model")
>>> inputs = processor(dataset[0]["audio"]["array"], sampling_rate=sampling_rate, return_tensors="pt")Pasa tus entradas al modelo y devuelve los logits:
>>> from transformers import AutoModelForCTC
>>> model = AutoModelForCTC.from_pretrained("stevhliu/my_awesome_asr_mind_model")
>>> with torch.no_grad():
... logits = model(**inputs).logitsObtén los input_ids predichos con la mayor probabilidad y usa el procesador para decodificar los input_ids predichos de vuelta a texto:
>>> import torch
>>> predicted_ids = torch.argmax(logits, dim=-1)
>>> transcription = processor.batch_decode(predicted_ids)
>>> transcription
['I WOUL LIKE O SET UP JOINT ACOUNT WTH Y PARTNER']