faster-whisper 결과가 실행마다 달라지는 건 temperature fallback 샘플링이 이전 텍스트 이어받기로 번지는 탓으로 보인다
·수정 1회
요약
- 같은 오디오와 같은 디코딩 설정으로 faster-whisper를 두 번 돌렸는데 결과가 달랐다. 갈라진 지점 19곳 중 17곳은 그 구간이나 바로 앞뒤 구간에서 temperature fallback이 돌았다
- fallback은 무작위 샘플링으로 그 창을 다시 뽑는다. (추론) 이어받기(
condition_on_previous_text=True)가 켜져 있으면 그 차이가 다음 창의 힌트로 들어가서 뒤로 번지는 것으로 보인다. 상관관계와 반복 측정에서 나온 정황 근거다 - 이어받기를 끄면 4파일 × 3회 반복에서 결과가 글자 하나까지 매번 같았다
본문
관측: 같은 설정인데 결과가 갈라진다
- 조건: large-v3, GPU L4 fp16, greedy + VAD, 기본 설정(이어받기 켬, fallback 켬), kcsc 한국어 대화 22파일
- 디코딩 설정은 같게 두고 두 번 돌려서 비교했다. 다만 두 번째 실행은 파일 경로 대신 미리 디코딩한 오디오 배열을 넘겼고 구간별 통계를 추가로 저장했다. 교란 변수를 완전히 없앤 대조는 아니다
- 3파일은 완전히 같았다. 세 파일 모두 fallback이 돈 구간이 0개였다
- 19파일은 중간까지 글자 하나까지 같다가 어느 지점에서 갈라졌다. 갈라진 지점 19곳 중 17곳이 fallback이 돈 구간(바로 앞뒤 구간 포함)이었다. 전체 구간 중 fallback 구간 비율은 13.3%뿐이다
- 갈라진 뒤 텍스트가 달라졌고 파일 CER이 최대 0.05 차이 났다. 끝까지 다시 합쳐지지 않았는지는 확인하지 않았다
- 예: 한 실행은 "아닌가 breakfastHour 느낌은…", 다른 실행은 "아닌가 아닌가 싶은 느낌도…"
원인 흐름
- 창 하나를 greedy(temperature 0)로 디코딩한다. 입력이 같으면 결과도 같다 (결정적)
- 결과가 이상하면 fallback이 작동한다. 이 판단도 입력이 같으면 결정적이다. faster-whisper 기본값은
compression_ratio_threshold=2.4(반복 의심),log_prob_threshold=-1.0(자신 없음)이다 - fallback은 temperature를 0.2 → 0.4 → … → 1.0으로 올리며 그 창을 무작위 샘플링으로 다시 뽑는다. (추론) 확인한 범위에서는 무작위가 끼어드는 곳이 여기뿐이다. 다른 비결정 요인(GPU 연산, 오디오 전달 방식 차이)을 배제하지는 못했다. faster-whisper 소스에서 샘플링은
sampling_topk: 0이고, 시드를 지정하는 코드는 찾지 못했다 - 이어받기가 켜져 있으면 달라진 텍스트가 다음 창의 힌트가 된다(문서에 나온 동작). (추론) 창 시작 위치도 앞 결과의 타임스탬프에 따라 바뀔 수 있다. 그러면 그 뒤의 fallback 판단(2번)도 실행마다 달라져서 계속 갈라질 수 있다
- 참고:
prompt_reset_on_temperature=0.5가 기본값이라 temperature가 0.5를 넘으면 힌트를 비운다. 그래도 창 시작 위치가 달라지는 건 막지 못한다(추론)
- 참고:
이어받기를 끄면 결정적이 된다
- 반복 측정 결과 (4파일 × 3회, VAD 켬, GPU):
| 조건 | 3회 결과가 서로 다른 조합 | 실행 간 CER 편차 |
|---|---|---|
| 이어받기 켬 + greedy | 4조합 중 3개 | 0.017 |
| 이어받기 켬 + beam5 | 4조합 중 4개 | 0.052 |
| 이어받기 끔 + greedy | 0개 | 0 |
| 이어받기 끔 + beam5 | 0개 | 0 |
- 이어받기를 켠 greedy 중 유일하게 3회가 같았던 파일(A0055_S0006_0_G0110)은 앞 분석에서 fallback이 0번이었던 파일이다
- (추론) 이어받기를 끈 실행에서 3회가 완전히 같았다는 건 fallback이 아예 안 돌았다는 뜻으로 본다. 돌았다면 무작위 샘플링이라 같은 결과가 나오기 어렵다. 이유는 이렇게 본다: 루프는 주로 오염된 이전 텍스트를 힌트로 받아서 생기는데, 이어받기를 끄면 창마다 깨끗하게 시작하니 fallback 조건에 덜 걸린다. 반복 측정에서는 창별 fallback 여부를 기록하지 않아서 직접 확인하지는 못했다
- faster-whisper 문서의 설명:
condition_on_previous_text: If True, the previous output of the model is provided as a prompt for the next window; disabling may make the text inconsistent across windows, but the model becomes less prone to getting stuck in a failure loop, such as repetition looping or timestamps going out of sync.
왜 중요한가
- 서비스에서 같은 파일을 다시 돌렸는데 다른 결과가 나오면 고객 문의를 재현할 수 없다
- 같은 설정을 다시 돌리기만 해도 파일 CER이 최대 0.05 흔들렸다. 그래서 (추론) greedy와 beam5를 파일 몇 개로 비교하면 fallback 운 때문에 번갈아 이기는 것처럼 보일 수 있다. 비교 실험을 하기 전에 결정성부터 확보해야 한다
- (추론) fallback이 temperature 0.8~1.0까지 올라간 구간이 있었다. "paradox vai implemented" 같은 엉뚱한 라틴 문자 환각이 거기서 나왔을 가능성이 있다(미검증)
참고
- 정답 전사가 없어도 변형 간 이탈 패턴으로 오디오 열화를 판별할 수 있다 — 실행마다 결과가 달라지는 현상의 원인
- WhisperX는 VAD로 청크 의존성을 제거해 배치 추론을 가능하게 한다
- faster-whisper BatchedInferencePipeline은 production blocker급 미해결 이슈가 다수 있다
- Whisper 음성 처리와 최적화 방식
- faster-whisper 1.2.1
transcribe.py(기본값 temperature [0.0, 0.2, 0.4, 0.6, 0.8, 1.0], compression_ratio_threshold 2.4, log_prob_threshold -1.0, prompt_reset_on_temperature 0.5)