오디오 분류(Audio Classification) — MFCC 기반 k-NN에서 AST와 BEATs까지
"개 짖음 vs 사이렌"부터 "이 언어가 무엇인가"까지 모두 오디오 분류(audio classification)입니다. 특징(feature)은 멜(mel)이고, 아키텍처(architecture)는 시대마다 바뀝니다. 평가 지표는 AUC, F1, 클래스별 재현율(per-class recall)로 남습니다.
유형: Build
언어: Python
선수 지식: Phase 6 · 02 (Spectrograms & Mel), Phase 3 · 06 (CNNs), Phase 5 · 08 (CNNs & RNNs for Text)
예상 시간: 약 75분
학습 목표
오디오 분류 문제를 log-mel -> model -> softmax 또는 다중 라벨 헤드(multi-label head) 흐름으로 정리합니다.
클래스 불균형(class imbalance), 도메인 이동(domain shift), 라벨 노이즈(label noise)가 실제 난이도라는 점을 이해합니다.
과제 유형에 맞는 평가 지표(metric)를 선택합니다.
문제
10초짜리 클립(clip)이 있습니다. 우리는 "이 소리는 무엇인가?"를 알고 싶습니다. 도시 소리(사이렌, 드릴, 개), 음성 명령(yes/no/stop), 언어 식별(language ID: en/es/ar), 화자 감정(speaker emotion: angry/neutral), 환경음(environmental sound: indoor/outdoor, babble)이 모두 오디오 분류입니다. 2026년 기준 기준선 아키텍처(baseline architecture)는 이미 성숙했습니다. 기본 흐름은 log-mel -> CNN or Transformer -> softmax입니다.
핵심 난이도는 신경망(network)이 아닙니다. 데이터(data)입니다. 오디오 데이터셋(audio dataset)은 클래스 불균형이 심하고, 깨끗한 데이터와 잡음 많은 데이터 사이의 도메인 이동이 강하며, 라벨 노이즈도 큽니다. 누가 "urban babble"과 "restaurant noise"를 구분했다고 믿을 수 있을까요? 문제의 80%는 CNN을 Transformer로 바꾸는 일이 아니라 큐레이션(curation), 증강(augmentation), 평가(evaluation)입니다.
사전 테스트
2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요
1.오디오 분류(audio classification)의 표준 파이프라인이 원시 파형(raw waveform)을 바로 넣지 않고 로그-멜(log-mel) -> 모델 -> 소프트맥스(softmax) 순서를 따르는 이유는 무엇인가요?
2.50개 클래스에 각 40개 클립(ESC-50)인 데이터셋과, 632개 클래스에 100,000:1 클래스 불균형(AudioSet)인 데이터셋이 있습니다. 불균형 데이터셋이 근본적으로 다른 학습 전략을 요구하는 이유는 무엇인가요?
0/2 답변 완료
개념
MFCC 기반 k-최근접 이웃(k-NN on MFCCs, 1990년대 기준선). 클립별 MFCC를 평탄화(flatten)하거나 풀링(pooling)하고, 라벨이 붙은 특징 저장소(labeled bank)와 코사인 유사도(cosine similarity)를 계산한 뒤 상위 K개 표본의 다수결(majority vote)을 반환합니다. Speech Commands, ESC-50처럼 깨끗하고 작은 데이터셋에서는 놀라울 정도로 강합니다. GPU 없이 실행됩니다.
로그 Mel 기반 2D CNN(2D CNN on log-mels, 2015-2019).(T, n_mels) 형태의 로그 Mel(log-mel)을 이미지(image)처럼 다룹니다. ResNet-18 또는 VGG 스타일 2D CNN을 적용하고, 시간축(time axis)에 전역 평균 풀링(global mean pool)을 적용한 뒤 클래스별 소프트맥스(softmax)를 붙입니다. 2026년에도 많은 Kaggle 경진대회에서 기준선으로 쓰입니다.
오디오 스펙트로그램 트랜스포머(Audio Spectrogram Transformer, AST, 2021-2024). 로그 Mel을 예를 들어 16x16 패치(patch)로 자르고, 위치 임베딩(position embedding)을 더한 뒤 ViT(Vision Transformer)에 넣습니다. 지도 학습(supervised learning) 기준 AudioSet에서 mAP 0.485를 기록한 강한 구조입니다.
BEATs와 WavLM-base(2024-2026). 수백만 시간의 오디오로 자기지도 사전학습(self-supervised pretraining)을 수행한 모델입니다. 원래 필요했을 지도 학습 데이터의 1-10%만으로도 과제에 맞게 미세조정(fine-tune)할 수 있습니다. 2026년 기준 비음성 오디오(non-speech audio)의 기본 출발점입니다. BEATs-iter3는 AudioSet에서 AST보다 1-2 mAP 높으면서도 약 1/4의 연산 자원(compute)만 사용합니다.
동결 백본으로 쓰는 Whisper 인코더(Whisper-encoder as a frozen backbone, 2024). Whisper의 인코더만 가져오고 디코더(decoder)는 버린 뒤 선형 분류기(linear classifier)를 붙입니다. 오디오 증강 없이도 언어 식별과 단순 이벤트 분류에서 거의 SOTA에 가까운 기준선이 됩니다. 일종의 "공짜 점심" 기준선입니다.
클래스 불균형이 진짜 문제입니다
ESC-50은 50개 클래스에 각 40개 클립이 있어 균형적이고 쉽습니다. UrbanSound8K는 10개 클래스지만 10:1 불균형이 있습니다. AudioSet은 632개 클래스와 100,000:1에 이르는 긴 꼬리(long tail)를 가집니다. 잘 작동하는 기법은 다음과 같습니다.
학습 중 균형 샘플링(balanced sampling)을 사용합니다. 평가는 균형 샘플링으로 하지 않습니다.
믹스업(Mixup): 두 클립과 두 라벨을 선형 보간하여 증강합니다.
스펙어그먼트(SpecAugment): 임의의 시간(time) 대역과 주파수(frequency) 대역을 마스킹(masking)합니다. 단순하지만 중요합니다.
defsummarize(mfcc_frames):
n = len(mfcc_frames[0])
mean = [sum(f[i] for f in mfcc_frames) / len(mfcc_frames) for i inrange(n)]
var = [
sum((f[i] - mean[i]) ** 2for f in mfcc_frames) / len(mfcc_frames) for i inrange(n)
]
return mean + var
단순하지만 강합니다. 시간축에 대한 평균(mean)과 분산(variance)을 이어 붙이면 13개 계수(coefficient)를 가진 MFCC에서 26차원 고정 임베딩(fixed embedding)을 만들 수 있습니다. 즉시 실행되며, ESC-50에서는 2017년 무렵까지도 최신 신경망 기준선을 이긴 사례가 있었습니다.
Step 3: k-NN
defcosine(a, b):
dot = sum(x * y for x, y inzip(a, b))
na = math.sqrt(sum(x * x for x in a)) or1e-12
nb = math.sqrt(sum(x * x for x in b)) or1e-12return dot / (na * nb)
defknn_classify(q, bank, labels, k=5):
sims = sorted(range(len(bank)), key=lambda i: -cosine(q, bank[i]))[:k]
votes = Counter(labels[i] for i in sims)
return votes.most_common(1)[0][0]