--- license: other license_name: non-commercial-inherited language: - ko library_name: pytorch pipeline_tag: audio-classification tags: - audio - audio-classification - sound-event-detection - efficientat - mobilenetv3 - edge datasets: - retrina0678/miimo-audio-dataset metrics: - accuracy - f1 - recall model-index: - name: miimo-efficientat-target4 results: - task: type: audio-classification name: Sound Event Classification dataset: name: miimo-audio-dataset (4-class, held-out test) type: retrina0678/miimo-audio-dataset metrics: - type: accuracy value: 0.9774 name: Accuracy (5-fold mean) - type: recall value: 0.9763 name: Macro Recall (5-fold mean) - type: f1 value: 0.9756 name: Macro F1 (5-fold mean) --- # miimo-efficientat-target4 [EfficientAT](https://github.com/fschmid56/EfficientAT) `mn10_as` 를 4개 음향 이벤트로 파인튜닝한 모델. 2초 클립 단위 분류이고 엣지 디바이스(라즈베리파이) 배포를 염두에 뒀다. - **클래스**: `baby_cry`, `bicycle`, `glass_break`, `gunshot` - **백본**: `mn10_as` (MobileNetV3, AudioSet 사전학습) + MLP head - **입력**: 32,000 Hz mono, 2.0초 (64,000 샘플) → AugmentMelSTFT 128 mel - **학습 데이터**: [retrina0678/miimo-audio-dataset](https://huggingface.co/datasets/retrina0678/miimo-audio-dataset) - **체크포인트 크기**: 17MB ## 성능 (held-out test, 5-fold) | metric | mean | std | min | max | |---|---|---|---|---| | accuracy | **0.9774** | 0.0113 | 0.9617 | 0.9909 | | balanced accuracy | 0.9763 | 0.0113 | 0.9618 | 0.9903 | | macro precision | 0.9758 | 0.0123 | 0.9594 | 0.9906 | | macro recall | 0.9763 | 0.0113 | 0.9618 | 0.9903 | | macro F1 | 0.9756 | 0.0122 | 0.9592 | 0.9904 | ### 클래스별 recall (5-fold) | 클래스 | mean | std | 비고 | |---|---|---|---| | `bicycle` | 0.9980 | 0.0046 | | | `baby_cry` | 0.9861 | 0.0113 | | | `gunshot` | 0.9849 | 0.0070 | | | `glass_break` | **0.9362** | 0.0314 | ⚠️ 가장 약함 — 주로 `gunshot` 으로 오분류 | 전체 5-fold pooled confusion matrix에서 `glass_break` → `gunshot` 오분류가 36건으로 가장 큰 오차 원인이다. 파열음 계열이라 2초 창에서 혼동되는 것으로 보인다. ### 출처별 recall | 클래스 | 출처 | recall | n | |---|---|---|---| | baby_cry | AI Hub (증강) | 0.9744 | 585 | | baby_cry | ESC-50 (증강) | 1.0000 | 305 | | baby_cry | donateacry | 1.0000 | 190 | | bicycle | AI Hub (증강) | 0.9980 | 490 | | glass_break | AI Hub (증강) | 0.9362 | 580 | | gunshot | AI Hub (증강) | 0.9849 | 595 | ## 파일 구성 ``` best_model.pt 최종 체크포인트 (fold 2, best by macro_recall) config.json 학습 하이퍼파라미터 labels.json 클래스 순서 / label2id all_metrics.json fold별 전체 지표 kfold_summary.csv fold별 요약 recall_by_source.csv 출처별 recall report.md 상세 리포트 (혼동행렬 포함) fold_01..05/ fold별 best.pt + 예측·혼동행렬 ``` `best_model.pt` 는 dict이고 키는 다음과 같다: `model_state_dict`, `config`, `labels`, `label2id`, `id2label`, `fold`, `epoch`, `val_metrics` ## 사용법 EfficientAT 저장소가 필요하다. ```bash git clone https://github.com/fschmid56/EfficientAT pip install torch torchaudio huggingface_hub ``` ```python import sys, torch, torchaudio from huggingface_hub import hf_hub_download sys.path.insert(0, "EfficientAT") from models.mn.model import get_model as get_mn from models.preprocess import AugmentMelSTFT from helpers.utils import NAME_TO_WIDTH ckpt_path = hf_hub_download("retrina0678/miimo-efficientat-target4", "best_model.pt") ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=False) labels = ckpt["labels"] # ['baby_cry','bicycle','glass_break','gunshot'] model = get_mn(num_classes=len(labels), pretrained_name="mn10_as", width_mult=NAME_TO_WIDTH("mn10_as"), head_type="mlp") model.load_state_dict(ckpt["model_state_dict"]) model.eval() # 학습과 동일한 전처리 — freqm/timem 은 추론 시 0 으로 둔다 mel = AugmentMelSTFT(n_mels=128, sr=32000, win_length=800, hopsize=320, freqm=0, timem=0) mel.eval() wav, sr = torchaudio.load("clip.wav") if sr != 32000: wav = torchaudio.functional.resample(wav, sr, 32000) wav = wav.mean(0, keepdim=True)[:, :64000] # mono, 2초 with torch.no_grad(): logits = model(mel(wav).unsqueeze(1)) if isinstance(logits, (tuple, list)): logits = logits[0] probs = logits.flatten(1).softmax(-1)[0] for lbl, p in sorted(zip(labels, probs.tolist()), key=lambda x: -x[1]): print(f"{lbl:<12} {p:.4f}") ``` ## 학습 설정 | 항목 | 값 | |---|---| | 백본 | `mn10_as` (AudioSet 사전학습) | | head | `mlp` | | epochs / batch | 20 / 16 | | optimizer | lr 1e-4, weight decay 1e-4 | | freeze backbone | 앞 2 epoch | | CV | StratifiedGroupKFold 5-fold, test_size 0.2 | | group column | `group_id` (= `aug_`) | | selection metric | `macro_recall` | | class weight | balanced + weighted sampler | | seed | 42 | | AMP | on | **데이터 누수 방지**: 같은 원본 음원에서 나온 클립은 50% 오버랩 + 증강으로 서로 겹치므로, 클립이 아니라 `source_file` 단위(`group_id`)로 분할했다. ## 클래스 균형 최소 클래스(`bicycle` 3,747)에 맞춰 클래스당 3,747개로 downsample → 총 14,988 클립. ## 한계 - **2초 고정창**이라 그보다 긴 이벤트의 문맥은 못 본다. - **`glass_break` recall이 0.936**으로 가장 낮고 fold 간 편차(std 0.031)도 크다. `gunshot` 과의 혼동이 주 원인. - 학습 데이터가 **AI Hub 중심**이라 녹음 환경이 다른 실사용 환경에서는 성능이 떨어질 수 있다. `recall_by_source.csv` 참고. - 4개 클래스만 다루고, 그 외 소리는 **가장 가까운 클래스로 강제 분류**된다. 실사용 시 확률 임계값(threshold)을 두고 reject 처리하는 것을 권한다. ## 라이선스 ⚠️ **상업적 이용 불가.** 학습 데이터에 [ESC-50](https://github.com/karolpiczak/ESC-50)(**CC BY-NC 3.0**)과 AI Hub 제공 데이터(**재배포 제한**)가 포함되어 있다. 이 가중치는 해당 데이터에서 파생되었으므로 원 데이터의 제약을 그대로 승계한다. - 상업적 용도로는 사용할 수 없다. - 백본 `mn10_as` 자체의 라이선스는 [EfficientAT 저장소](https://github.com/fschmid56/EfficientAT)를 따른다. - 자세한 출처는 [데이터셋 카드](https://huggingface.co/datasets/retrina0678/miimo-audio-dataset)를 참고. ## 인용 ``` EfficientAT: F. Schmid, K. Koutini, G. Widmer. "Efficient Large-Scale Audio Tagging via Transformer-to-CNN Knowledge Distillation." ICASSP 2023. ESC-50: K. J. Piczak. "ESC: Dataset for Environmental Sound Classification." ACM MM 2015. ```