화자 인식과 검증

음성 인식(ASR)이 "무엇을 말했는가"를 묻는다면, 화자 인식(Speaker Recognition)은 "누가 말했는가"를 묻습니다. 수학적으로는 임베딩(embedding)과 코사인(cosine)이라는 비슷한 도구를 쓰지만, 실제 운영 환경의 모든 결정은 단 하나의 EER 숫자에 좌우됩니다.

유형: Build 언어: Python 선수 강의: Phase 6 · 02 (Spectrograms & Mel), Phase 5 · 22 (Embedding Models) 예상 시간: 약 45분

학습 목표

  • 검증(verification, 1:1), 식별(identification, 1:N), 개방형 인식(open-set recognition)을 구분합니다.
  • ECAPA-TDNN, WavLM-SV, x-vector의 역할을 이해합니다.
  • 코사인 유사도(cosine similarity), 임계값(threshold), 동일오류율(Equal Error Rate; EER)을 계산합니다.
  • 화자 분리(diarization) 파이프라인과 화자 분리 오류율(Diarization Error Rate; DER)을 설명합니다.

문제

사용자가 통과 문구(passphrase)를 말합니다. 이 사람이 본인이 주장하는 그 사람이 맞는지 확인하고 싶다면 검증(verification, 1:1)입니다. 등록 데이터베이스(enrollment bank) 안의 누구와 일치하는지 알고 싶다면 식별(identification, 1:N)입니다. 둘 다 아닐 수도 있습니다. 등록되지 않은 알 수 없는 화자(unknown speaker)가 들어올 수 있는 상황은 개방형(open-set)입니다.

2018년 이전에는 GMM-UBM + i-vector가 주로 쓰였습니다. EER 자체는 합리적이었지만 채널 변화(channel shift: 전화기 대 노트북)와 감정 변화에 취약했습니다. 2018-2022년에는 각도 마진(angular margin)으로 학습한 TDNN 백본(backbone) 기반 x-vector가 표준이었습니다. 2022년 이후로는 ECAPA-TDNN과 WavLM-large 임베딩이 주류가 되었습니다. 2026년 현재 이 분야는 세 가지 모델과 단 하나의 지표로 크게 정리되어 있습니다.

그 지표가 바로 동일오류율(Equal Error Rate; EER) 입니다. 오수락률(False Accept Rate)과 오거부율(False Reject Rate)이 같아지도록 결정 임계값(decision threshold)을 잡습니다. 두 곡선이 교차하는 지점이 EER입니다. 모든 논문, 모든 리더보드(leaderboard), 모든 조달(procurement) 평가에서 사용됩니다.

사전 테스트

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

1.화자 검증(verification, 1:1)과 화자 식별(identification, 1:N)의 핵심 차이점은 무엇이며, 시스템 설계에 왜 중요한가요?

2.동일오류율(EER; Equal Error Rate)은 화자 검증에서 가장 많이 보고되는 단일 지표입니다. 교차하는 두 곡선은 무엇을 나타내나요?

0/2 답변 완료

개념

enroll → embed → cosine → EER enrollment 3–5 clean clips > 3 s each, same channel embedder ECAPA / WavLM-SV 192-d or 256-d, L2-normalized anchor mean of enroll embeds single speaker vector test utterance 1 clip (> 2 s) channel-matched if possible embedder same model L2-normalize output score cosine(anchor, test) optional AS-norm for domain threshold accept / reject tune on dev set pick threshold at EER EER FA = FR FR FA low threshold → high FA; high threshold → high FR VoxCeleb1-O EER in 2026 ReDimNet (2024) 0.39% WavLM-SV large 0.42% Pyannote 3.1 0.65% ECAPA-TDNN 0.87% x-vector (classic) 3.10% start with ECAPA; move to WavLM if domain needs it

파이프라인. 등록(enrollment) 단계에서는 대상 화자의 5-30초 분량 오디오를 녹음하고 고정 차원 임베딩(fixed-dimension embedding)을 계산합니다. ECAPA-TDNN은 보통 192차원, WavLM-large는 보통 256차원입니다. 검증(verification) 단계에서는 시험 발화(test utterance)의 임베딩을 구한 뒤 코사인 유사도를 계산하고 임계값과 비교합니다.

ECAPA-TDNN (2020, 2026년에도 주류). Emphasized Channel Attention, Propagation and Aggregation - Time-Delay Neural Network의 약자입니다. 스퀴즈-여기(squeeze-excitation)가 들어간 1D 합성곱 블록(1D conv block), 다중 헤드 어텐션 풀링(multi-head attention pooling), 그리고 192차원으로 연결되는 선형 계층(linear layer)으로 구성됩니다. VoxCeleb 1+2(2,700명 화자, 110만 발화)에서 가산적 각도 마진 손실(Additive Angular Margin loss; AAM-softmax)로 학습합니다.

WavLM-SV (2022+). 사전학습된 WavLM-large 자기지도 학습(self-supervised learning; SSL) 백본을 AAM 손실로 미세조정(fine-tune)합니다. 품질은 더 높지만 더 느립니다. 모델 크기 기준 300MB 이상과 15MB의 차이를 떠올리면 됩니다.

x-vector (기준선). TDNN과 통계 풀링(statistics pooling) 구조로 이루어져 있습니다. 고전적이지만 CPU와 엣지(edge) 환경에서는 여전히 유용합니다.

AAM-softmax. 표준 소프트맥스(softmax)에 각도 공간(angular space)의 마진 m을 더한 형태입니다. 정답 클래스에 대해 cos(θ + m)을 적용해 클래스 사이의 각도 분리를 강제합니다. 일반적인 값은 m=0.2, 스케일은 s=30입니다.

점수 계산(Scoring)

  • 코사인(Cosine). 등록 임베딩과 시험 임베딩 사이의 코사인 유사도를 계산합니다. 임계값 기반으로 판정합니다.
  • PLDA (Probabilistic LDA). 같은 화자(same-speaker) 대 다른 화자(different-speaker)가 닫힌 형식의 가능도비(likelihood ratio)를 갖도록 임베딩을 잠재 공간(latent space)으로 사영합니다. 코사인 위에 결합하면 EER을 10-20% 더 낮출 수 있습니다. 2020년 이전에는 표준이었고, 지금은 폐쇄형(closed-set) 환경에서 주로 사용됩니다.
  • 점수 정규화(Score normalization). S-norm 또는 AS-norm은 각 점수를 위조 화자 코호트(imposter cohort)의 평균과 표준편차에 대해 정규화합니다. 영역 간(cross-domain) 평가에서는 필수적입니다.

알아두어야 할 2026년 수치

모델VoxCeleb1-O EER파라미터 수처리량(Throughput, A100)
x-vector (classic)3.10%5 M400x RT
ECAPA-TDNN0.87%15 M200x RT
WavLM-SV large0.42%316 M20x RT
Pyannote 3.1 segmentation + embedding0.65%6 M100x RT
ReDimNet (2024)0.39%24 M100x RT

화자 분리(Diarization)

화자 분리는 여러 화자가 섞인 클립에서 "누가 언제 말했는가"를 찾는 작업입니다. 파이프라인은 음성 활동 감지(VAD) -> 구간 분할(segment) -> 각 구간 임베딩(embed) -> 군집화(cluster) -> 경계 평활화(smooth boundaries) 순서입니다. 군집화에는 병합적 군집화(agglomerative clustering) 또는 스펙트럴 군집화(spectral clustering)가 쓰입니다. 현대적인 스택은 pyannote.audio 3.1이며, 화자 구간 분할, 임베딩, 군집화를 한 번의 호출 뒤에 묶어 제공합니다. 2026년 AMI 데이터셋 기준 최첨단(SOTA) DER은 약 15%로, 2022년의 23%에서 내려온 수치입니다.

직접 만들기

Step 1: MFCC 통계로 토이(toy) 임베딩 만들기

def embed_mfcc_stats(signal, sr):
    frames = featurize_mfcc(signal, sr, n_mfcc=13)
    mean = [sum(f[i] for f in frames) / len(frames) for i in range(13)]
    std = [
        math.sqrt(sum((f[i] - mean[i]) ** 2 for f in frames) / len(frames))
        for i in range(13)
    ]
    return mean + std  # 26차원

최첨단(SOTA)과는 거리가 멉니다. 어디까지나 교육용입니다. code/main.py는 합성 화자 데이터(synthetic speaker data)에서 이 방식을 개념 증명(proof-of-concept)으로 사용합니다.

Step 2: 코사인 유사도와 임계값

def cosine(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    na = math.sqrt(sum(x * x for x in a))
    nb = math.sqrt(sum(x * x for x in b))
    return dot / (na * nb) if na and nb else 0.0

def verify(enroll, test, threshold=0.75):
    return cosine(enroll, test) >= threshold

Step 3: 유사도 쌍에서 EER 구하기

def eer(same_scores, diff_scores):
    thresholds = sorted(set(same_scores + diff_scores))
    best = (1.0, 1.0, 0.0)  # (오수락률, 오거부율, 임계값)
    for t in thresholds:
        fr = sum(1 for s in same_scores if s < t) / len(same_scores)
        fa = sum(1 for s in diff_scores if s >= t) / len(diff_scores)
        if abs(fa - fr) < abs(best[0] - best[1]):
            best = (fa, fr, t)
    return (best[0] + best[1]) / 2, best[2]

반환값은 (eer, threshold_at_eer)입니다. 두 값 모두 함께 보고해야 합니다.

Step 4: SpeechBrain으로 운영 환경 구성하기

from speechbrain.pretrained import EncoderClassifier

clf = EncoderClassifier.from_hparams(source="speechbrain/spkrec-ecapa-voxceleb")

# 등록: 3-5개의 깨끗한 샘플 임베딩을 평균합니다
enroll = torch.stack([clf.encode_batch(load(x)) for x in enrollment_clips]).mean(0)
# 검증
score = clf.similarity(enroll, clf.encode_batch(load("test.wav"))).item()
verdict = score > 0.25   # ECAPA의 일반적 임계값; 실제 데이터에 맞춰 조정합니다

Step 5: pyannote로 화자 분리하기

from pyannote.audio import Pipeline

pipe = Pipeline.from_pretrained("pyannote/speaker-diarization-3.1")
diarization = pipe("meeting.wav", num_speakers=None)
for turn, _, speaker in diarization.itertracks(yield_label=True):
    print(f"{turn.start:.1f}{turn.end:.1f}  {speaker}")

사용하기

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

상황선택
폐쇄형(closed-set) 1:1 검증, 엣지 환경ECAPA-TDNN + 코사인 임계값
개방형(open-set) 검증, 클라우드WavLM-SV + AS-norm
화자 분리(diarization, 회의·팟캐스트)pyannote/speaker-diarization-3.1
위조 방지(anti-spoofing, 재생·딥페이크 감지)AASIST 또는 RawNet2
초소형 임베디드(KWS + 등록)Titanet-Small (NeMo)

흔한 함정

  • 채널 불일치(Channel mismatch). VoxCeleb(웹 동영상)으로 학습한 모델이 전화 통화 오디오에서도 그대로 동작하리라고 가정하면 안 됩니다. 반드시 목표 채널에서 평가합니다.
  • 짧은 발화. 시험 오디오가 3초보다 짧으면 EER이 급격히 나빠집니다.
  • 소음이 섞인 등록(Noise enrollment). 잡음이 섞인 등록 샘플 하나가 기준점(anchor)을 망칠 수 있습니다. 깨끗한 샘플 3개 이상을 모아 평균합니다.
  • 조건을 무시한 고정 임계값. 목표 도메인의 별도 검증용 집합(held-out dev set)에서 임계값을 반드시 조정합니다.
  • 정규화되지 않은 임베딩에 코사인 적용. 먼저 L2 정규화(L2-normalize)부터 수행합니다. 그렇지 않으면 벡터의 크기(magnitude)가 결과를 지배해 버립니다.

산출물 만들기

outputs/skill-speaker-verifier.md로 저장합니다. 모델 선택, 등록 프로토콜(enrollment protocol), 임계값 튜닝(threshold-tuning) 계획, 그리고 사기 방지(fraud safeguards) 장치를 결정하는 스킬입니다.

연습문제

  1. 쉬움. code/main.py를 실행합니다. 서로 다른 음색 프로파일(tone profile)을 가진 합성 "화자"들을 만들고, 등록한 뒤, 100쌍 시험 목록(100-pair trial list)에서 EER을 계산합니다.
  2. 중간. VoxCeleb1 발화 30개(화자 5명 × 각 6개)에 SpeechBrain ECAPA를 사용합니다. 코사인 점수와 PLDA 점수의 EER을 비교합니다.
  3. 어려움. pyannote.audio등록(enroll) -> 화자 분리(diarize) -> 검증(verify) 전체 파이프라인을 구축합니다. AMI 검증용 집합(dev set)에서 DER을 평가합니다.

핵심 용어

용어흔한 설명실제 의미
EER대표 지표오수락률(False Accept)과 오거부율(False Reject)이 같아지는 임계값에서의 오류율입니다.
Verification1:1"이 사람이 Alice가 맞는가?"를 묻습니다.
Identification1:N"누가 말하고 있는가?"를 묻습니다.
Open-set미지의 화자 가능시험 집합에 등록되지 않은 화자가 포함될 수 있다는 뜻입니다.
Enrollment등록화자의 기준 임베딩(reference embedding)을 계산하는 과정입니다.
AAM-softmax손실 함수가산적 각도 마진(additive angular margin)을 가진 소프트맥스로, 클러스터 분리를 강제합니다.
PLDA고전적 점수 계산확률적 LDA(Probabilistic LDA)로, 임베딩 위에서 가능도비(likelihood-ratio) 점수를 계산합니다.
DER화자 분리 지표화자 분리 오류율(Diarization Error Rate)이며, 누락(miss) + 오경보(false alarm) + 혼동(confusion)으로 구성됩니다.

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

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

speaker-verifier

Design a speaker verification or diarization pipeline with model choice, enrollment protocol, and threshold tuning.

Skill

확인 문제

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

1.VoxCeleb(웹 동영상)으로 화자 검증 모델을 학습하고 전화 뱅킹 인증에 배포했더니 EER이 0.9%에서 8%로 뛰었습니다. 가장 가능성 높은 원인은 무엇인가요?

2.AAM-softmax가 학습 중 표준 소프트맥스(softmax) 대신 cos(theta + m)을 사용하는 이유와, 각도 마진(angular margin) m이 학습된 임베딩(embedding)에 미치는 효과는 무엇인가요?

3.화자 분리(diarization) 파이프라인에서 VAD가 오디오를 구간 분할(segment)하고 각 구간을 임베딩한 뒤, 등록 데이터베이스에 대한 단순 최근접 이웃(nearest-neighbor) 탐색 대신 군집화(clustering, 예: 병합적(agglomerative) 또는 스펙트럴(spectral))를 사용하는 이유는 무엇인가요?

0/3 답변 완료

추가 문제 풀기

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