Zettelkasten

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 느낌은…", 다른 실행은 "아닌가 아닌가 싶은 느낌도…"

원인 흐름

  1. 창 하나를 greedy(temperature 0)로 디코딩한다. 입력이 같으면 결과도 같다 (결정적)
  2. 결과가 이상하면 fallback이 작동한다. 이 판단도 입력이 같으면 결정적이다. faster-whisper 기본값은 compression_ratio_threshold=2.4(반복 의심), log_prob_threshold=-1.0(자신 없음)이다
  3. fallback은 temperature를 0.2 → 0.4 → … → 1.0으로 올리며 그 창을 무작위 샘플링으로 다시 뽑는다. (추론) 확인한 범위에서는 무작위가 끼어드는 곳이 여기뿐이다. 다른 비결정 요인(GPU 연산, 오디오 전달 방식 차이)을 배제하지는 못했다. faster-whisper 소스에서 샘플링은 sampling_topk: 0이고, 시드를 지정하는 코드는 찾지 못했다
  4. 이어받기가 켜져 있으면 달라진 텍스트가 다음 창의 힌트가 된다(문서에 나온 동작). (추론) 창 시작 위치도 앞 결과의 타임스탬프에 따라 바뀔 수 있다. 그러면 그 뒤의 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" 같은 엉뚱한 라틴 문자 환각이 거기서 나왔을 가능성이 있다(미검증)

참고