본문으로 건너뛰기

내 어노테이션으로 음성과 오디오 모델 학습하기

수정된 RTTM 턴으로 화자 분리를 학습시키고, 수정된 전사로 Whisper를 파인튜닝하고, 스펙트로그램에 그린 박스로 울음소리 탐지기를 학습시킵니다.

v2.14.0의 새 기능

이 튜토리얼은 어노테이터가 Potato에서 준 답으로 음성과 오디오 모델을 학습시키고, 각 모델의 출력을 사전 레이블로 어노테이터에게 돌려보냅니다. 이 페이지는 Potato에서 이미 전사, 화자 턴, 동물 울음소리를 수정하고 있으며 그 수정에서 배우는 모델을 원하는 연구 책임자를 위해 쓰였습니다. 주된 경로는 화자 분리 파일을 가져오고, 어노테이터가 화자 턴을 수정하게 하고, 수정된 턴으로 화자 분리 모델을 학습시키고, 수정본을 RTTM으로 내보냅니다. 이어지는 더 짧은 세 섹션은 수정된 전사 턴으로 Whisper를 파인튜닝하고, 스펙트로그램에서 박스 탐지기를 학습시키고, 파형에서 소리 이벤트 태거를 학습시킵니다. 학습 루프 전반은 먼저 모델 학습 개요를 읽고, 실행을 한 번도 시작해 본 적이 없다면 첫 모델 학습시키기를 읽으십시오.

오디오 트레이너 네 가지

각 트레이너는 한 종류의 스키마에서 학습하며, Training 페이지는 스키마에 맞는 트레이너만 제공합니다.

트레이너학습 대상모델홀드아웃 점수설치
diarizationtiered_annotation 스키마의 화자 티어, 또는 레이블이 화자인 audio_annotation 스키마음성 인코더, 기본값은 WavLM화자 분리 정확도(1 − DER)potato-annotation[train-audio]
whisper-asrspeech_transcript 스키마에서 어노테이터가 수정한 턴Whisper, 기본값은 whisper-small단어 정확도(1 − WER)potato-annotation[train-audio]
torchvision-detect, ultralytics-detectspectrogram_annotation 스키마의 박스렌더링된 스펙트로그램에 대한 Faster R-CNN 또는 YOLO 탐지기IoU 0.5에서의 mAPpotato-annotation[train-vision], 또는 pip install ultralytics(AGPL-3.0)
hf-audio-taggeraudio_annotation 스키마의 레이블이 달린 세그먼트음성 인코더, 기본값은 wav2vec 2.0IoU 0.5에서의 세그먼트 F1potato-annotation[train-audio]

모든 오디오 트레이너는 soundfile이 여는 서버 디스크의 파일에서 녹음을 읽습니다. 예를 들어 WAV, FLAC, OGG이며, 최신 libsndfile이 있으면 MP3도 됩니다. /media/meet000.wav 같은 경로는 작업 디렉터리의 media/ 폴더에 있는 파일을 가리키며, 어노테이션 페이지는 이 폴더에서 녹음을 재생합니다. 녹음이 http(s) URL인 항목은 경고와 함께 학습에서 제외됩니다. 학습 전에 원격 녹음을 media/로 내려받으십시오. 트레이너 레퍼런스에 모든 파라미터가 나와 있습니다.

Potato를 실행하는 환경에 트레이너를 설치하십시오.

bash
pip install "potato-annotation[train-audio]"

[train-audio] extra는 PyTorch, transformers, soundfile을 설치합니다. 스펙트로그램 탐지기에는 대신 [train-vision]이 필요하며, 모든 텍스트, 이미지, 오디오, LLM 트레이너를 한꺼번에 설치하려면 pip install "potato-annotation[train]"을 쓰십시오. 패키지가 없는 트레이너는 Training 페이지에 "not installed"로 남으며, 패키지를 설치하는 명령도 함께 나옵니다.

RTTM 파일로 화자 분리 가져오기

화자 분리는 누가 말하고 있는지에 따라 녹음을 턴으로 나눕니다. pyannote와 NeMo는 화자 분리를 RTTM으로 쓰는데, 턴마다 SPEAKER 줄 하나가 있는 텍스트 형식이며 dscore와 md-eval이 RTTM 파일의 점수를 매깁니다. 한 줄에는 녹음의 파일 ID, 채널, 턴의 시작과 지속 시간(초), 화자가 들어 있습니다.

text
SPEAKER meet000 1 0.200 1.055 <NA> <NA> SPEAKER_01 <NA> <NA>
SPEAKER meet000 1 1.539 0.755 <NA> <NA> SPEAKER_00 <NA> <NA>

RTTM 파일과 녹음을 한 폴더에 두고, 각 녹음의 이름을 파일 ID에 맞추어(meet000이면 meet000.wav) 폴더를 가져오십시오.

bash
potato import -f rttm -i diarization/ -o interviews \
  --speaker-map "SPEAKER_00=Interviewer,SPEAKER_01=Guest"

가져오기는 녹음마다 항목 하나를 만들고, 녹음을 interviews/media/로 복사하고, config.yaml, data/diarization.jsonl, README를 씁니다. 이 페이지의 바탕이 된 녹음 16개짜리 시험 프로젝트에서 요약 줄은 다음과 같았습니다.

text
Imported 16 item(s), 1 question(s), 0 answer(s) from 0 annotator(s), and 16 model suggestion(s) on 16 item(s) from RTTM speaker diarization.

가져오기에는 고유한 플래그 세 개가 있습니다.

  • **--rttm-scheme audio|tiered**는 턴이 놓이는 스키마를 고릅니다. 기본값인 audio는 레이블이 화자인 speakers라는 audio_annotation 스키마를 만듭니다. tiered는 speaker 티어 하나를 가진 tiers라는 tiered_annotation 스키마를 만듭니다. 나중에 턴별로 전사하는 연구에는 tiered를 쓰십시오.
  • **--speaker-map**은 화자의 이름을 바꾸며, 맵에 없는 화자는 RTTM의 이름을 유지합니다. 이름이 모든 녹음에서 같은 사람을 뜻할 때만 맵을 쓰십시오. 화자 분리기는 파일 안에서 화자에 번호를 매기므로, 한 인터뷰의 SPEAKER_00과 다음 인터뷰의 SPEAKER_00은 다른 사람일 수 있습니다.
  • **--media-dir DIR**은 녹음이 RTTM 파일 옆에 있지 않을 때 녹음이 들어 있는 폴더를 지정합니다.

가져오기는 SPEAKER 줄만 읽고 다른 줄 유형은 건너뛴 것으로 셉니다. 길이가 0인 턴, 시작이 음수인 턴, 화자 이름이 없는(<NA>) 턴, 두 번 나열된 턴도 건너뜁니다. RTTM은 필드를 공백으로 구분하며, 가져오기는 공백이 들어 있는 화자 이름을 경고와 함께 공백까지만 읽습니다. 프로젝트 가져오기가 가져오기를 전부 다룹니다.

화자 분리 설정

생성된 설정은 가져온 턴을 이미 사전 어노테이션으로 보여 줍니다. config.yaml의 끝에 관리자 키와 model_training 블록을 추가하십시오. 아래 전체 파일은 python -m potato.validate_cli config.yaml --strict를 통과합니다.

yaml
port: 8000
annotation_task_name: diarization (imported)
task_dir: .
output_annotation_dir: annotation_output/
data_files:
- data/diarization.jsonl
item_properties:
  id_key: id
  text_key: text
user_config:
  allow_all_users: true
  users: []
site_dir: default
pre_annotation:
  enabled: true
  field: predictions
  allow_modification: true
annotation_schemes:
- annotation_type: audio_annotation
  name: speakers
  description: Check and correct who speaks when.
  source_field: audio_url
  mode: label
  labels:
  - name: Guest
  - name: Interviewer
admin_api_key: "change-me"
model_training:
  enabled: true

가져오기는 화자 레이블을 알파벳순으로 정렬하므로 Guest가 Interviewer보다 앞에 옵니다. 모델의 되쓰기는 기본적으로 항목 필드 predictions로 가며, 이는 가져오기의 pre_annotation 블록이 읽는 필드와 같습니다. 활성화된 pre_annotation 블록이 writeback.field와 다른 필드를 지정하면 학습 사전 레이블이 나타나지 않으므로 Potato는 시작을 거부합니다. 첫 실행의 홀드아웃 점수가 어노테이터에게 보여 줄 만해질 때까지는 설정에서 writeback을 빼 두십시오.

화자 턴 수정

프로젝트 폴더에서 서버를 시작하십시오.

bash
cd interviews
potato start config.yaml -p 8000

각 녹음은 화자 분리기의 턴이 파형 위에 그려진 채로 열립니다. 어노테이터는 턴의 가장자리를 옮기고, 턴의 화자를 바꾸고, 잡음인 턴을 삭제하고, 화자 분리기가 놓친 턴을 그립니다. 사전 어노테이션은 어노테이터가 항목을 저장해야 비로소 저장됩니다. 아무도 열지 않은 항목은 답이 없으므로 학습하지 않습니다. 화자 분리 어노테이션은 파형 조작과 키보드 단축키를 다룹니다.

diarization 트레이너는 train 분할에 어노테이션된 녹음이 4개 이상 필요하며, 기본 분할은 레이블이 달린 녹음의 약 70%를 train에 둡니다. 첫 실행 전에 녹음 8개 이상을 수정하십시오. 믿을 만한 홀드아웃 점수를 얻으려면 더 많이 수정하십시오.

화자 분리 모델 학습

http://localhost:8000/admin을 열고 관리자 키를 입력한 뒤 /admin/training으로 가십시오. 트레이너로 diarization을, 스키마로 speakers를 고르십시오. Training 페이지는 같은 스키마에 hf-audio-tagger도 제공합니다. hf-audio-tagger는 화자가 아니라 소리의 종류를 가리키는 레이블에 맞습니다. 두 사람이 나누는 인터뷰라면 Parameters 필드를 다음과 같이 설정하십시오.

json
{"max_speakers": 2}

Train now를 누르십시오. 같은 실행을 관리자 키로 스크립트에서 시작할 수도 있습니다.

bash
curl -X POST -H "X-API-Key: change-me" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs \
  -d '{"trainer": "diarization", "schemas": ["speakers"], "params": {"max_speakers": 2}}'

diarization은 pyannote의 분할 모델(Bredin and Laurent, 2021)의 방법을 pyannote나 pyannote의 제한된 가중치 없이 따르며, max_speakers명까지의 화자를 위한 프레임 분류기로 WavLM(microsoft/wavlm-base-plus)을 파인튜닝합니다. 모델은 한 번에 chunk_s초(기본값 10)의 오디오를 봅니다. 각 청크의 손실은 모델의 화자 출력을 청크의 어노테이션된 화자와 가장 잘 맞추는 대응 아래에서 계산됩니다. 화자 이름이 녹음마다 다른 사람을 가리키므로 이 대응이 중요하며, 이름에 대한 분류기에는 일관된 목표가 없을 것입니다. 아래 파라미터가 예측되는 턴의 모양을 결정합니다.

파라미터기본값효과
max_speakers3한 청크 안에서 동시에 활성인 최대 화자 수이며 최대 6입니다
chunk_s10모델이 한 번에 보는 초
threshold0.5화자가 말하는 것으로 치는 프레임 확률
min_gap_s, min_duration_s0.2, 0.2턴 안에서 이보다 짧은 간격은 메워지고, 이보다 짧은 턴은 버려집니다
model_namemicrosoft/wavlm-base-plusWavLM 또는 wav2vec 2.0 체크포인트나 로컬 경로입니다

원격 학습은 실행을 ssh로 GPU 서버에, 또는 SLURM 클러스터에 보냅니다.

화자 분리 점수 읽기

실행 페이지와 GET /admin/training/api/status는 홀드아웃 녹음에서의 실행 점수를 보고합니다. diarization의 대표 지표는 diarization_accuracy이며, 1에서 화자 분리 오류율(DER)을 뺀 값에 하한 0을 둔 것으로 정의됩니다. DER은 누락된 음성, 오경보, 화자 혼동을 더해 어노테이션된 음성으로 나눈 값입니다. Potato는 DER을 여유 구간 없이 10 ms 격자에서, 예측된 화자와 어노테이션된 화자의 가장 좋은 일대일 대응 아래에서 측정합니다. 실행은 세 가지 오류 유형도 따로 보고합니다. 세 숫자를 읽으면 모델이 음성을 놓치는지, 없는 음성을 만들어 내는지, 화자를 혼동하는지 알 수 있습니다. DER은 턴이 Interviewer로 불리는지 SPEAKER_01로 불리는지는 무시하고, 화자가 바뀌는 시점이 맞는지를 셉니다.

지표 이름에는 val_der나 test_diarization_accuracy처럼 분할이 들어 있습니다. 어노테이션된 턴이 있는데 예측이 없는 녹음은 틀린 것으로 칩니다. 따라서 모델은 어려운 녹음을 건너뛰어 점수를 올릴 수 없습니다.

예측된 턴 게시

홀드아웃 점수가 모델의 턴을 어노테이터에게 보여 줄 만하다고 뒷받침하면, 스키마를 writeback에 추가하고 서버를 재시작하십시오.

yaml
model_training:
  enabled: true
  writeback:
    schemas: [speakers]
    include_unlabeled: true

include_unlabeled: true는 아직 아무도 수정하지 않은 녹음도 예측합니다. 이 설정이 없으면 실행은 홀드아웃 val과 test 녹음에서만 예측합니다. 재시작 뒤에 다시 학습시키십시오. GET /admin/training/api/status의 되쓰기 보고서가 개수를 알려 줍니다. 시험 프로젝트에서 보고서는 val 녹음 3개와 수정되지 않은 녹음 4개에 대해 "Published 7 prediction(s) as prelabels."라고 읽혔고, train 분할의 녹음은 가져온 RTTM 턴을 유지했습니다.

모델은 각 녹음 안에서 처음 말한 순서대로 화자의 이름을 붙이며, 스키마의 레이블을 먼저 쓰고 그다음 SPEAKER_00, SPEAKER_01 등을 씁니다. 따라서 각 녹음에서 처음 들리는 화자는 그 사람이 손님이든 아니든 이 프로젝트에서 Guest입니다. 모델에는 사람을 알아볼 음성 임베딩이 없습니다. 두 청크가 겹치는 동안 침묵하다가 나중에 다시 말하는 화자는 새 이름을 받습니다. 어노테이터에게 턴의 가장자리만이 아니라 예측된 모든 턴의 화자 이름도 확인하라고 알리십시오. 루프 속의 모델은 신뢰도가 낮은 순서로 사전 레이블을 검토하는 방법과 수정이 들어오는 대로 재학습하는 방법을 다룹니다.

수정된 턴을 RTTM으로 내보내기

segments 내보내기는 수정된 턴을 어노테이터마다 파일 하나씩 RTTM으로 다시 씁니다.

bash
python -m potato.export --config config.yaml --format segments --output ./export/

내보내기는 턴마다 한 행인 export/segments.jsonl과 export/rttm/<annotator>.rttm을 씁니다. 각 RTTM 줄의 파일 ID는 확장자를 뺀 녹음의 이름입니다. 그러면 pyannote.metrics, dscore, md-eval이 화자 분리기의 원래 출력을 수정된 파일과 비교해 그대로 점수를 매길 수 있습니다. 시험 프로젝트에서 export/rttm/ana.rttm의 첫 줄들은 다음과 같았습니다.

text
SPEAKER meet000 1 0.200 1.055 <NA> <NA> Guest <NA> <NA>
SPEAKER meet000 1 1.539 0.755 <NA> <NA> Interviewer <NA> <NA>

화자 티어에서의 화자 분리

어노테이터가 같은 타임라인에 전사 티어 같은 다른 티어를 추가할 때는 --rttm-scheme tiered로 가져오십시오.

bash
potato import -f rttm -i diarization/ -o interviews --rttm-scheme tiered

가져오기는 speaker 티어 하나를 가진 tiers라는 tiered_annotation 스키마를 씁니다. 위와 같이 admin_api_key와 model_training을 추가하고 writeback 아래에 schemas: [tiers]를 두면 설정이 validate_cli --strict를 통과합니다. diarization은 화자 티어에서 학습하고 예측된 턴을 같은 티어에 되씁니다. 트레이너는 이름이 speaker 또는 speakers인 티어를 고릅니다. 그런 티어가 없으면 이름에 "speaker"가 들어 있는 유일한 티어를 고르며, non-speaker라는 티어는 해당하지 않습니다. 마지막 대체 수단은 레이블이 있는 유일한 티어입니다. 두 티어가 해당하거나, 레이블이 있는 티어가 여럿인데 화자를 위한 이름이 없으면, 실행은 티어 이름을 밝히는 경고와 함께 그 녹음들을 제외합니다.

수정된 전사로 Whisper 파인튜닝

whisper-asr은 어노테이터가 수정한 전사 턴으로 Whisper를 파인튜닝한 다음, 아무도 확인하지 않은 턴에 수정을 제안합니다. 이 섹션은 전사가 없는 녹음 폴더에서 시작합니다.

녹음 전사

녹음을 프로젝트의 media/ 폴더에 두고 서버 머신에서 녹음을 전사하십시오.

bash
pip install "potato-annotation[transcribe]"
potato transcripts media --transcribe --asr-model small.en --asr-word-timestamps \
  --media-url-prefix /media -o data/interviews.json

potato transcripts --transcribe는 WhisperX가 설치되어 있고 머신에서 작동하면 WhisperX를 실행하고, 그렇지 않으면 faster-whisper를 실행합니다. [transcribe] extra는 faster-whisper를 설치하며, WhisperX는 자체 PyTorch를 가져오는 별도 설치(pip install whisperx)입니다. Potato는 WhisperX가 없거나, 불러오지 못하거나, 장치에서 실행할 수 없거나, 모델을 불러오지 못하면 faster-whisper로 대체하며, 요약은 파일마다 사용한 엔진의 이름을 알려 줍니다. --asr-engine whisperx나 --asr-engine faster-whisper는 대체 없이 한 엔진만 실행합니다. --media-url-prefix /media는 각 녹음의 경로를 /media/<file>로 쓰며, 이는 어노테이션 페이지가 녹음을 재생하는 주소입니다.

--asr-word-timestamps는 강제 정렬로 각 단어의 시간을 매기고 WhisperX가 문장 끝에서 세그먼트를 나누게 합니다. 시험 녹음에서 WhisperX는 이 플래그가 없으면 10초 녹음당 턴 하나를, 이 플래그가 있으면 녹음당 턴 셋을 반환했습니다. 턴이 짧을수록 whisper-asr이 얻는 예시가 많아지며, Whisper의 입력 창은 30초입니다. 전사 형식과 Whisper 전사 어노테이션 방법은 전사 옵션, 화자 레이블, 기존 Whisper 출력을 다룹니다.

전사 설정

speech_transcript 스키마는 전사의 각 턴을 시간 범위와 수정 상자와 함께 보여 줍니다. 아래 전체 설정은 validate_cli --strict를 통과합니다.

yaml
annotation_task_name: "Interview transcript correction"
task_dir: .
output_annotation_dir: annotation_output/
data_files:
  - data/interviews.json
item_properties:
  id_key: id
  text_key: conversation
admin_api_key: "change-me"
annotation_schemes:
  - annotation_type: speech_transcript
    name: transcript
    description: "Play each turn and type the right text wherever the transcript is wrong."
    segments_key: conversation
    error_types: [asr_error]
model_training:
  enabled: true
  trainer_params:
    whisper-asr:
      model_name: openai/whisper-small
      language: en

segments_key: conversation은 potato transcripts가 전사를 쓰는 필드를 지정합니다. error_types: [asr_error]는 연구가 전사 오류만 다루므로 오류 플래그를 하나만 남깁니다. language: en은 학습과 예측의 언어를 고정합니다. 설정하지 않으면 다국어 Whisper는 학습 턴 최대 16개에서 언어를 한 번 감지하며, 표본 턴의 4분의 3 미만이 일치하면 실행 로그가 경고합니다.

수정된 턴이 학습 예시가 되는 방식

수정된 턴은 하나하나가 예시이며, 턴의 시작과 끝으로 녹음에서 잘라 낸 턴의 오디오와 수정된 텍스트로 이루어집니다. 아무도 수정하지 않은 턴은 예시가 아닌데, 스키마는 어노테이터가 건드린 턴만 저장하고 건드리지 않은 턴은 맞을 수도 있고 읽히지 않았을 수도 있기 때문입니다. 플래그는 달렸지만 수정이 없는 턴도 예시가 아닙니다. 30초보다 긴 턴은 경고와 함께 제외됩니다. 트레이너는 train 분할에 수정된 턴이 10개보다 적으면 실행을 거부합니다.

홀드아웃 점수는 수정된 턴에 대해 계산되므로, 여는 녹음에서는 틀린 턴을 모두 수정하십시오. 시험 녹음 12개에서 tiny.en을 쓴 WhisperX는 턴 36개 중 11개가 틀렸고, Ypsilanti를 "Epsilanti"로, Kerrytown을 "Cary Town"으로 쓰거나 턴의 시작에서 "I"를 빠뜨리는 오류가 있었습니다.

학습하고 전사와 비교하기

Training 페이지에서 whisper-asr과 transcript 스키마를 고르고 Train now를 누르십시오. 대표 점수는 word_accuracy이며, 수정된 턴에 대한 단어 오류율(WER)을 1에서 뺀 값입니다. 실행은 같은 턴에서의 원래 전사의 WER인 wer_asr도 보고하며, 모델이 그대로 둔 턴은 전사의 텍스트로 점수가 매겨집니다. 무엇이든 게시하기 전에 두 숫자를 비교하십시오. 파인튜닝된 모델은 모델의 WER이 wer_asr보다 낮을 때에만 어노테이터에게 보여 줄 가치가 있습니다.

이 페이지의 바탕이 된 시험 실행은 비교가 왜 중요한지 보여 줍니다. train 분할에 수정된 턴 8개, min_instances를 4로 낮추고, openai/whisper-tiny를 3 에포크 학습시킨 실행은 test WER 0.31을 기록했고 원래 전사는 0.19였습니다. 그 수준의 모델은 올바른 텍스트를 틀린 텍스트로 바꿀 것입니다. writeback을 추가하기 전에 수정을 더 모으거나 더 큰 체크포인트에서 시작하여 다시 학습시키십시오.

제안된 수정 게시

모델이 전사를 이기면 스키마를 writeback에 추가하고, 재시작한 뒤 다시 학습시키십시오.

yaml
model_training:
  enabled: true
  trainer_params:
    whisper-asr:
      model_name: openai/whisper-small
      language: en
  writeback:
    schemas: [transcript]
    include_unlabeled: true

예측은 모든 홀드아웃 녹음과 레이블 없는 녹음의 모든 턴을 전사합니다. 새 텍스트가 전사와 다른 턴은 asr_error로 플래그가 달린 제안된 수정이 되며, 모델의 평균 토큰 확률이 제안의 신뢰도입니다. 제안은 수정 상자를 채우고, 어노테이터는 제안마다 유지하거나, 편집하거나, 지웁니다.

파인튜닝된 모델로 새 녹음 전사하기

기본적으로 실행은 ct2/, 즉 모델의 int8 CTranslate2 복사본도 실행의 아티팩트에 씁니다. 이 복사본에는 ctranslate2 패키지가 필요하며, [transcribe] extra가 faster-whisper와 함께 설치합니다. 복사본의 경로를 potato transcripts에 넘기면 파인튜닝된 모델로 다음 녹음 묶음을 전사합니다.

bash
potato transcripts media/batch2 --transcribe \
  --asr-model annotation_output/training/runs/<run_id>/artifacts/ct2 \
  --media-url-prefix /media/batch2 -o data/batch2.json

WhisperX와 faster-whisper 둘 다 이 복사본을 불러옵니다. 실행 페이지는 각 실행의 ID를 보여 주고, 설정은 실행 폴더를 설명합니다.

스펙트로그램에서 울음소리 탐지

spectrogram_annotation 스키마에서 어노테이터는 울음소리 둘레에 시간-주파수 박스를 그립니다. torchvision-detect와 ultralytics-detect는 위젯이 스펙트로그램을 그리는 방식대로 각 녹음을 스펙트로그램 이미지로 렌더링하여 그 박스로 학습합니다. 렌더링은 주파수를 스키마의 min_freq에서 max_freq(max_freq가 설정되지 않으면 샘플링 레이트의 절반)까지의 선형 축에 두며, 높이는 256픽셀, 초당 100픽셀입니다. 각 박스는 이미지 박스가 됩니다. 시간과 주파수는 픽셀에 선형으로 대응됩니다. 따라서 이미지에서 박스의 IoU는 초와 헤르츠에서의 박스의 IoU와 같습니다. Audacity 레이블이나 BirdNET 행처럼 주파수 범위가 없는 박스는 전체 대역을 덮습니다. 41초 이상의 녹음은 가로 4,096픽셀 이상으로 렌더링되며 창으로 잘렸다가 다시 이어 붙입니다.

박스는 보통 가져오기에서 옵니다. potato import는 Potato의 생물음향학과 스펙트로그램에서 BirdNET 탐지 검증하기가 설명하듯 Raven 선택 표, Audacity 레이블 트랙, BirdNET-Analyzer 출력을 spectrogram_annotation 프로젝트로 읽습니다. 트레이너는 어노테이터가 그리거나 수정한 박스에서 학습하며, 탐지기는 BirdNET이나 Perch 임베딩이 아니라 스펙트로그램 픽셀을 읽습니다.

아래 설정은 validate_cli --strict를 통과하며 탐지기의 score_threshold를 0.5로 설정합니다.

yaml
annotation_task_name: "Dawn chorus calls"
task_dir: .
output_annotation_dir: annotation_output/
data_files:
  - data/recordings.jsonl
item_properties:
  id_key: id
  text_key: id
admin_api_key: "change-me"
annotation_schemes:
  - annotation_type: spectrogram_annotation
    name: calls
    description: "Draw a box around each call and pick its type."
    source_field: audio_url
    max_freq: 8000
    labels:
      - name: whistle
      - name: chirp
model_training:
  enabled: true
  trainer_params:
    torchvision-detect:
      score_threshold: 0.5
  writeback:
    schemas: [calls]
    include_unlabeled: true

16 kHz 녹음의 스펙트럼은 8 kHz에서 끝나며, max_freq: 8000은 전체 대역을 보여 줍니다. 기본 score_threshold인 0.25는 탐지기의 추측을 더 많이 유지합니다. 녹음 24개짜리 시험 프로젝트에서 기본 임계값의 torchvision-detect는 test 녹음에서 어노테이션된 울음소리 10개에 대해 박스 34개를 예측했고, 여분의 박스는 어노테이터가 삭제해야 할 박스가 하나 더 늘어난 것입니다.

각 데이터 행은 {"id": "site_00", "audio_url": "/media/site_00.wav"}처럼 녹음을 지정합니다. 탐지기는 박스가 하나 이상 있는 녹음에서만 학습하는데, 박스가 없는 녹음은 아무도 확인하지 않은 녹음과 똑같아 보이기 때문입니다. 탐지기에는 기본적으로 train 분할에 어노테이션된 녹음 20개가 필요합니다(min_instances).

torchvision-detect는 torchvision의 COCO 가중치에서 Faster R-CNN을 파인튜닝하고, ultralytics-detect는 YOLO 탐지기를 학습시킵니다. YOLO 탐지기가 학습과 실행이 더 빠릅니다. Ultralytics는 AGPL-3.0 라이선스이며, Ultralytics로 학습하고 배포한 모델에는 AGPL의 조건이 적용됩니다. Training 페이지는 ultralytics-detect 실행 전에 라이선스를 확인하도록 요청하고, API 실행에는 "accept_licence": true가 필요합니다. 두 탐지기 모두 렌더링된 스펙트로그램에서 IoU 0.5의 mAP로 점수가 매겨지며, 둘 다 예측된 박스를 모델 출력으로 표시한 start_s, end_s, low_hz, high_hz로 되써서 위젯을 미리 채웁니다. 비전 모델은 탐지기의 파라미터와 타일링을 다룹니다.

hf-audio-tagger로 소리 이벤트 태깅

hf-audio-tagger는 audio_annotation 스키마에서 음성, 음악, 울음소리, 기침 같은 레이블이 달린 시간 세그먼트를 학습합니다. 트레이너는 음성 인코더(기본값은 facebook/wav2vec2-base)를 파인튜닝하여 약 20 ms의 각 프레임에서 어떤 레이블이 활성인지 말하게 합니다. 각 레이블은 따로 점수가 매겨집니다. 따라서 서로 다른 레이블이 겹치는 세그먼트는 어노테이션된 그대로 학습됩니다. 예측된 세그먼트는 파형 위의 편집 가능한 영역으로 돌아갑니다. 아래 설정은 validate_cli --strict를 통과합니다.

yaml
annotation_task_name: "Dawn chorus events"
task_dir: .
output_annotation_dir: annotation_output/
data_files:
  - data/recordings.jsonl
item_properties:
  id_key: id
  text_key: id
admin_api_key: "change-me"
annotation_schemes:
  - annotation_type: audio_annotation
    name: events
    description: "Mark every call on the waveform and pick its type."
    source_field: audio_url
    mode: label
    labels:
      - name: whistle
      - name: chirp
model_training:
  enabled: true
  writeback:
    schemas: [events]
    include_unlabeled: true

태거는 어노테이터가 표시하지 않은 녹음의 모든 구간을 "여기에는 레이블 없음"으로 취급합니다. 이 가정은 어노테이터가 모든 이벤트를 표시하는 연구에 맞으며, 위 스키마의 설명이 "every call"을 요청합니다. 어노테이터가 일부 이벤트만 표시하는 곳에서는 모델이 나머지를 놓치도록 학습합니다. 대표 점수는 세그먼트 F1이며, 예측된 세그먼트가 같은 레이블의 어노테이션된 세그먼트와 IoU 0.5 이상으로 겹칠 때 일치로 칩니다. 실행은 일치한 세그먼트의 평균 IoU도 보고합니다. 트레이너에는 기본적으로 train 분할에 어노테이션된 녹음 10개가 필요합니다.

파라미터기본값효과
window_s10학습 및 예측 창당 오디오 초
threshold0.5레이블이 활성인 것으로 치는 프레임 확률
min_gap_s, min_duration_s0.1, 0.1세그먼트 안에서 이보다 짧은 간격은 메워지고, 이보다 짧은 세그먼트는 버려집니다
freeze_feature_encodertrue인코더의 합성곱 특징 레이어를 고정합니다

Training 페이지는 audio_annotation 스키마에 hf-audio-tagger와 diarization을 모두 제공합니다. 레이블이 소리의 종류를 가리키며 모든 녹음에서 같은 뜻일 때는 hf-audio-tagger를 고르십시오. 레이블이 녹음마다 이름이 달라지는 화자일 때는 diarization을 고르십시오.

이 페이지의 바탕이 된 실행

이 페이지의 명령과 설정은 아래에 이름을 밝힌 더 작은 모델로 노트북에서 Potato 2.14.0에 대해 실행되었습니다. 화자 분리 경로는 턴의 20%에 잘못된 화자를 준 합성 두 화자 녹음 16개의 RTTM 가져오기에서 시작하여, 녹음 12개의 수정, diarization 실행, 되쓰기를 거쳐 segments 내보내기까지 끝에서 끝까지 실행되었습니다. 이 실행은 WavLM 대신 한 층짜리 시험용 인코더를 썼습니다. 따라서 이 실행의 점수는 실제 음성에 대해 아무것도 말해 주지 않습니다. Whisper 섹션은 합성된 음성의 녹음 12개를 썼으며, tiny.en의 WhisperX로 전사하고 openai/whisper-tiny에서 파인튜닝했습니다. 스펙트로그램과 태거 섹션은 3 kHz와 6 kHz 톤의 합성 녹음 24개를 썼습니다. 모든 설정 블록은 python -m potato.validate_cli --strict를 통과합니다.

더 읽어보기

참고문헌

  • Bain, M., Huh, J., Han, T., and Zisserman, A. (2023). WhisperX: Time-Accurate Speech Transcription of Long-Form Audio. Interspeech 2023, 4489–4493. doi:10.21437/Interspeech.2023-78
  • Bredin, H., and Laurent, A. (2021). End-To-End Speaker Segmentation for Overlap-Aware Resegmentation. Interspeech 2021, 3111–3115. doi:10.21437/Interspeech.2021-560
  • Chen, S., Wang, C., Chen, Z., Wu, Y., Liu, S., Chen, Z., Li, J., Kanda, N., Yoshioka, T., Xiao, X., Wu, J., Zhou, L., Ren, S., Qian, Y., Qian, Y., Wu, J., Zeng, M., Yu, X., and Wei, F. (2022). WavLM: Large-Scale Self-Supervised Pre-Training for Full Stack Speech Processing. IEEE Journal of Selected Topics in Signal Processing. doi:10.1109/JSTSP.2022.3188113
  • Radford, A., Kim, J. W., Xu, T., Brockman, G., McLeavey, C., and Sutskever, I. (2023). Robust Speech Recognition via Large-Scale Weak Supervision. Proceedings of the 40th International Conference on Machine Learning, PMLR 202, 28492–28518. proceedings.mlr.press