Mel-skala och MFCC
Kunna beräkna mel-spektrogram och förklara varför skalan efterliknar hörseln.
Förkunskaper
- EFourier och spektrogramkrävs
Intuition
Hörseln är inte linjär i frekvens. Skillnaden mellan 100 och 200 Hz hörs som ett stort steg; skillnaden mellan 8 000 och 8 100 Hz hör du knappt alls. Båda är 100 Hz.
Mel-skalan är en omskalning som gör lika stora steg låta lika stora. Den är nästan linjär under 1 000 Hz och logaritmisk över.
Ett mel-spektrogram byggs i tre steg:
- STFT → magnitudspektrogram (201 frekvensbin vid 25 ms fönster och 16 kHz).
- Summera ihop binen med triangelfilter som är smala i botten och breda i toppen — typiskt 80 filter.
- Ta logaritmen.
Resultatet är kompaktare (80 i stället för 201 kanaler), mer perceptuellt relevant, och det som Whisper och nästan alla moderna ljudmodeller tar som indata.
Formellt
Mel-omvandlingen (den vanligaste varianten):
Skalan är kalibrerad så att 1 000 Hz ≈ 1 000 mel.
Filterbanken. Lägg punkter jämnt fördelade på mel-skalan mellan och , konvertera tillbaka till hertz, och bygg triangelfilter där filter har sitt stöd mellan punkt och med toppen i . Jämn fördelning i mel blir alltså ojämn i hertz: filtren är smala i botten och breda i toppen. Det är hela poängen.
MFCC går ett steg till: ta DCT av log-mel-energierna och behåll de 13 första koefficienterna. DCT:n dekorrelerar kanalerna, vilket var nödvändigt för de gaussiska blandningsmodeller som dominerade fram till cirka 2012.
När behövs vad?
| Metod | Kanaler | Används till |
|---|---|---|
| Log-mel-spektrogram | 40–128 | neurala nät — standard i dag |
| MFCC | 13 (+Δ, ΔΔ) | klassisk ML, små dataset, mycket begränsad hårdvara |
| Rå vågform | — | wav2vec 2.0 och liknande självövervakade modeller |
Praktisk regel: använd log-mel om du tränar ett neuralt nät. MFCC är inte fel, men DCT:n kastar bort information som ett CNN hellre hade fått använda själv. Faltningsnät klarar korrelerade kanaler utmärkt — de är byggda för det.
Kod
import numpy as np
def hz2mel(f): return 2595.0 * np.log10(1.0 + np.asarray(f, float) / 700.0)
def mel2hz(m): return 700.0 * (10.0 ** (np.asarray(m, float) / 2595.0) - 1.0)
def mel_filterbank(n_filter=80, n_fft=400, fs=16000, f_min=0.0, f_max=8000.0):
punkter = mel2hz(np.linspace(hz2mel(f_min), hz2mel(f_max), n_filter + 2))
bins = np.floor((n_fft + 1) * punkter / fs).astype(int)
fb = np.zeros((n_filter, n_fft // 2 + 1))
for m in range(n_filter):
v, t, h = bins[m], bins[m + 1], bins[m + 2]
for k in range(v, t):
fb[m, k] = (k - v) / max(t - v, 1)
for k in range(t, h):
fb[m, k] = (h - k) / max(h - t, 1)
return fb
fb = mel_filterbank()
bredd = fb.sum(axis=1)
print(round(bredd[0], 1), round(bredd[-1], 1)) # ~1.0 ~10.5 — filtren blir bredare uppåt
# log-mel-spektrogram ur ett magnitudspektrogram S (ramar × bin)
mel = np.log(fb @ S.T + 1e-10).T # (ramar, 80)
Raden bredd[0] mot bredd[-1] visar det centrala: det översta filtret täcker tio gånger fler frekvensbin än det nedersta. Modellen får därmed hög upplösning där örat har det, och grov upplösning där örat inte bryr sig.
Behärskning innebär
- Omvandlar mellan hertz och mel
- Bygger en mel-filterbank
- Vet när MFCC behövs och när mel-spektrogram räcker
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- librosa — dokumentation (ISC) — ISC
- Wikipedia — Mel scale (CC BY-SA 4.0) — CC BY-SA 4.0
- Dive into Deep Learning (CC BY-SA 4.0) — CC BY-SA 4.0