コンテンツへスキップ

アノテーションで音声・オーディオのモデルを学習する

修正したRTTMのターンで話者ダイアライゼーションを学習し、修正した書き起こしでWhisperをファインチューニングし、スペクトログラムに描いたボックスで鳴き声の検出器を学習します。

v2.14.0の新機能

このチュートリアルでは、Potatoでアノテーターが与える答えで、音声とオーディオのモデルを学習し、各モデルの出力を事前ラベルとしてアノテーターに戻します。このページは、すでにPotatoで書き起こし、話者のターン、動物の鳴き声を修正していて、その修正から学習するモデルがほしい研究の担当者に向けて書かれています。主な流れは、話者ダイアライゼーションのファイルをインポートし、アノテーターに話者のターンを修正してもらい、修正したターンでダイアライゼーションのモデルを学習し、修正をRTTMとしてエクスポートすることです。そのあと、短い3つのセクションで、修正した書き起こしのターンでWhisperをファインチューニングし、スペクトログラムで検出用のボックス検出器を学習し、波形で音イベントのタガーを学習します。学習のループ全般については、まずモデル学習の概要を読み、実行を一度も開始したことがなければ、最初のモデルを学習するを読んでください。

4つの音声トレーナー

各トレーナーは1種類のスキームから学習し、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.0)IoU 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として書き出します。RTTMは、1ターンにつき1行のSPEAKER行を持つテキスト形式で、dscoreとmd-evalがRTTMファイルを採点します。1行には、録音のファイル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ファイルと録音を1つのフォルダーに置き、各録音には、そのファイルIDに従った名前(meet000ならmeet000.wav)を付けて、フォルダーをインポートします。

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

インポーターは、録音ごとに1つの項目を作り、録音を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.

インポーターには、独自のフラグが3つあります。

  • **--rttm-scheme audio|tiered**は、ターンが入るスキームを選びます。既定のaudioは、ラベルが話者である、speakersという名前のaudio_annotationスキームを作ります。tieredは、speakerティアを1つ持つ、tiersという名前のtiered_annotationスキームを作ります。あとでターンごとに書き起こす研究には、tieredを使ってください。
  • **--speaker-map**は話者の名前を変え、マップに挙がっていない話者は、RTTMの名前のままです。マップは、ある名前がすべての録音で同じ人を指すときにだけ使ってください。ダイアライザーは話者にファイルごとに番号を付けるため、あるインタビューのSPEAKER_00と、次のインタビューのSPEAKER_00は、別の人かもしれません。
  • **--media-dir DIR**は、録音がRTTMファイルの隣にないときに、録音のあるフォルダーを指定します。

インポーターはSPEAKER行だけを読み、ほかの種類の行は、スキップしたものとして数えます。長さがゼロのターン、開始が負のターン、話者の名前がない(<NA>)ターン、2回挙がっているターンも、スキップされます。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は、ラベルが話者ではなく、音の種類を表すときに向いています。2人のインタビューでは、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の制限付きの重みなしで従い、WavLM(microsoft/wavlm-base-plus)を、最大max_speakers人の話者のためのフレーム分類器でファインチューニングします。モデルは、一度にchunk_s秒(既定では10秒)の音声を見ます。各チャンクの損失は、モデルの話者の出力と、チャンクの注釈付きの話者との、最良の対応付けのもとで計算されます。話者の名前は録音ごとに別の人を指すため、名前に対する分類器には一貫したターゲットがなく、この対応付けが重要です。次のパラメーターが、予測されるターンを形作ります。

パラメーター既定値効果
max_speakers31つのチャンク内で同時に話す話者の最大数。最大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のグリッド上で、予測された話者と注釈付きの話者との、最良の1対1の対応付けのもとで測ります。実行は、3種類の誤りも別々に報告します。3つの数値を読むと、モデルが発話を見逃しているのか、発話を作り出しているのか、話者を取り違えているのかがわかります。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の書き戻しのレポートが、件数を示します。テストプロジェクトでは、3本のvalの録音と4本の未修正の録音に対して、レポートは「Published 7 prediction(s) as prelabels.」となり、train分割の録音は、インポートしたRTTMのターンのままでした。

モデルは、各録音の中で、最初に話した順に話者に名前を付け、まずスキームのラベルを、そのあとにSPEAKER_00、SPEAKER_01などを使います。そのため、各録音で最初に聞こえる話者は、その人がゲストであるかどうかにかかわらず、このプロジェクトではGuestになります。モデルには、声で人を認識するための声の埋め込みがありません。2つのチャンクの重なりの間は黙っていて、あとでまた話す話者には、新しい名前が付きます。アノテーターには、ターンの端だけでなく、予測された各ターンの話者の名前を確認するように伝えてください。事前ラベルを信頼度の低いものから順にレビューし、修正が届くたびに再学習する方法は、ループ内のモデルが扱います。

修正したターンをRTTMとしてエクスポートする

segmentsエクスポートは、修正したターンを、アノテーターごとに1つのファイルとして、RTTMに書き戻します。

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

エクスポートは、1ターンにつき1行の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ティアを1つ持つ、tiersという名前のtiered_annotationスキームを書き出します。上と同じようにadmin_api_keyとmodel_trainingを追加し、writebackの下にschemas: [tiers]を入れると、設定はvalidate_cli --strictを通ります。diarizationは、話者ティアで学習し、予測したターンを同じティアに書き戻します。トレーナーは、名前がspeakerまたはspeakersであるティアを選びます。それがなければ、名前に「speaker」を含む1つのティアを選び、non-speakerという名前のティアは数えません。最後の代替は、ラベルを持つ唯一のティアです。2つのティアが該当するとき、またはラベルを持つティアが複数あって、どれも話者にちなんだ名前でないときは、実行は、そのティアの名前を挙げた警告とともに、録音を除外します。

修正した書き起こしで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は別のインストール(pip install whisperx)で、独自のPyTorchを持ち込みます。Potatoは、WhisperXがないとき、インポートできないとき、デバイスで動かないとき、モデルを読み込めないときに、faster-whisperに切り替え、要約には、各ファイルのエンジンが示されます。--asr-engine whisperxまたは--asr-engine faster-whisperは、切り替えなしで、1つのエンジンを実行します。--media-url-prefix /mediaは、各録音のパスを/media/<file>、つまりアノテーションのページが録音を再生するアドレスとして書き出します。

--asr-word-timestampsは、強制アラインメントで各単語の時刻を付け、WhisperXが文末でセグメントを分割できるようにします。テスト用の録音では、WhisperXは、このフラグがないと、10秒の録音につき1つのターンを返し、フラグがあると、録音につき3つのターンを返しました。ターンが短いほど、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]は、研究が書き起こしの誤りだけを扱うため、誤りのフラグを1つだけ残します。language: enは、学習と予測の言語を固定します。未設定のままだと、多言語のWhisperは、最大16個の学習ターンから、言語を1回検出し、サンプルしたターンの4分の3に満たない数しか一致しないときは、実行ログが警告します。

修正したターンを学習例にする

修正された各ターンは、1つの例で、ターンの開始と終了で録音から切り出したターンの音声と、修正されたテキストから成ります。誰も修正していないターンは、例になりません。スキームは、アノテーターが触れたターンだけを保存し、触れられていないターンは、正しいのか、読まれていないのか、わからないからです。修正のないフラグ付きのターンも、例になりません。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も報告し、モデルが手を加えなかったターンは、書き起こしのテキストとして採点されます。何かを公開する前に、2つの数値を比べてください。ファインチューニングされたモデルをアノテーターに見せる価値があるのは、モデルの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のフラグが付いた、提案された修正になり、提案の信頼度は、モデルのトークン確率の平均です。提案は修正ボックスを埋め、アノテーターは、各提案を残すか、編集するか、消します。

ファインチューニングしたモデルで新しい録音を書き起こす

既定では、実行は、実行の成果物の1つとして、モデルのint8のCTranslate2コピーであるct2/も書き出します。このコピーには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ピクセル、1秒あたり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個のボックスを予測し、余分なボックスの1つ1つが、アノテーターが削除するボックスを1つ増やします。

各データ行は、{"id": "site_00", "audio_url": "/media/site_00.wav"}のように、録音を指定します。検出器は、少なくとも1つのボックスがある録音でだけ学習します。ボックスのない録音は、誰も確認していない録音と見分けがつかないからです。検出器には、既定で、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本の合成の2人話者の録音のRTTMインポートから、12本の録音での修正、diarizationの実行、書き戻しを経て、segmentsエクスポートまで、最初から最後まで実行しました。この実行は、WavLMの代わりに1層のテスト用エンコーダーを使いました。したがって、実行のスコアは、実際の音声については何も示しません。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