Spanish translation of asr.mdx and add_new_pipeline.mdx (#20569)
* Fix minor typo in question_answering.mdx * Fixes minor typo in the english version of tasks/asr.mdx * Update _toctree.yml * Translate add_new_pipeline.mdx into Spanish * Fixes some typos in the English version of add_new_pipeline.mdx * Translate asr.mdx into Spanish * Fixes small typos in add_new_pipeline.mdx * Update docs/source/es/add_new_pipeline.mdx Suggestion by @osanseviero Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/add_new_pipeline.mdx Suggestion by @osanseviero: use "biblioteca" instead of "librería." Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/tasks/asr.mdx Suggestion by @osanseviero. Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/add_new_pipeline.mdx Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/add_new_pipeline.mdx Suggestion by @osanseviero. Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/add_new_pipeline.mdx Suggestion by @osanseviero. Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/add_new_pipeline.mdx Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/tasks/asr.mdx Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/tasks/asr.mdx Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update docs/source/es/tasks/asr.mdx Co-authored-by: Omar Sanseviero <osanseviero@gmail.com> * Update asr.mdx Co-authored-by: Omar Sanseviero <osanseviero@gmail.com>
This commit is contained in:
committed by
GitHub
parent
8d2fca07e8
commit
8286af6f54
@@ -12,7 +12,7 @@ an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express o
|
|||||||
# How to create a custom pipeline?
|
# How to create a custom pipeline?
|
||||||
|
|
||||||
In this guide, we will see how to create a custom pipeline and share it on the [Hub](hf.co/models) or add it to the
|
In this guide, we will see how to create a custom pipeline and share it on the [Hub](hf.co/models) or add it to the
|
||||||
Transformers library.
|
🤗 Transformers library.
|
||||||
|
|
||||||
First and foremost, you need to decide the raw entries the pipeline will be able to take. It can be strings, raw bytes,
|
First and foremost, you need to decide the raw entries the pipeline will be able to take. It can be strings, raw bytes,
|
||||||
dictionaries or whatever seems to be the most likely desired input. Try to keep these inputs as pure Python as possible
|
dictionaries or whatever seems to be the most likely desired input. Try to keep these inputs as pure Python as possible
|
||||||
@@ -22,8 +22,8 @@ pipeline (`preprocess`).
|
|||||||
Then define the `outputs`. Same policy as the `inputs`. The simpler, the better. Those will be the outputs of
|
Then define the `outputs`. Same policy as the `inputs`. The simpler, the better. Those will be the outputs of
|
||||||
`postprocess` method.
|
`postprocess` method.
|
||||||
|
|
||||||
Start by inheriting the base class `Pipeline`. with the 4 methods needed to implement `preprocess`,
|
Start by inheriting the base class `Pipeline` with the 4 methods needed to implement `preprocess`,
|
||||||
`_forward`, `postprocess` and `_sanitize_parameters`.
|
`_forward`, `postprocess`, and `_sanitize_parameters`.
|
||||||
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -62,14 +62,14 @@ contain more information and is usually a `Dict`.
|
|||||||
called method as it contains safeguards to make sure everything is working on the expected device. If anything is
|
called method as it contains safeguards to make sure everything is working on the expected device. If anything is
|
||||||
linked to a real model it belongs in the `_forward` method, anything else is in the preprocess/postprocess.
|
linked to a real model it belongs in the `_forward` method, anything else is in the preprocess/postprocess.
|
||||||
|
|
||||||
`postprocess` methods will take the output of `_forward` and turn it into the final output that were decided
|
`postprocess` methods will take the output of `_forward` and turn it into the final output that was decided
|
||||||
earlier.
|
earlier.
|
||||||
|
|
||||||
`_sanitize_parameters` exists to allow users to pass any parameters whenever they wish, be it at initialization
|
`_sanitize_parameters` exists to allow users to pass any parameters whenever they wish, be it at initialization
|
||||||
time `pipeline(...., maybe_arg=4)` or at call time `pipe = pipeline(...); output = pipe(...., maybe_arg=4)`.
|
time `pipeline(...., maybe_arg=4)` or at call time `pipe = pipeline(...); output = pipe(...., maybe_arg=4)`.
|
||||||
|
|
||||||
The returns of `_sanitize_parameters` are the 3 dicts of kwargs that will be passed directly to `preprocess`,
|
The returns of `_sanitize_parameters` are the 3 dicts of kwargs that will be passed directly to `preprocess`,
|
||||||
`_forward` and `postprocess`. Don't fill anything if the caller didn't call with any extra parameter. That
|
`_forward`, and `postprocess`. Don't fill anything if the caller didn't call with any extra parameter. That
|
||||||
allows to keep the default arguments in the function definition which is always more "natural".
|
allows to keep the default arguments in the function definition which is always more "natural".
|
||||||
|
|
||||||
A classic example would be a `top_k` argument in the post processing in classification tasks.
|
A classic example would be a `top_k` argument in the post processing in classification tasks.
|
||||||
@@ -126,7 +126,7 @@ PIPELINE_REGISTRY.register_pipeline(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
You can specify a default model if you want, in which case it should come with a specific revision (which can be the name of a branch or a commit hash, here we took `"abcdef"`) as well was the type:
|
You can specify a default model if you want, in which case it should come with a specific revision (which can be the name of a branch or a commit hash, here we took `"abcdef"`) as well as the type:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
PIPELINE_REGISTRY.register_pipeline(
|
PIPELINE_REGISTRY.register_pipeline(
|
||||||
@@ -225,9 +225,9 @@ from transformers import pipeline
|
|||||||
classifier = pipeline(model="{your_username}/test-dynamic-pipeline", trust_remote_code=True)
|
classifier = pipeline(model="{your_username}/test-dynamic-pipeline", trust_remote_code=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Add the pipeline to Transformers
|
## Add the pipeline to 🤗 Transformers
|
||||||
|
|
||||||
If you want to contribute your pipeline to Transformers, you will need to add a new module in the `pipelines` submodule
|
If you want to contribute your pipeline to 🤗 Transformers, you will need to add a new module in the `pipelines` submodule
|
||||||
with the code of your pipeline, then add it in the list of tasks defined in `pipelines/__init__.py`.
|
with the code of your pipeline, then add it in the list of tasks defined in `pipelines/__init__.py`.
|
||||||
|
|
||||||
Then you will need to add tests. Create a new file `tests/test_pipelines_MY_PIPELINE.py` with example with the other tests.
|
Then you will need to add tests. Create a new file `tests/test_pipelines_MY_PIPELINE.py` with example with the other tests.
|
||||||
@@ -237,7 +237,7 @@ architecture as defined by `model_mapping` and `tf_model_mapping`.
|
|||||||
|
|
||||||
This is very important to test future compatibility, meaning if someone adds a new model for
|
This is very important to test future compatibility, meaning if someone adds a new model for
|
||||||
`XXXForQuestionAnswering` then the pipeline test will attempt to run on it. Because the models are random it's
|
`XXXForQuestionAnswering` then the pipeline test will attempt to run on it. Because the models are random it's
|
||||||
impossible to check for actual values, that's why There is a helper `ANY` that will simply attempt to match the
|
impossible to check for actual values, that's why there is a helper `ANY` that will simply attempt to match the
|
||||||
output of the pipeline TYPE.
|
output of the pipeline TYPE.
|
||||||
|
|
||||||
You also *need* to implement 2 (ideally 4) tests.
|
You also *need* to implement 2 (ideally 4) tests.
|
||||||
@@ -248,7 +248,7 @@ You also *need* to implement 2 (ideally 4) tests.
|
|||||||
and test the pipeline outputs. The results should be the same as `test_small_model_pt`.
|
and test the pipeline outputs. The results should be the same as `test_small_model_pt`.
|
||||||
- `test_large_model_pt` (`optional`): Tests the pipeline on a real pipeline where the results are supposed to
|
- `test_large_model_pt` (`optional`): Tests the pipeline on a real pipeline where the results are supposed to
|
||||||
make sense. These tests are slow and should be marked as such. Here the goal is to showcase the pipeline and to make
|
make sense. These tests are slow and should be marked as such. Here the goal is to showcase the pipeline and to make
|
||||||
sure there is no drift in future releases
|
sure there is no drift in future releases.
|
||||||
- `test_large_model_tf` (`optional`): Tests the pipeline on a real pipeline where the results are supposed to
|
- `test_large_model_tf` (`optional`): Tests the pipeline on a real pipeline where the results are supposed to
|
||||||
make sense. These tests are slow and should be marked as such. Here the goal is to showcase the pipeline and to make
|
make sense. These tests are slow and should be marked as such. Here the goal is to showcase the pipeline and to make
|
||||||
sure there is no drift in future releases
|
sure there is no drift in future releases.
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ Take a look at the example again:
|
|||||||
|
|
||||||
There are two fields:
|
There are two fields:
|
||||||
|
|
||||||
- `audio`: a 1-dimensional `array` of the speech signal that must be called to load and resample the audio file.
|
- `audio`: a 1-dimensional `array` of the speech signal that must be called to load and resample the audio file.
|
||||||
- `transcription`: the target text.
|
- `transcription`: the target text.
|
||||||
|
|
||||||
## Preprocess
|
## Preprocess
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ The next step is to load a Wav2Vec2 processor to process the audio signal:
|
|||||||
>>> processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base")
|
>>> processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base")
|
||||||
```
|
```
|
||||||
|
|
||||||
The MInDS-14 dataset has a sampling rate of 8000khz (you can find this information in its [dataset card](https://huggingface.co/datasets/PolyAI/minds14)), which means you'll need to resample the dataset to 16000kHz to use the pretrained Wav2Vec2 model:
|
The MInDS-14 dataset has a sampling rate of 8000kHz (you can find this information in its [dataset card](https://huggingface.co/datasets/PolyAI/minds14)), which means you'll need to resample the dataset to 16000kHz to use the pretrained Wav2Vec2 model:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
>>> minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
|
>>> minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
|
||||||
|
|||||||
@@ -51,11 +51,17 @@
|
|||||||
title: Selección múltiple
|
title: Selección múltiple
|
||||||
title: Guías de tareas
|
title: Guías de tareas
|
||||||
title: Procesamiento del Lenguaje Natural
|
title: Procesamiento del Lenguaje Natural
|
||||||
|
- sections:
|
||||||
|
- local: tasks/asr
|
||||||
|
title: Reconocimiento automático del habla
|
||||||
|
title: Audio
|
||||||
- sections:
|
- sections:
|
||||||
- local: tasks/image_classification
|
- local: tasks/image_classification
|
||||||
title: Clasificación de imágenes
|
title: Clasificación de imágenes
|
||||||
title: Visión Artificial
|
title: Visión Artificial
|
||||||
- sections:
|
- sections:
|
||||||
|
- local: add_new_pipeline
|
||||||
|
title: ¿Cómo puedo añadir un pipeline a 🤗 Transformers?
|
||||||
- local: pr_checks
|
- local: pr_checks
|
||||||
title: Verificaciones en un Pull Request
|
title: Verificaciones en un Pull Request
|
||||||
title: Contribuir
|
title: Contribuir
|
||||||
|
|||||||
260
docs/source/es/add_new_pipeline.mdx
Normal file
260
docs/source/es/add_new_pipeline.mdx
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
<!--Copyright 2020 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
-->
|
||||||
|
|
||||||
|
# ¿Cómo puedo crear un pipeline personalizado?
|
||||||
|
|
||||||
|
En esta guía, veremos cómo crear un pipeline personalizado y cómo compartirlo en el [Hub](hf.co/models) o añadirlo
|
||||||
|
a la biblioteca 🤗 Transformers.
|
||||||
|
|
||||||
|
En primer lugar, debes decidir las entradas que tu pipeline podrá recibir. Pueden ser strings, bytes,
|
||||||
|
diccionarios o lo que te parezca que vaya a ser la entrada más apropiada. Intenta mantener estas entradas en un
|
||||||
|
formato que sea tan Python puro como sea posible, puesto que esto facilita la compatibilidad (incluso con otros
|
||||||
|
lenguajes de programación por medio de JSON). Estos serán los `inputs` (entradas) del pipeline (`preprocess`).
|
||||||
|
|
||||||
|
Ahora debes definir los `outputs` (salidas). Al igual que con los `inputs`, entre más simple el formato, mejor.
|
||||||
|
Estas serán las salidas del método `postprocess` (posprocesamiento).
|
||||||
|
|
||||||
|
Empieza heredando la clase base `Pipeline` con los 4 métodos que debemos implementar: `preprocess` (preprocesamiento),
|
||||||
|
`_forward` (ejecución), `postprocess` (posprocesamiento) y `_sanitize_parameters` (verificar parámetros).
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import Pipeline
|
||||||
|
|
||||||
|
|
||||||
|
class MyPipeline(Pipeline):
|
||||||
|
def _sanitize_parameters(self, **kwargs):
|
||||||
|
preprocess_kwargs = {}
|
||||||
|
if "maybe_arg" in kwargs:
|
||||||
|
preprocess_kwargs["maybe_arg"] = kwargs["maybe_arg"]
|
||||||
|
return preprocess_kwargs, {}, {}
|
||||||
|
|
||||||
|
def preprocess(self, inputs, maybe_arg=2):
|
||||||
|
model_input = Tensor(inputs["input_ids"])
|
||||||
|
return {"model_input": model_input}
|
||||||
|
|
||||||
|
def _forward(self, model_inputs):
|
||||||
|
# model_inputs == {"model_input": model_input}
|
||||||
|
outputs = self.model(**model_inputs)
|
||||||
|
# Quizá {"logits": Tensor(...)}
|
||||||
|
return outputs
|
||||||
|
|
||||||
|
def postprocess(self, model_outputs):
|
||||||
|
best_class = model_outputs["logits"].softmax(-1)
|
||||||
|
return best_class
|
||||||
|
```
|
||||||
|
|
||||||
|
La estructura de este desglose es así para garantizar una compatibilidad más o menos transparente con el uso de
|
||||||
|
CPU/GPU y el pre/posprocesamiento en CPU en varios hilos.
|
||||||
|
|
||||||
|
`preprocess` tomará las entradas definidas originalmente y las convertirá en algo que se le pueda pasar al modelo.
|
||||||
|
Podría contener más información y a menudo es un objeto `Dict` (diccionario).
|
||||||
|
|
||||||
|
`_forward` contiene los detalles de la implementación y no debería ser invocado de forma directa. `forward` es el
|
||||||
|
método preferido a utilizar pues contiene verificaciones para asegurar que todo funcione en el dispositivo correcto.
|
||||||
|
Cualquier cosa que esté relacionada con un modelo real debería ir en el método `_forward`, todo lo demás va en
|
||||||
|
los métodos de preprocesamiento y posprocesamiento.
|
||||||
|
|
||||||
|
Los métodos `postprocess` reciben la salida `_forward` y la convierten en la salida final que decidimos
|
||||||
|
anteriormente.
|
||||||
|
|
||||||
|
`_sanitize_parameters` existe para permitir a los usuarios pasar cualesquiera parámetros cuando lo deseen, ya
|
||||||
|
sea al momento de inicializar el pipeline `pipeline(...., maybe_arg=4)` o al momento de invocarlo
|
||||||
|
`pipe = pipeline(...); output = pipe(...., maybe_arg=4)`.
|
||||||
|
|
||||||
|
|
||||||
|
El método `_sanitize_parameters` devuelve 3 diccionarios de kwargs que serán pasados directamente a `preprocess`,
|
||||||
|
`_forward` y `postprocess`. No ingreses nada si el caller no se va a invocar con parámetros adicionales.
|
||||||
|
Esto permite mantener los parámetros por defecto de la definición de la función, lo que es más "natural".
|
||||||
|
|
||||||
|
Un ejemplo clásico sería un argumento `top_k` en el posprocesamiento de una tarea de clasificación.
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> pipe = pipeline("my-new-task")
|
||||||
|
>>> pipe("This is a test")
|
||||||
|
[{"label": "1-star", "score": 0.8}, {"label": "2-star", "score": 0.1}, {"label": "3-star", "score": 0.05}
|
||||||
|
{"label": "4-star", "score": 0.025}, {"label": "5-star", "score": 0.025}]
|
||||||
|
|
||||||
|
>>> pipe("This is a test", top_k=2)
|
||||||
|
[{"label": "1-star", "score": 0.8}, {"label": "2-star", "score": 0.1}]
|
||||||
|
```
|
||||||
|
|
||||||
|
Para lograrlo, actualizaremos nuestro método `postprocess` con un valor por defecto de `5` y modificaremos
|
||||||
|
`_sanitize_parameters` para permitir este nuevo parámetro.
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
def postprocess(self, model_outputs, top_k=5):
|
||||||
|
best_class = model_outputs["logits"].softmax(-1)
|
||||||
|
# Añade la lógica para manejar el top_k
|
||||||
|
return best_class
|
||||||
|
|
||||||
|
|
||||||
|
def _sanitize_parameters(self, **kwargs):
|
||||||
|
preprocess_kwargs = {}
|
||||||
|
if "maybe_arg" in kwargs:
|
||||||
|
preprocess_kwargs["maybe_arg"] = kwargs["maybe_arg"]
|
||||||
|
|
||||||
|
postprocess_kwargs = {}
|
||||||
|
if "top_k" in kwargs:
|
||||||
|
postprocess_kwargs["top_k"] = kwargs["top_k"]
|
||||||
|
return preprocess_kwargs, {}, postprocess_kwargs
|
||||||
|
```
|
||||||
|
|
||||||
|
Intenta que las entradas y salidas sean muy simples e, idealmente, que puedan serializarse como JSON, pues esto
|
||||||
|
hace el uso del pipeline muy sencillo sin que el usuario tenga que preocuparse por conocer nuevos tipos de objetos.
|
||||||
|
También es relativamente común tener compatibilidad con muchos tipos diferentes de argumentos por facilidad de uso
|
||||||
|
(por ejemplo, los archivos de audio pueden ser nombres de archivo, URLs o bytes).
|
||||||
|
|
||||||
|
|
||||||
|
## Añadirlo a la lista de tareas
|
||||||
|
|
||||||
|
Para registrar tu `new-task` (nueva tarea) en la lista de tareas, debes añadirla al
|
||||||
|
`PIPELINE_REGISTRY` (registro de pipelines):
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers.pipelines import PIPELINE_REGISTRY
|
||||||
|
|
||||||
|
PIPELINE_REGISTRY.register_pipeline(
|
||||||
|
"new-task",
|
||||||
|
pipeline_class=MyPipeline,
|
||||||
|
pt_model=AutoModelForSequenceClassification,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Puedes especificar un modelo por defecto si lo deseas, en cuyo caso debe venir con una versión específica (que puede ser el nombre de un branch o hash de commit, en este caso usamos `"abcdef"`), así como el tipo:
|
||||||
|
|
||||||
|
```python
|
||||||
|
PIPELINE_REGISTRY.register_pipeline(
|
||||||
|
"new-task",
|
||||||
|
pipeline_class=MyPipeline,
|
||||||
|
pt_model=AutoModelForSequenceClassification,
|
||||||
|
default={"pt": ("user/awesome_model", "abcdef")},
|
||||||
|
type="text", # tipo de datos que maneja: texto, audio, imagen, multi-modalidad
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparte tu pipeline en el Hub
|
||||||
|
|
||||||
|
Para compartir tu pipeline personalizado en el Hub, solo tienes que guardar el código personalizado de tu sub-clase
|
||||||
|
`Pipeline` en un archivo de Python. Por ejemplo, digamos que queremos usar un pipeline personalizado para la
|
||||||
|
clasificación de duplas de oraciones de esta forma:
|
||||||
|
|
||||||
|
```py
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from transformers import Pipeline
|
||||||
|
|
||||||
|
|
||||||
|
def softmax(outputs):
|
||||||
|
maxes = np.max(outputs, axis=-1, keepdims=True)
|
||||||
|
shifted_exp = np.exp(outputs - maxes)
|
||||||
|
return shifted_exp / shifted_exp.sum(axis=-1, keepdims=True)
|
||||||
|
|
||||||
|
|
||||||
|
class PairClassificationPipeline(Pipeline):
|
||||||
|
def _sanitize_parameters(self, **kwargs):
|
||||||
|
preprocess_kwargs = {}
|
||||||
|
if "second_text" in kwargs:
|
||||||
|
preprocess_kwargs["second_text"] = kwargs["second_text"]
|
||||||
|
return preprocess_kwargs, {}, {}
|
||||||
|
|
||||||
|
def preprocess(self, text, second_text=None):
|
||||||
|
return self.tokenizer(text, text_pair=second_text, return_tensors=self.framework)
|
||||||
|
|
||||||
|
def _forward(self, model_inputs):
|
||||||
|
return self.model(**model_inputs)
|
||||||
|
|
||||||
|
def postprocess(self, model_outputs):
|
||||||
|
logits = model_outputs.logits[0].numpy()
|
||||||
|
probabilities = softmax(logits)
|
||||||
|
|
||||||
|
best_class = np.argmax(probabilities)
|
||||||
|
label = self.model.config.id2label[best_class]
|
||||||
|
score = probabilities[best_class].item()
|
||||||
|
logits = logits.tolist()
|
||||||
|
return {"label": label, "score": score, "logits": logits}
|
||||||
|
```
|
||||||
|
|
||||||
|
La implementación es independiente del framework y funcionará con modelos de PyTorch y TensorFlow. Si guardamos
|
||||||
|
esto en un archivo llamado `pair_classification.py`, podemos importarlo y registrarlo de la siguiente manera:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from pair_classification import PairClassificationPipeline
|
||||||
|
from transformers.pipelines import PIPELINE_REGISTRY
|
||||||
|
from transformers import AutoModelForSequenceClassification, TFAutoModelForSequenceClassification
|
||||||
|
|
||||||
|
PIPELINE_REGISTRY.register_pipeline(
|
||||||
|
"pair-classification",
|
||||||
|
pipeline_class=PairClassificationPipeline,
|
||||||
|
pt_model=AutoModelForSequenceClassification,
|
||||||
|
tf_model=TFAutoModelForSequenceClassification,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Una vez hecho esto, podemos usarlo con un modelo pre-entrenado. Por ejemplo, al modelo `sgugger/finetuned-bert-mrpc`
|
||||||
|
se le hizo fine-tuning con el dataset MRPC, en el cual se clasifican duplas de oraciones como paráfrasis o no.
|
||||||
|
|
||||||
|
```py
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
classifier = pipeline("pair-classification", model="sgugger/finetuned-bert-mrpc")
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora podemos compartirlo en el Hub usando el método `save_pretrained` (guardar pre-entrenado) en un `Repository`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from huggingface_hub import Repository
|
||||||
|
|
||||||
|
repo = Repository("test-dynamic-pipeline", clone_from="{your_username}/test-dynamic-pipeline")
|
||||||
|
classifier.save_pretrained("test-dynamic-pipeline")
|
||||||
|
repo.push_to_hub()
|
||||||
|
```
|
||||||
|
|
||||||
|
Esto copiará el archivo donde definiste `PairClassificationPipeline` dentro de la carpeta `"test-dynamic-pipeline"`,
|
||||||
|
y además guardará el modelo y el tokenizer del pipeline, antes de enviar todo al repositorio
|
||||||
|
`{your_username}/test-dynamic-pipeline`. Después de esto, cualquier persona puede usarlo siempre que usen la opción
|
||||||
|
`trust_remote_code=True` (confiar en código remoto):
|
||||||
|
|
||||||
|
```py
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
classifier = pipeline(model="{your_username}/test-dynamic-pipeline", trust_remote_code=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Añadir el pipeline a 🤗 Transformers
|
||||||
|
|
||||||
|
Si quieres contribuir tu pipeline a la biblioteca 🤗 Transformers, tendrás que añadirlo a un nuevo módulo en el
|
||||||
|
sub-módulo `pipelines` con el código de tu pipeline. Luego, debes añadirlo a la lista de tareas definidas en
|
||||||
|
`pipelines/__init__.py`.
|
||||||
|
|
||||||
|
A continuación tienes que añadir las pruebas. Crea un nuevo archivo llamado `tests/test_pipelines_MY_PIPELINE.py`
|
||||||
|
basándote en las pruebas existentes.
|
||||||
|
|
||||||
|
La función `run_pipeline_test` será muy genérica y se correrá sobre modelos pequeños escogidos al azar sobre todas las
|
||||||
|
arquitecturas posibles definidas en `model_mapping` y `tf_model_mapping`.
|
||||||
|
|
||||||
|
Esto es muy importante para probar compatibilidades a futuro, lo que significa que si alguien añade un nuevo modelo
|
||||||
|
para `XXXForQuestionAnswering` entonces el pipeline intentará ejecutarse con ese modelo. Ya que los modelos son aleatorios,
|
||||||
|
es imposible verificar los valores como tales, y es por eso que hay un helper `ANY` que simplemente intentará que la
|
||||||
|
salida tenga el mismo tipo que la salida esperada del pipeline.
|
||||||
|
|
||||||
|
También *debes* implementar 2 (preferiblemente 4) pruebas:
|
||||||
|
|
||||||
|
- `test_small_model_pt` : Define un (1) modelo pequeño para este pipeline (no importa si los resultados no tienen sentido)
|
||||||
|
y prueba las salidas del pipeline. Los resultados deberían ser los mismos que en `test_small_model_tf`.
|
||||||
|
- `test_small_model_tf` : Define un (1) modelo pequeño para este pipeline (no importa si los resultados no tienen sentido)
|
||||||
|
y prueba las salidas del pipeline. Los resultados deberían ser los mismos que en `test_small_model_pt`.
|
||||||
|
- `test_large_model_pt` (`optional`): Prueba el pipeline en una tarea real en la que los resultados deben tener sentido.
|
||||||
|
Estas pruebas son lentas y deben marcarse como tales. El objetivo de esto es ejemplificar el pipeline y asegurarse de que
|
||||||
|
no haya divergencias en versiones futuras.
|
||||||
|
- `test_large_model_tf` (`optional`): Prueba el pipeline en una tarea real en la que los resultados deben tener sentido.
|
||||||
|
Estas pruebas son lentas y deben marcarse como tales. El objetivo de esto es ejemplificar el pipeline y asegurarse de que
|
||||||
|
no haya divergencias en versiones futuras.
|
||||||
363
docs/source/es/tasks/asr.mdx
Normal file
363
docs/source/es/tasks/asr.mdx
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
<!--Copyright 2022 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Reconocimiento automático del habla
|
||||||
|
|
||||||
|
<Youtube id="TksaY_FDgnk"/>
|
||||||
|
|
||||||
|
El reconocimiento automático del habla (ASR, por sus siglas en inglés) convierte una señal de habla en texto y mapea una secuencia de entradas de audio en salidas en forma de texto. Los asistentes virtuales como Siri y Alexa usan modelos de ASR para ayudar a sus usuarios todos los días. De igual forma, hay muchas otras aplicaciones, como la transcripción de contenidos en vivo y la toma automática de notas durante reuniones.
|
||||||
|
|
||||||
|
En esta guía te mostraremos como:
|
||||||
|
|
||||||
|
1. Hacer fine-tuning al modelo [Wav2Vec2](https://huggingface.co/facebook/wav2vec2-base) con el dataset [MInDS-14](https://huggingface.co/datasets/PolyAI/minds14) para transcribir audio a texto.
|
||||||
|
2. Usar tu modelo ajustado para tareas de inferencia.
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
|
||||||
|
Revisa la [página de la tarea](https://huggingface.co/tasks/automatic-speech-recognition) de reconocimiento automático del habla para acceder a más información sobre los modelos, datasets y métricas asociados.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
Antes de comenzar, asegúrate de haber instalado todas las librerías necesarias:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install transformers datasets evaluate jiwer
|
||||||
|
```
|
||||||
|
|
||||||
|
Te aconsejamos iniciar sesión con tu cuenta de Hugging Face para que puedas subir tu modelo y comartirlo con la comunidad. Cuando te sea solicitado, ingresa tu token para iniciar sesión:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> from huggingface_hub import notebook_login
|
||||||
|
|
||||||
|
>>> notebook_login()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cargar el dataset MInDS-14
|
||||||
|
|
||||||
|
Comencemos cargando un subconjunto más pequeño del dataset [MInDS-14](https://huggingface.co/datasets/PolyAI/minds14) desde la biblioteca 🤗 Datasets. De esta forma, tendrás la oportunidad de experimentar y asegurarte de que todo funcione antes de invertir más tiempo entrenando con el dataset entero.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> from datasets import load_dataset, Audio
|
||||||
|
|
||||||
|
>>> minds = load_dataset("PolyAI/minds14", name="en-US", split="train[:100]")
|
||||||
|
```
|
||||||
|
Divide la partición `train` (entrenamiento) en una partición de entrenamiento y una de prueba usando el método [`~Dataset.train_test_split`]:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> minds = minds.train_test_split(test_size=0.2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora échale un vistazo al dataset:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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 dataset contiene mucha información útil, como los campos `lang_id` (identificador del lenguaje) y `english_transcription` (transcripción al inglés), en esta guía nos enfocaremos en los campos `audio` y `transcription`. Puedes quitar las otras columnas con el método [`~datasets.Dataset.remove_columns`]:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> minds = minds.remove_columns(["english_transcription", "intent_class", "lang_id"])
|
||||||
|
```
|
||||||
|
|
||||||
|
Vuelve a echarle un vistazo al ejemplo:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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`: un `array` (arreglo) unidimensional de la señal de habla que debe ser invocado para cargar y re-muestrear el archivo de audio.
|
||||||
|
- `transcription`: el texto objetivo.
|
||||||
|
|
||||||
|
## Preprocesamiento
|
||||||
|
|
||||||
|
El siguiente paso es cargar un procesador Wav2Vec2 para procesar la señal de audio:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> from transformers import AutoProcessor
|
||||||
|
|
||||||
|
>>> processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base")
|
||||||
|
```
|
||||||
|
El dataset MInDS-14 tiene una tasa de muestreo de 8000kHz (puedes encontrar esta información en su [tarjeta de dataset](https://huggingface.co/datasets/PolyAI/minds14)), lo que significa que tendrás que re-muestrear el dataset a 16000kHz para poder usar el modelo Wav2Vec2 pre-entrenado:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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 puedes ver en el campo `transcription`, el texto contiene una mezcla de carácteres en mayúsculas y en minúsculas. El tokenizer Wav2Vec2 fue entrenado únicamente con carácteres en mayúsculas, así que tendrás que asegurarte de que el texto se ajuste al vocabulario del tokenizer:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> def uppercase(example):
|
||||||
|
... return {"transcription": example["transcription"].upper()}
|
||||||
|
|
||||||
|
|
||||||
|
>>> minds = minds.map(uppercase)
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora vamos a crear una función de preprocesamiento que:
|
||||||
|
|
||||||
|
1. Invoque la columna `audio` para cargar y re-muestrear el archivo de audio.
|
||||||
|
2. Extraiga el campo `input_values` (valores de entrada) del archivo de audio y haga la tokenización de la columna `transcription` con el procesador.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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 batch
|
||||||
|
```
|
||||||
|
|
||||||
|
Para aplicar la función de preprocesamiento a todo el dataset, puedes usar la función [`~datasets.Dataset.map`] de 🤗 Datasets. Para acelerar la función `map` puedes incrementar el número de procesos con el parámetro `num_proc`. Quita las columnas que no necesites con el método [`~datasets.Dataset.remove_columns`]:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> encoded_minds = minds.map(prepare_dataset, remove_columns=minds.column_names["train"], num_proc=4)
|
||||||
|
```
|
||||||
|
|
||||||
|
🤗 Transformers no tiene un collator de datos para la tarea de ASR, así que tendrás que adaptar el [`DataCollatorWithPadding`] para crear un lote de ejemplos. El collator también le aplicará padding dinámico a tu texto y etiquetas para que tengan la longitud del elemento más largo en su lote (en vez de la mayor longitud en el dataset entero), de forma que todas las muestras tengan una longitud uniforme. Aunque es posible hacerle padding a tu texto con el `tokenizer` haciendo `padding=True`, el padding dinámico es más eficiente.
|
||||||
|
|
||||||
|
A diferencia de otros collators de datos, este tiene que aplicarle un método de padding distinto a los campos `input_values` (valores de entrada) y `labels` (etiquetas):
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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]:
|
||||||
|
... # particiona las entradas y las etiquetas ya que tienen que tener longitudes distintas y
|
||||||
|
... # requieren métodos de padding diferentes
|
||||||
|
... 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")
|
||||||
|
|
||||||
|
... # remplaza el padding con -100 para ignorar la pérdida de forma correcta
|
||||||
|
... labels = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100)
|
||||||
|
|
||||||
|
... batch["labels"] = labels
|
||||||
|
|
||||||
|
... return batch
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora puedes instanciar tu `DataCollatorForCTCWithPadding`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> data_collator = DataCollatorCTCWithPadding(processor=processor, padding="longest")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Evaluación
|
||||||
|
|
||||||
|
A menudo es útil incluir una métrica durante el entrenamiento para evaluar el rendimiento de tu modelo. Puedes cargar un método de evaluación rápidamente con la biblioteca 🤗 [Evaluate](https://huggingface.co/docs/evaluate/index). Para esta tarea, puedes usar la métrica de [tasa de error por palabra](https://huggingface.co/spaces/evaluate-metric/wer) (WER, por sus siglas en inglés). Puedes ver la [guía rápida](https://huggingface.co/docs/evaluate/a_quick_tour) de 🤗 Evaluate para aprender más acerca de cómo cargar y computar una métrica.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> import evaluate
|
||||||
|
|
||||||
|
>>> wer = evaluate.load("wer")
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora crea una función que le pase tus predicciones y etiquetas a [`~evaluate.EvaluationModule.compute`] para calcular la WER:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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 = wer.compute(predictions=pred_str, references=label_str)
|
||||||
|
|
||||||
|
... return {"wer": wer}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora tu función `compute_metrics` (computar métricas) está lista y podrás usarla cuando estés preparando tu entrenamiento.
|
||||||
|
|
||||||
|
## Entrenamiento
|
||||||
|
|
||||||
|
<frameworkcontent>
|
||||||
|
<pt>
|
||||||
|
<Tip>
|
||||||
|
|
||||||
|
Si no tienes experiencia haciéndole fine-tuning a un modelo con el [`Trainer`], ¡échale un vistazo al tutorial básico [aquí](../training#train-with-pytorch-trainer)!
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
¡Ya puedes empezar a entrenar tu modelo! Para ello, carga Wav2Vec2 con [`AutoModelForCTC`]. Especifica la reducción que quieres aplicar con el parámetro `ctc_loss_reduction`. A menudo, es mejor usar el promedio en lugar de la sumatoria que se hace por defecto.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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:
|
||||||
|
|
||||||
|
1. Define tus hiperparámetros de entrenamiento en [`TrainingArguments`]. El único parámetro obligatorio es `output_dir` (carpeta de salida), el cual especifica dónde guardar tu modelo. Puedes subir este modelo al Hub haciendo `push_to_hub=True` (debes haber iniciado sesión en Hugging Face para subir tu modelo). Al final de cada época, el [`Trainer`] evaluará la WER y guardará el punto de control del entrenamiento.
|
||||||
|
2. Pásale los argumentos del entrenamiento al [`Trainer`] junto con el modelo, el dataset, el tokenizer, el collator de datos y la función `compute_metrics`.
|
||||||
|
3. Llama el método [`~Trainer.train`] para hacerle fine-tuning a tu modelo.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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,
|
||||||
|
... group_by_length=True,
|
||||||
|
... evaluation_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,
|
||||||
|
... )
|
||||||
|
|
||||||
|
>>> trainer = Trainer(
|
||||||
|
... model=model,
|
||||||
|
... args=training_args,
|
||||||
|
... train_dataset=encoded_minds["train"],
|
||||||
|
... eval_dataset=encoded_minds["test"],
|
||||||
|
... tokenizer=processor.feature_extractor,
|
||||||
|
... data_collator=data_collator,
|
||||||
|
... compute_metrics=compute_metrics,
|
||||||
|
... )
|
||||||
|
|
||||||
|
>>> trainer.train()
|
||||||
|
```
|
||||||
|
|
||||||
|
Una vez que el entrenamiento haya sido completado, comparte tu modelo en el Hub con el método [`~transformers.Trainer.push_to_hub`] para que todo el mundo pueda usar tu modelo:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> trainer.push_to_hub()
|
||||||
|
```
|
||||||
|
</pt>
|
||||||
|
</frameworkcontent>
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
|
||||||
|
Para ver un ejemplo más detallado de cómo hacerle fine-tuning a un modelo para reconocimiento automático del habla, échale un vistazo a esta [entrada de blog](https://huggingface.co/blog/fine-tune-wav2vec2-english) para ASR en inglés y a esta [entrada](https://huggingface.co/blog/fine-tune-xlsr-wav2vec2) para ASR multilingüe.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
## Inferencia
|
||||||
|
|
||||||
|
¡Genial, ahora que le has hecho fine-tuning a un modelo, puedes usarlo para inferencia!
|
||||||
|
|
||||||
|
Carga el archivo de audio sobre el cual quieras correr la inferencia. ¡Recuerda re-muestrar la tasa de muestreo del archivo de audio para que sea la misma del modelo si es necesario!
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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 manera más simple de probar tu modelo para hacer inferencia es usarlo en un [`pipeline`]. Puedes instanciar un `pipeline` para reconocimiento automático del habla con tu modelo y pasarle tu archivo de audio:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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'}
|
||||||
|
```
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
|
||||||
|
La transcripción es decente, pero podría ser mejor. ¡Intenta hacerle fine-tuning a tu modelo con más ejemplos para obtener resultados aún mejores!
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
También puedes replicar de forma manual los resultados del `pipeline` si lo deseas:
|
||||||
|
|
||||||
|
<frameworkcontent>
|
||||||
|
<pt>
|
||||||
|
Carga un procesador para preprocesar el archivo de audio y la transcripción y devuelve el `input` como un tensor de PyTorch:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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")
|
||||||
|
```
|
||||||
|
|
||||||
|
Pásale tus entradas al modelo y devuelve los logits:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> from transformers import AutoModelForCTC
|
||||||
|
|
||||||
|
>>> model = AutoModelForCTC.from_pretrained("stevhliu/my_awesome_asr_mind_model")
|
||||||
|
>>> with torch.no_grad():
|
||||||
|
... logits = model(**inputs).logits
|
||||||
|
```
|
||||||
|
|
||||||
|
Obtén los identificadores de los tokens con mayor probabilidad en las predicciones y usa el procesador para decodificarlos y transformarlos en texto:
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> 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']
|
||||||
|
```
|
||||||
|
</pt>
|
||||||
|
</frameworkcontent>
|
||||||
@@ -172,7 +172,7 @@ Para familiarizarte con el fine-tuning con [`Trainer`], ¡mira el tutorial bási
|
|||||||
En este punto, solo quedan tres pasos:
|
En este punto, solo quedan tres pasos:
|
||||||
|
|
||||||
1. Definir tus hiperparámetros de entrenamiento en [`TrainingArguments`].
|
1. Definir tus hiperparámetros de entrenamiento en [`TrainingArguments`].
|
||||||
2. Pasarle los argumentos del entrenamiento al [`Trainer`] jnto con el modelo, el dataset, el tokenizer y el collator de datos.
|
2. Pasarle los argumentos del entrenamiento al [`Trainer`] junto con el modelo, el dataset, el tokenizer y el collator de datos.
|
||||||
3. Invocar el método [`~Trainer.train`] para realizar el fine-tuning del modelo.
|
3. Invocar el método [`~Trainer.train`] para realizar el fine-tuning del modelo.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
|||||||
Reference in New Issue
Block a user