Whisper — 구조와 파인튜닝(Architecture & Fine-Tuning)

Whisper는 30초 창(window)을 사용하는 트랜스포머 인코더-디코더(transformer encoder-decoder)입니다. 68만 시간의 다국어 약지도(multilingual weakly-supervised) 오디오-텍스트 쌍(audio-text pair)으로 학습되었고, 하나의 아키텍처로 여러 과제를 수행하며 99개 언어를 견고하게 다룹니다. 2026년 기준 참조 자동 음성 인식 모델(reference ASR)입니다.

유형: Build 언어: Python 선수 강의: Phase 6 · 04 (ASR), Phase 5 · 10 (Attention), Phase 7 · 05 (Full Transformer) 예상 시간: 약 75분

학습 목표

  • Whisper의 30초 로그 멜 입력(log-mel input), 인코더-디코더 구조, 디코더 프롬프트(decoder prompt) 형식을 설명합니다.
  • 긴 오디오(long-form audio)를 청킹(chunking), 음성 활동 감지(VAD), 정렬(alignment)과 함께 처리해야 하는 이유를 이해합니다.
  • 미세조정(fine-tuning)이 필요한 도메인 이동(domain shift) 상황과 LoRA 미세조정 전략을 구분합니다.
  • Whisper 추론(inference)에서 환각(hallucination)을 줄이는 안전장치(guard)를 적용합니다.

문제

OpenAI가 2022년 9월 공개한 Whisper는 자동 음성 인식(ASR) 모델을 일종의 범용 상품(commodity)처럼 사용할 수 있게 만든 첫 모델이었습니다. 오디오를 붙여넣으면 텍스트가 나오고, 99개 언어를 지원하며, 잡음에 강하고, 노트북에서도 실행됩니다. 2024년에는 OpenAI가 Large-v3와 Turbo 변형(variant)을 공개했고, 2026년에는 팟캐스트 전사(podcast transcription), 음성 비서(voice assistant), YouTube 자막의 기본 기준선(default baseline)으로 쓰입니다.

하지만 Whisper를 언제까지나 블랙박스(black box) 파이프라인처럼 다룰 수는 없습니다. 기술 전문 용어(technical jargon), 화자 억양(speaker accent), 고유명사(proper noun), 짧은 클립(short clip), 침묵(silence) 같은 도메인 이동은 Whisper도 망가뜨립니다. 다음을 알아야 합니다.

  1. Whisper의 내부가 실제로 어떤 구조인지
  2. 청크 단위, 스트리밍(streaming), 긴 오디오(long-form audio)를 올바르게 넘기는 방법
  3. 언제 미세조정(fine-tune)을 해야 하고 어떻게 해야 하는지

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.Whisper는 디코더 프롬프트에 <|en|>이나 <|transcribe|> 같은 특수 토큰(special token)을 사용합니다. 이 설계가 하나의 모델로 여러 과제를 수행할 수 있게 하는 이유는 무엇인가요?

2.Whisper의 입력은 30초 로그-멜(log-mel) 윈도우(window)로 고정되어 있습니다. 30초보다 긴 오디오 클립에 이 설계가 어떤 문제를 만드나요?

0/2 답변 완료

개념

Whisper: one architecture, many tasks, steered by prompt audio encoder 30 s → 80 log-mel, 3000 fr conv stride-2 N × transformer blocks Large-v3: N=32 cross-attn text decoder SOT → <|en|> → <|transcribe|> → <|notimestamps|> → tokens → EOT N × transformer blocks (causal) Large: N=32 Turbo: N=4 → 8× faster 51,865-BPE softmax prompt-based task <|en|> <|transcribe|> → English transcript <|fr|> <|translate|> → FR speech → EN text <|ja|> <|transcribe|> → Japanese transcript no_timestamps / timestamps → word-level alignment on long-form = chunk 30 s + overlap 0–30 25–55 50–80 75–105 5 s stride overlap; VAD-gate silence to prevent hallucinations LoRA fine-tune (q_proj + v_proj, r=16) full-FT Turbo-809M → 809M trainable LoRA-r16 Turbo → 0.65M trainable LoRA-r16 Large-v3 → 5.2M trainable LoRA-r16 Medium → 3.1M trainable freeze encoder if <10 h; tune decoder only 2–20 h gets 2–5× WER drop in-domain

아키텍처(Architecture). 표준 트랜스포머 인코더-디코더 구조입니다.

  • 입력(Input): 30초 로그 멜 스펙트로그램(log-mel spectrogram), 80 멜 빈(mel bin), 10 ms 홉(hop), 3000 프레임(frame)입니다. 더 짧은 클립은 0으로 채우고(zero-padding), 더 긴 클립은 청크 단위로 자릅니다(chunking).
  • 인코더(Encoder): 스트라이드 2의 합성곱 다운샘플(conv-downsample, stride 2)과 N개의 트랜스포머 블록으로 구성됩니다. Large-v3 기준 32 레이어(layer), 1280 차원, 20 헤드(head)입니다.
  • 디코더(Decoder): 인과적 셀프 어텐션(causal self-attention)과 인코더 출력에 대한 교차 어텐션(cross-attention)을 가진 N개의 트랜스포머 블록입니다. 인코더와 같은 크기입니다.
  • 출력(Output): 51,865개 토큰 어휘(vocab) 위의 BPE(byte pair encoding) 토큰입니다.

Large-v3는 1.55B 파라미터(parameter)를 가집니다. Turbo는 디코더를 32 레이어에서 4 레이어로 줄여 지연시간(latency)을 8배 낮추고, 단어 오류율(WER) 손실은 1% 미만으로 유지합니다.

프롬프트 형식(prompt format). Whisper는 디코더 프롬프트 안의 특수 토큰(special token)으로 조종되는 멀티태스크 모델(multitask model)입니다.

<|startoftranscript|><|en|><|transcribe|><|notimestamps|> Hello world.<|endoftext|>
  • <|en|> — 언어 태그(language tag)입니다. 번역과 전사 동작을 강제로 정합니다.
  • <|transcribe|> 또는 <|translate|> — 어떤 언어 입력이든 영어 출력으로 번역할지, 원문 그대로 전사할지 정합니다.
  • <|notimestamps|> — 단어 수준 타임스탬프(timestamp)를 건너뜁니다. 더 빠릅니다.

이 프롬프트 덕분에 하나의 모델이 여러 과제를 수행합니다. <|en|><|fr|>로 바꾸면 프랑스어를 전사합니다.

30초 창(30-second window). 모든 것이 30초에 고정되어 있습니다. 긴 클립은 청크 단위로 잘라야 하고, 짧은 클립은 패딩됩니다. 이 윈도우는 기본적으로(native) 스트리밍을 지원하지 않습니다. 그래서 WhisperX, Whisper-Streaming, faster-whisper 같은 도구들이 존재합니다.

로그 멜 정규화(Log-mel normalization). (log_mel - mean) / std를 적용하며, 이 통계는 Whisper 자신의 학습 말뭉치(training corpus)에서 옵니다. librosa.feature.melspectrogram이 아니라 Whisper의 전처리(whisper.audio.log_mel_spectrogram)를 반드시 사용해야 합니다.

2026년 변형(Variants in 2026)

VariantParamsLatency (A100)WER (LibriSpeech-clean)
Tiny39M1x realtime5.4%
Base74M1x4.1%
Small244M1x3.0%
Medium769M1x2.7%
Large-v31.55B2x1.8%
Large-v3-turbo809M8x1.58%
Whisper-Streaming (2024)1.55Bstreaming2.0%

미세조정(Fine-tuning)

2026년 기준 표준 워크플로(workflow)는 다음과 같습니다.

  1. 목표 도메인(target-domain)의 오디오와 정렬된 전사문(aligned transcript)을 10~100시간 수집합니다.
  2. generate_with_loss 콜백(callback)과 함께 transformers.Seq2SeqTrainer를 실행합니다.
  3. 파라미터 효율적(parameter-efficient) 방식으로 어텐션 레이어의 q_proj, k_proj, v_proj에 LoRA를 적용하면 GPU 메모리를 4배 줄이면서도 WER 손실은 0.3 미만으로 유지할 수 있습니다.
  4. 데이터가 10시간 미만이면 인코더를 동결(freeze)합니다. 디코더만 조정합니다.
  5. Whisper 자신의 토크나이저(tokenizer)와 프롬프트 형식을 사용합니다. 토크나이저는 절대 바꾸지 않습니다.

커뮤니티 결과를 보면, 의료 받아쓰기(medical dictation) 20시간으로 Medium을 미세조정하면 의료 어휘(medical vocabulary)에 대한 WER이 12%에서 4.5%로 떨어질 수 있습니다. 아이슬란드어(Icelandic) 4시간으로 Turbo를 미세조정해 WER이 18%에서 6%로 떨어진 사례도 있습니다.

직접 만들기

Step 1: Whisper를 그대로 실행하기

import whisper
model = whisper.load_model("large-v3-turbo")
result = model.transcribe(
    "clip.wav",
    language="en",
    task="transcribe",
    temperature=0.0,
    condition_on_previous_text=False,  # 폭주하는 반복 생성을 막습니다
)
print(result["text"])
for seg in result["segments"]:
    print(f"[{seg['start']:.2f}{seg['end']:.2f}] {seg['text']}")

항상 덮어써야 하는 주요 기본값은 temperature=0.0, condition_on_previous_text=False, no_speech_threshold=0.6입니다. temperature=0.0은 샘플링 폴백 체인(sampling fallback chain; 0.0 → 0.2 → 0.4 ...)을 통제하고, condition_on_previous_text=False는 연쇄 환각(cascading hallucination)을 막으며, no_speech_threshold=0.6은 침묵 감지를 돕습니다.

Step 2: 청크 단위 긴 오디오 처리(chunked long-form)

# whisperx는 단어 수준 타임스탬프를 제공하는 2026년 기준 긴 오디오 처리 표준입니다
import whisperx
model = whisperx.load_model("large-v3-turbo", device="cuda", compute_type="float16")
segments = model.transcribe("1hour.mp3", batch_size=16, chunk_size=30)

WhisperX는 (1) Silero VAD 게이팅(gating), (2) wav2vec 2.0 기반 단어 수준 정렬(word-level alignment), (3) pyannote.audio 기반 화자 분리(diarization)를 추가합니다. 2026년 운영 환경(production) 전사의 주력 도구(workhorse)입니다.

Step 3: LoRA로 미세조정하기

from transformers import WhisperForConditionalGeneration, WhisperProcessor
from peft import LoraConfig, get_peft_model

model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-large-v3-turbo")
lora = LoraConfig(
    r=16, lora_alpha=32, target_modules=["q_proj", "v_proj"],
    lora_dropout=0.1, bias="none", task_type="SEQ_2_SEQ_LM",
)
model = get_peft_model(model, lora)
# model.print_trainable_parameters()  -> ~3M trainable / 809M total

그다음은 표준 Trainer 루프(loop)입니다. 1000 스텝마다 체크포인트(checkpoint)를 저장하고, 별도로 떼어둔 검증 세트(held-out set)에서 WER로 평가합니다.

Step 4: 각 레이어가 배우는 것 확인하기

# 디코딩 도중 교차 어텐션 가중치를 가져와 디코더가 어디에 주의를 두는지 확인합니다.
with torch.inference_mode():
    out = model.generate(
        input_features=features,
        return_dict_in_generate=True,
        output_attentions=True,
    )
# out.cross_attentions: layer × head × step × src_len

히트맵(heatmap)으로 시각화하면 디코더 스텝이 인코더 프레임을 훑으며 진행하는 대각 정렬(diagonal alignment)을 볼 수 있습니다. 이 대각선이 Whisper가 단어 타임스탬프를 이해하는 방식입니다.

사용하기

2026년 기준 스택은 다음처럼 고릅니다.

상황선택
일반 영어, 오프라인whisperx를 통한 Large-v3-turbo
모바일/엣지int8로 양자화(quantized)한 Whisper-Tiny 또는 Moonshine
다국어 긴 오디오whisperx와 화자 분리(diarization)를 사용하는 Large-v3
저자원 언어(low-resource language)Medium 또는 Turbo를 LoRA로 미세조정
스트리밍(2초 지연)Whisper-Streaming 또는 Parakeet-TDT
단어 수준 타임스탬프WhisperX(wav2vec 2.0 기반 강제 정렬(forced alignment))

faster-whisper(CTranslate2 백엔드)는 2026년 기준 가장 빠른 CPU+GPU 추론 런타임(runtime)입니다. 기본(vanilla) Whisper보다 4배 빠르면서도 출력은 동일합니다.

2026년에도 자주 마주치는 함정

  • 침묵에서 환각된 텍스트. Whisper는 자막 데이터(caption data)로 학습되어 "Thanks for watching!", "Subscribe!", 노래 가사 같은 문장을 만들 수 있습니다. 호출 전에 항상 VAD로 침묵 구간을 걸러냅니다.
  • condition_on_previous_text 연쇄. 한 번의 환각이 뒤따르는 윈도우를 오염시킵니다. 청크 사이의 유창성이 꼭 필요한 상황이 아니라면 False로 둡니다.
  • 짧은 클립 패딩. 2초짜리 클립을 30초로 패딩하면 뒷부분의 침묵(trailing silence)에서 환각이 일어날 수 있습니다. pad=False로 두거나 VAD로 차단합니다.
  • 잘못된 멜(mel) 통계. Whisper의 멜 대신 librosa 멜을 사용하면 거의 무작위에 가까운 출력이 나옵니다. 반드시 whisper.audio.log_mel_spectrogram을 사용합니다.

산출물 만들기

outputs/skill-whisper-tuner.md로 저장합니다. 주어진 도메인(domain)에 맞는 Whisper 미세조정 또는 추론 파이프라인(inference pipeline)을 설계하는 스킬(skill)입니다.

연습문제

  1. 쉬움. code/main.py를 실행합니다. Whisper 스타일 프롬프트를 토크나이징(tokenizing)하고, 디코딩 형태(decoded shape)의 예산을 계산하며, 10분 분량 클립의 청크 스케줄(chunk schedule)을 출력합니다.
  2. 중간. faster-whisper를 설치하고 10분짜리 팟캐스트(podcast)를 텍스트로 변환(transcribe)한 뒤, 사람이 작성한 전사문(human transcript)과 WER을 비교합니다. language="auto"와 강제 지정한 language="en"을 함께 비교해 봅니다.
  3. 어려움. HF datasets를 사용하여 Whisper가 어려워하는 언어(예: 우르두어(Urdu))를 고릅니다. 2시간 분량 데이터로 Medium을 LoRA 미세조정으로 2 에폭(epoch) 수행하고 WER 변화량(delta)을 보고합니다.

핵심 용어

용어흔한 설명실제 의미
30초 창(30-sec window)Whisper의 한계입력 길이의 단단한 상한입니다. 더 긴 오디오는 청크 단위로 잘라야 합니다.
SOT전사 시작(Start-of-transcript)`<
타임스탬프 토큰(Timestamp token)시간 정렬(temporal alignment)51k 어휘 안에 0.02초 오프셋마다 존재하는 특수 토큰입니다.
Turbo빠른 변형디코더가 4 레이어이며, 8배 빠르고 WER 회귀(regression)는 1% 미만입니다.
WhisperX긴 오디오용 래퍼(wrapper)VAD + Whisper + wav2vec 정렬 + 화자 분리의 결합입니다.
LoRA 미세조정효율적인 튜닝어텐션에 저차원 어댑터(low-rank adapter)를 추가하고 전체 파라미터의 약 0.3%만 학습합니다.
환각(Hallucination)조용한 실패(silent failure)Whisper가 잡음이나 침묵에서 유창한 영어를 생성하는 현상입니다.

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 1개

whisper-tuner

Design a Whisper fine-tune or inference pipeline for a given language, domain, and latency budget.

Skill

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.의료 받아쓰기(medical dictation)를 위해 Whisper를 미세조정(fine-tune)하는데 도메인 데이터가 15시간뿐입니다. 인코더와 디코더 중 어느 쪽을 동결(freeze)해야 하며, 그 이유는 무엇인가요?

2.LoRA로 Whisper를 미세조정할 때 q_proj와 v_proj에 저차원 어댑터(low-rank adapter)를 추가해 전체 파라미터의 약 0.3%만 학습합니다. 이것이 대부분의 팀에게 전체 미세조정(full fine-tuning)보다 실용적인 이유는 무엇인가요?

3.Whisper의 log_mel_spectrogram 함수 대신 librosa로 멜 스펙트로그램(mel spectrogram)을 계산했더니 출력 텍스트가 거의 무작위에 가깝습니다. 원인은 무엇인가요?

0/3 답변 완료

추가 문제 풀기

AI가 강의 내용을 바탕으로 새로운 문제를 생성합니다