# Classificação de áudio

A classificação de áudio — assim como a de texto — atribui um rótulo de classe como saída a partir dos dados de entrada. A única diferença é que, em vez de entradas de texto, você tem formas de onda de áudio brutas. Algumas aplicações práticas da classificação de áudio incluem a identificação da intenção do falante, a classificação de idiomas e até mesmo a identificação de espécies de animais pelos seus sons.

Este guia mostrará como:

1. Ajuste fino de [Wav2Vec2](https://huggingface.co/facebook/wav2vec2-base) no conjunto de dados [MInDS-14](https://huggingface.co/datasets/PolyAI/minds14) para classificar a intenção do falante.
2. Use seu modelo ajustado para inferência.

Para ver todas as arquiteturas e checkpoints compatíveis com esta tarefa, recomendamos consultar a [página da tarefa](https://huggingface.co/tasks/audio-classification)

Antes de começar, verifique se você tem todas as bibliotecas necessárias instaladas:

```bash
pip install transformers datasets evaluate soundfile librosa torchcodec
```

Recomendamos que você faça login na sua conta do Hugging Face para que possa enviar e compartilhar seu modelo com a comunidade. Quando solicitado, insira seu token para fazer login:

```py
>>> from huggingface_hub import notebook_login

>>> notebook_login()
```

## Carregar o conjunto de dados MInDS-14

Comece carregando o conjunto de dados MInDS-14 a partir da biblioteca 🤗 Datasets:

```py
>>> from datasets import load_dataset, Audio

>>> minds = load_dataset("PolyAI/minds14", name="en-US", split="train")
```

Divida o split `train` do conjunto de dados em um conjunto de treino menor e um conjunto de teste com o método [train_test_split](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.train_test_split). Isso lhe dará a oportunidade de experimentar e garantir que tudo funcione antes de gastar mais tempo no conjunto de dados completo.

```py
>>> minds = minds.train_test_split(test_size=0.2)
```

Em seguida, examine o conjunto de dados:

```py
>>> minds
DatasetDict({
    train: Dataset({
        features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
        num_rows: 450
    })
    test: Dataset({
        features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
        num_rows: 113
    })
})
```

Embora o conjunto de dados contenha muitas informações úteis, como `lang_id` e `english_transcription`, você se concentrará em `audio` e `intent_class` neste guia. Remova as outras colunas com o método [remove_columns](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.remove_columns):

```py
>>> minds = minds.remove_columns(["path", "transcription", "english_transcription", "lang_id"])
```

Aqui está um exemplo:

```py
>>> minds["train"][0]
{'audio': {'array': array([ 0.        ,  0.        ,  0.        , ..., -0.00048828,
         -0.00024414, -0.00024414], dtype=float32),
  'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602b9a5fbb1e6d0fbce91f52.wav',
  'sampling_rate': 8000},
 'intent_class': 2}
```

Há dois campos:

- `audio`: um `array` unidimensional do sinal de fala que deve ser chamado para carregar e reamostrar o arquivo de áudio.
- `intent_class`: representa o id da classe da intenção do falante.

Para facilitar que o modelo obtenha o nome do rótulo a partir do id do rótulo, crie um dicionário que mapeia o nome do rótulo para um inteiro e vice-versa:

```py
>>> labels = minds["train"].features["intent_class"].names
>>> label2id, id2label = dict(), dict()
>>> for i, label in enumerate(labels):
...     label2id[label] = str(i)
...     id2label[str(i)] = label
```

Agora você pode converter o id do rótulo em um nome de rótulo:

```py
>>> id2label[str(2)]
'app_error'
```

## Pré-processar

A próxima etapa é carregar um extrator de recursos Wav2Vec2 para processar o sinal de áudio:

```py
>>> from transformers import AutoFeatureExtractor

>>> feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")
```

O conjunto de dados MInDS-14 tem uma taxa de amostragem de 8 kHz (você pode encontrar essa informação em seu [dataset card](https://huggingface.co/datasets/PolyAI/minds14)), o que significa que você precisará reamostrar o conjunto de dados para 16 kHz para usar o modelo Wav2Vec2 pré-treinado:

```py
>>> minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
>>> minds["train"][0]
{'audio': {'array': array([ 2.2098757e-05,  4.6582241e-05, -2.2803260e-05, ...,
         -2.8419291e-04, -2.3305941e-04, -1.1425107e-04], dtype=float32),
  'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602b9a5fbb1e6d0fbce91f52.wav',
  'sampling_rate': 16000},
 'intent_class': 2}
```

Agora, crie uma função de pré-processamento que:

1. Chama a coluna `audio` para carregar e, se necessário, reamostra o arquivo de áudio.
2. Verifica se a taxa de amostragem do arquivo de áudio corresponde à taxa de amostragem dos dados de áudio com os quais o modelo foi pré-treinado. Você pode encontrar essas informações no [model card](https://huggingface.co/facebook/wav2vec2-base) do Wav2Vec2.
3. Defina um comprimento máximo de entrada para agrupar entradas mais longas sem truncá-las.

```py
>>> def preprocess_function(examples):
...     audio_arrays = [x["array"] for x in examples["audio"]]
...     inputs = feature_extractor(
...         audio_arrays, sampling_rate=feature_extractor.sampling_rate, max_length=16000, truncation=True
...     )
...     return inputs
```

Para aplicar a função de pré-processamento em todo o conjunto de dados, use a função [map](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.map) do 🤗 Datasets. Você pode acelerar o `map` definindo `batched=True` para processar vários elementos do conjunto de dados de uma vez. Remova as colunas desnecessárias e renomeie `intent_class` para `label`, conforme exigido pelo modelo:

```py
>>> encoded_minds = minds.map(preprocess_function, remove_columns="audio", batched=True)
>>> encoded_minds = encoded_minds.rename_column("intent_class", "label")
```

## Avaliar

Incluir uma métrica durante o treinamento é frequentemente útil para avaliar o desempenho do seu modelo. Você pode carregar rapidamente um método de avaliação com a biblioteca 🤗 [Evaluate](https://huggingface.co/docs/evaluate/index). Para esta tarefa, carregue a métrica [accuracy](https://huggingface.co/spaces/evaluate-metric/accuracy) (veja o [quick tour](https://huggingface.co/docs/evaluate/a_quick_tour) do 🤗 Evaluate para saber mais sobre como carregar e calcular uma métrica):

```py
>>> import evaluate

>>> accuracy = evaluate.load("accuracy")
```

Em seguida, crie uma função que passa suas previsões e rótulos para [compute](https://huggingface.co/docs/evaluate/main/en/package_reference/main_classes#evaluate.EvaluationModule.compute) para calcular a precisão:

```py
>>> import numpy as np

>>> def compute_metrics(eval_pred):
...     predictions = np.argmax(eval_pred.predictions, axis=1)
...     return accuracy.compute(predictions=predictions, references=eval_pred.label_ids)
```

Sua função `compute_metrics` está pronta para uso e você voltará a ela ao configurar o treinamento.

## Treinar

Se você não está familiarizado com o ajuste fino de um modelo usando o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer), dê uma olhada no tutorial básico [aqui](../training)!

Agora você está pronto para começar a treinar seu modelo! Carregue o Wav2Vec2 com [AutoModelForAudioClassification](/docs/transformers/main/pt/model_doc/auto#transformers.AutoModelForAudioClassification) junto com o número de rótulos esperados e os mapeamentos de rótulos:

```py
>>> from transformers import AutoModelForAudioClassification, TrainingArguments, Trainer

>>> num_labels = len(id2label)
>>> model = AutoModelForAudioClassification.from_pretrained(
...     "facebook/wav2vec2-base", num_labels=num_labels, label2id=label2id, id2label=id2label
... )
```

Neste ponto, restam apenas três etapas:

1. Defina os hiperparâmetros de treinamento em [TrainingArguments](/docs/transformers/main/pt/main_classes/trainer#transformers.TrainingArguments). O único parâmetro obrigatório é `output_dir`, que especifica onde salvar seu modelo. Você enviará este modelo para o Hub definindo `push_to_hub=True` (é necessário estar conectado ao Hugging Face para enviar seu modelo). No final de cada epoch, o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) avaliará a precisão e salvará o checkpoint de treinamento.
2. Passe os argumentos de treinamento para o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) junto com o modelo, o conjunto de dados, o tokenizer, o data collator e a função `compute_metrics`.
3. Chame [train()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.train) para fazer o ajuste fino do seu modelo.

```py
>>> training_args = TrainingArguments(
...     output_dir="my_awesome_mind_model",
...     eval_strategy="epoch",
...     save_strategy="epoch",
...     learning_rate=3e-5,
...     per_device_train_batch_size=32,
...     gradient_accumulation_steps=4,
...     per_device_eval_batch_size=32,
...     num_train_epochs=10,
...     warmup_steps=0.1,
...     logging_steps=10,
...     load_best_model_at_end=True,
...     metric_for_best_model="accuracy",
...     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=feature_extractor,
...     compute_metrics=compute_metrics,
... )

>>> trainer.train()
```

Quando o treinamento for concluído, compartilhe seu modelo no Hub com o método [push_to_hub()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.push_to_hub) para que todos possam usá-lo:

```py
>>> trainer.push_to_hub()
```

Para um exemplo mais detalhado de como fazer o ajuste fino de um modelo para classificação de áudio, confira o [notebook do PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/audio_classification.ipynb) correspondente.

## Inferência

Ótimo, agora que você ajustou um modelo, pode usá-lo para inferência!

Carregue um arquivo de áudio para inferência. Lembre-se de reamostrar a taxa de amostragem do arquivo de áudio para corresponder à taxa de amostragem do modelo, se necessário.

```py
>>> from datasets import load_dataset, Audio

>>> dataset = load_dataset("PolyAI/minds14", name="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"]
```

A maneira mais simples de testar seu modelo ajustado para inferência é usá-lo em um [pipeline()](/docs/transformers/main/pt/main_classes/pipelines#transformers.pipeline). Instancie um `pipeline` para classificação de áudio com seu modelo e passe seu arquivo de áudio para ele:

```py
>>> from transformers import pipeline

>>> classifier = pipeline("audio-classification", model="stevhliu/my_awesome_minds_model")
>>> classifier(audio_file)
[
    {'score': 0.09766869246959686, 'label': 'cash_deposit'},
    {'score': 0.07998877018690109, 'label': 'app_error'},
    {'score': 0.0781070664525032, 'label': 'joint_account'},
    {'score': 0.07667109370231628, 'label': 'pay_bill'},
    {'score': 0.0755252093076706, 'label': 'balance'}
]
```

Você também pode replicar manualmente os resultados do `pipeline`, se desejar:

Carregue um extrator de recursos para pré-processar o arquivo de áudio e retornar o `input` como tensores do PyTorch:

```py
>>> from transformers import AutoFeatureExtractor

>>> feature_extractor = AutoFeatureExtractor.from_pretrained("stevhliu/my_awesome_minds_model")
>>> inputs = feature_extractor(dataset[0]["audio"]["array"], sampling_rate=sampling_rate, return_tensors="pt")
```

Passe suas entradas para o modelo e retorne os logits:

```py
>>> from transformers import AutoModelForAudioClassification

>>> model = AutoModelForAudioClassification.from_pretrained("stevhliu/my_awesome_minds_model")
>>> with torch.no_grad():
...     logits = model(**inputs).logits
```

Obtenha a classe com a maior probabilidade e use o mapeamento `id2label` do modelo para convertê-la em um rótulo:

```py
>>> import torch

>>> predicted_class_ids = torch.argmax(logits).item()
>>> predicted_label = model.config.id2label[predicted_class_ids]
>>> predicted_label
'cash_deposit'
```

