| import os |
| import torch |
| import glob |
| from datasets import load_dataset, Audio, Dataset, ClassLabel |
| from transformers import ( |
| AutoFeatureExtractor, |
| AutoModelForAudioClassification, |
| TrainingArguments, |
| Trainer |
| ) |
| import numpy as np |
| import evaluate |
| import random |
|
|
| |
| |
| MODEL_NAME = "lgris/w2v_podcasts_base_400k_pt" |
| |
| DATASET_PATH = "./dataset_preparado/" |
| |
| OUTPUT_DIR = "./portuguese-accent-classifier" |
| |
| NUM_TRAIN_EPOCHS = 50 |
| BATCH_SIZE = 32 |
|
|
| def train_model(): |
| """ |
| Carrega o dataset, pré-processa os dados e faz o fine-tuning do modelo |
| para classificação de sotaques. |
| """ |
| print("Carregando dataset a partir das pastas...") |
| |
| |
| pt_br_files = glob.glob(os.path.join(DATASET_PATH, "pt_br", "*.wav")) |
| pt_pt_files = glob.glob(os.path.join(DATASET_PATH, "pt_pt", "*.wav")) |
| |
| print(f"Arquivos pt_br encontrados: {len(pt_br_files)}") |
| print(f"Arquivos pt_pt encontrados: {len(pt_pt_files)}") |
| |
| |
| all_files = [] |
| all_labels = [] |
| |
| |
| for file_path in pt_br_files: |
| all_files.append(file_path) |
| all_labels.append(0) |
| |
| |
| for file_path in pt_pt_files: |
| all_files.append(file_path) |
| all_labels.append(1) |
| |
| print(f"Total de arquivos carregados: {len(all_files)}") |
| |
| |
| data_dict = { |
| "audio": all_files, |
| "label": all_labels |
| } |
| |
| dataset = Dataset.from_dict(data_dict) |
| dataset = dataset.cast_column("audio", Audio()) |
| |
| |
| labels = ["pt_br", "pt_pt"] |
| dataset = dataset.cast_column("label", ClassLabel(names=labels)) |
| |
| print(f"Dataset criado com {len(dataset)} exemplos") |
| |
| |
| dataset = dataset.train_test_split(test_size=0.1, shuffle=True, stratify_by_column="label") |
|
|
| print("Dataset carregado e dividido:") |
| print(dataset) |
| |
| |
| label2id, id2label = {}, {} |
| for i, label in enumerate(labels): |
| label2id[label] = str(i) |
| id2label[str(i)] = label |
|
|
| print(f"Mapeamento de labels: {id2label}") |
|
|
| |
| feature_extractor = AutoFeatureExtractor.from_pretrained(MODEL_NAME) |
| target_sampling_rate = feature_extractor.sampling_rate |
| target_length = int(target_sampling_rate * 5.0) |
| |
| def preprocess_function(examples): |
| |
| |
| audio_arrays = [x["array"] for x in examples["audio"]] |
| |
| |
| processed_audios = [] |
| for audio_array in audio_arrays: |
| audio_length = len(audio_array) |
| |
| if audio_length > target_length: |
| |
| start_idx = random.randint(0, audio_length - target_length) |
| processed_audio = audio_array[start_idx:start_idx + target_length] |
| else: |
| |
| padding_needed = target_length - audio_length |
| |
| |
| left_padding = random.randint(0, padding_needed) |
| right_padding = padding_needed - left_padding |
| |
| |
| left_silence = np.zeros(left_padding, dtype=audio_array.dtype) |
| right_silence = np.zeros(right_padding, dtype=audio_array.dtype) |
| |
| |
| processed_audio = np.concatenate([left_silence, audio_array, right_silence]) |
| |
| processed_audios.append(processed_audio) |
| |
| |
| inputs = feature_extractor( |
| processed_audios, |
| sampling_rate=target_sampling_rate, |
| padding=False, |
| truncation=False |
| ) |
| return inputs |
|
|
| |
| print("Aplicando pré-processamento...") |
| encoded_dataset = dataset.map(preprocess_function, remove_columns="audio", batched=True) |
| |
| |
| num_labels = len(labels) |
| model = AutoModelForAudioClassification.from_pretrained( |
| MODEL_NAME, |
| num_labels=num_labels, |
| label2id={k: int(v) for k, v in label2id.items()}, |
| id2label=id2label, |
| ignore_mismatched_sizes=True |
| ) |
| |
| |
| accuracy = evaluate.load("accuracy") |
| def compute_metrics(eval_pred): |
| predictions = np.argmax(eval_pred.predictions, axis=1) |
| return accuracy.compute(predictions=predictions, references=eval_pred.label_ids) |
|
|
| |
| training_args = TrainingArguments( |
| output_dir=OUTPUT_DIR, |
| eval_strategy="epoch", |
| save_strategy="epoch", |
| learning_rate=3e-5, |
| per_device_train_batch_size=BATCH_SIZE, |
| per_device_eval_batch_size=BATCH_SIZE, |
| num_train_epochs=NUM_TRAIN_EPOCHS, |
| weight_decay=0.01, |
| logging_steps=10, |
| load_best_model_at_end=True, |
| metric_for_best_model="accuracy", |
| report_to="tensorboard", |
| push_to_hub=False, |
| ) |
|
|
| |
| trainer = Trainer( |
| model=model, |
| args=training_args, |
| train_dataset=encoded_dataset["train"], |
| eval_dataset=encoded_dataset["test"], |
| tokenizer=feature_extractor, |
| compute_metrics=compute_metrics, |
| ) |
|
|
| |
| print("\n--- Iniciando o Fine-tuning ---") |
| trainer.train() |
| print("--- Treinamento Concluído ---\n") |
| |
| |
| final_model_path = os.path.join(OUTPUT_DIR, "final_model") |
| trainer.save_model(final_model_path) |
| print(f"Modelo final salvo em: {final_model_path}") |
|
|
|
|
| if __name__ == '__main__': |
| |
| if not torch.cuda.is_available(): |
| print("Aviso: Nenhuma GPU encontrada. O treinamento será muito lento.") |
| train_model() |