오디오 분류
Audio classification - 텍스트와 마찬가지로 - 입력 데이터에서 클래스 라벨을 출력으로 생성합니다. 유일한 차이는 텍스트 입력 대신 원시 오디오 웨이브폼을 사용한다는 점입니다. Audio classification의 실용적인 응용 분야에는 화자의 의도 식별, 언어 분류, 그리고 소리로부터 동물 종 식별 등이 포함됩니다.
이 가이드에서는 다음 내용을 보여 드립니다:
이 작업과 호환되는 모든 아키텍처와 체크포인트를 확인하려면 task-page를 확인하는 것을 권장합니다.
시작하기 전에 필요한 라이브러리가 모두 설치되어 있는지 확인하세요:
pip install transformers datasets evaluate soundfile librosa torchcodec
모델을 업로드하고 커뮤니티와 공유할 수 있도록 Hugging Face 계정에 로그인하는 것을 권장합니다. 프롬프트가 표시되면 로그인할 토큰을 입력하세요:
>>> from huggingface_hub import notebook_login
>>> notebook_login()MInDS-14 데이터셋 로드
🤗 Datasets 라이브러리를 사용하여 MInDS-14 데이터셋을 로드하는 것부터 시작합니다:
>>> from datasets import load_dataset, Audio
>>> minds = load_dataset("PolyAI/minds14", name="en-US", split="train")데이터셋의 train 스플릿을 train_test_split 메서드를 사용하여 더 작은 train 세트와 test 세트로 나눕니다. 이를 통해 전체 데이터셋에 더 많은 시간을 투입하기 전에 실험을 해보고 모든 것이 정상적으로 작동하는지 확인할 수 있습니다.
>>> minds = minds.train_test_split(test_size=0.2)이제 데이터셋을 살펴보세요:
>>> 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
})
})데이터셋에는 lang_id와 english_transcription와 같이 유용한 정보가 많이 포함되어 있지만, 이 가이드에서는 audio와 intent_class에 집중합니다. remove_columns 메서드를 사용하여 다른 컬럼을 제거하세요:
>>> minds = minds.remove_columns(["path", "transcription", "english_transcription", "lang_id"])다음은 예시입니다:
>>> 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}두 개의 필드가 있습니다:
audio: 오디오 파일을 로드하고 리샘플링하기 위해 호출해야 하는 음성 신호의 1차원array.intent_class: 화자의 의도 클래스 ID를 나타냅니다.
에서 를 더 쉽게 가져올 수 있도록, 을 정수로 매핑하고 그 반대의 경우도 처리하는 사전(dictionary)을 생성합니다:
>>> 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이제 label id를 label 이름으로 변환할 수 있습니다:
>>> id2label[str(2)]
'app_error'전처리
다음 단계는 오디오 신호를 처리하기 위해 Wav2Vec2 feature extractor를 로드하는 것입니다:
>>> from transformers import AutoFeatureExtractor
>>> feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")MInDS-14 데이터셋의 샘플링 주파수는 8kHz입니다(dataset card에서 이 정보를 확인할 수 있습니다). 따라서 사전 학습된 Wav2Vec2 모델을 사용하려면 데이터셋을 16kHz로 리샘플링해야 합니다:
>>> 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}이제 다음을 수행하는 전처리 함수를 생성합니다:
audio컬럼을 불러오도록 호출하고, 필요할 경우 오디오 파일을 리샘플링합니다.- 오디오 파일의 샘플링 레이트가 모델이 사전 학습에 사용한 오디오 데이터의 샘플링 레이트와 일치하는지 확인합니다. 이 정보는 Wav2Vec2 모델 카드에서 찾을 수 있습니다.
- 입력을 잘라내지 않고 더 긴 입력을 배치하기 위해 최대 입력 길이를 설정합니다.
>>> 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전체 데이터셋에 전처리 함수를 적용하려면 🤗 Datasets의 map 함수를 사용합니다. batched=True를 설정하여 데이터셋의 여러 요소를 한 번에 처리하면 map의 속도를 높일 수 있습니다. 모델에서 요구하는 대로 불필요한 컬럼을 제거하고 intent_class를 label로 이름 변경합니다:
>>> encoded_minds = minds.map(preprocess_function, remove_columns="audio", batched=True)
>>> encoded_minds = encoded_minds.rename_column("intent_class", "label")평가
학습 중에 메트릭을 포함하는 것은 모델 성능을 평가하는 데 도움이 되는 경우가 많습니다. 🤗 Evaluate 라이브러리를 사용하면 평가 방법을 빠르게 로드할 수 있습니다. 이 작업에서는 accuracy 메트릭을 로드합니다(메트릭을 로드하고 계산하는 방법에 대해 자세히 알아보려면 🤗 Evaluate quick tour를 참고하세요):
>>> import evaluate
>>> accuracy = evaluate.load("accuracy")이후 예측값과 라벨을 compute에 전달하여 정확도를 계산하는 함수를 만듭니다:
>>> 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)compute_metrics 함수가 이제 준비되었습니다. 학습을 설정할 때 다시 이 함수를 다루게 됩니다.
학습
Trainer를 사용하여 모델을 fine-tuning하는 방법에 대해 잘 모르신다면, 여기의 기본 튜토리얼을 참고하세요!
이제 모델 학습을 시작할 준비가 되었습니다! AutoModelForAudioClassification를 사용하여 Wav2Vec2를 로드하고, 예상되는 라벨 수와 라벨 매핑을 지정하세요:
>>> 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
... )이 시점에서 남은 단계는 단 세 가지입니다:
- TrainingArguments에서 학습 하이퍼파라미터를 정의합니다. 필수 파라미터는
output_dir하나이며, 모델을 저장할 위치를 지정합니다.push_to_hub=True를 설정하여 모델을 Hub에 업로드할 수 있습니다(모델 업로드를 위해 Hugging Face에 로그인되어 있어야 합니다). 각 epoch가 끝나면 Trainer가 정확도를 평가하고 학습 체크포인트를 저장합니다. - 모델, 데이터셋, 토크나이저, 데이터 콜레이터,
compute_metrics함수와 함께 학습 인수를 Trainer에 전달합니다. - train()을 호출하여 모델을 파인튜닝합니다.
>>> 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()학습이 완료되면 push_to_hub() 메서드를 사용하여 모델을 Hub에 공유하여 누구나 모델을 사용할 수 있도록 하세요:
>>> trainer.push_to_hub()음성 분류를 위해 모델을 미세 조정하는 방법에 대한 더 자세한 예제는 해당 PyTorch 노트북을 참고하세요.
추론
좋습니다. 이제 모델을 fine-tuning 했으므로 추론에 사용할 수 있습니다!
추론을 위해 오디오 파일을 로드합니다. 필요에 따라 오디오 파일의 샘플링 레이트를 모델의 샘플링 레이트에 맞게 리샘플링하는 것을 잊지 마세요.
>>> 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"]파인튜닝한 모델을 추론에 적용해 보는 가장 간단한 방법은 pipeline()에서 사용하는 것입니다. 해당 모델로 오디오 분류용 pipeline을 생성한 후, 오디오 파일을 전달하세요:
>>> 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'}
]원하시는 경우 pipeline의 결과를 수동으로 재현할 수도 있습니다:
오디오 파일을 전처리하고 input을 PyTorch 텐서로 반환하기 위해 feature extractor를 로드합니다:
>>> 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")입력을 모델에 전달하고 logits를 반환합니다:
>>> from transformers import AutoModelForAudioClassification
>>> model = AutoModelForAudioClassification.from_pretrained("stevhliu/my_awesome_minds_model")
>>> with torch.no_grad():
... logits = model(**inputs).logits가장 높은 확률을 가진 클래스를 가져오고, 모델의 id2label 매핑을 사용하여 라벨로 변환합니다:
>>> import torch
>>> predicted_class_ids = torch.argmax(logits).item()
>>> predicted_label = model.config.id2label[predicted_class_ids]
>>> predicted_label
'cash_deposit'