コンテンツへスキップ
チュートリアル19分で読めます

BirdNET の検出結果をスペクトログラム上で検証する

夜明けの合唱の録音に BirdNET-Analyzer を実行し、Potato ですべての検出を確認して、種ごとの適合率と修正済みの Raven セレクションテーブルを得ます。

Potato Team

ARU や AudioMoth の録音に BirdNET-Analyzer を実行している鳥類調査のチームは、このチュートリアルに従って、Potato 2.13.1 で人がすべての BirdNET の検出を確認し、その確認から種ごとの BirdNET の適合率を計算し、確認済みのボックスを Raven のセレクションテーブルとしてエクスポートできます。BirdNET は、録音の各 3 秒ウィンドウにおける各種の信頼度スコアを報告します。BirdNET のドキュメントは、スコアのカットオフを選ぶ前に検出を手作業で確認するよう利用者に求めており、その方法として Wood and Kahl (2024) を挙げています。実例では、すべての鳴き声に専門家のボックスが付いた、公開されている夜明けの合唱の 20 分間の録音を使います。したがって、このページが報告する適合率は、正解キーと照合できます。生物音響はすべてのインポートとエクスポートのオプションを説明しており、このページでは、BirdNET の表からエクスポートされた結果まで、一つのレビューを追います。

録音と専門家のボックス

例のデータは、ペンシルベニア州レクターの Powdermill Nature Reserve のもので、2018 年 4 月から 7 月にかけて AudioMoth レコーダーが夜明けの合唱を記録しました(Chronister et al., 2021)。このデータセットには、5 分ずつの WAV セグメントとして 385 分の音声があり、48 種について 16,052 個のボックスがあります。一人のアノテーターが Raven Pro でボックスを描き、二人目が種を再度同定し、三人目が不一致を解決しました。各セグメントのボックスは、セグメントにちなんだ名前の Raven のセレクションテーブルにあり、たとえば Recording_2_Segment_01.wav には Recording_2_Segment_01.Table.1.selections.txt があって、Species 列は、各種を四文字の標識コードで示します。データは Dryad で CC0 1.0 の下で公開されており、著者は論文を引用するよう求めています。

Dryad はファイルをブラウザのダウンロードで配信します。Zenodo のレコード 4656848 は、同じ四つのファイルを Dryad の DOI の下に列挙しており、コマンドラインからダウンロードできます。Zenodo の WAV ファイルは 44.1 kHz で、データセットの README は 32 kHz の録音を説明しています。Dryad のコピーに対する BirdNET のスコアは、下のスコアとわずかに異なる場合があります。このチュートリアルでは、wav_Files.zip(1.4 GB)と annotation_Files.zip の Zenodo のコピーを使い、2018 年 5 月 8 日の午前 5 時 32 分から行った Recording 2 の最初の四つのセグメントを取ります。この 20 分間には、13 種について 891 個の専門家のボックスがあります。

BirdNET-Analyzer の実行

BirdNET-Analyzer は PyPI からインストールでき、Python 3.11 以降が必要です。初回の実行では、約 224 MB のモデルをダウンロードします。四つの WAV ファイルを recordings/ というフォルダーに置き、そのフォルダーに対して BirdNET を実行します。

bash
pip install birdnet-analyzer==2.4.0
python -m birdnet_analyzer.analyze recordings/ --lat 40.16 --lon -79.27 --week 18 --min_conf 0.1

--lat、--lon、--week は、BirdNET の分布モデルが 5 月第 2 週に Powdermill で想定する 150 種に BirdNET を制限します。BirdNET は一年を 48 週、月ごとに 4 週に分けます。--min_conf 0.1 は、BirdNET のデフォルトの 0.25 を下回る、0.1 のスコアまでの検出を残します。下のインポートの手順がレビューのカットオフを設定し、スコアの低い行は BirdNET の表に残るため、後で BirdNET をもう一度実行せずに別のカットオフを試せます。-o がない場合、BirdNET は各録音の隣に Recording_2_Segment_01.BirdNET.selection.table.txt のようなファイルを一つずつ書き出します。四番目のクリップからの一つのウィンドウが、その形式を示します。

text
Selection	View	Channel	Begin Time (s)	End Time (s)	Low Freq (Hz)	High Freq (Hz)	Common Name	Species Code	Confidence	Begin Path	File Offset (s)
36	Spectrogram 1	1	39.0	42.0	0	15000	Wood Thrush	woothr	0.9909	recordings/Recording_2_Segment_04.wav	39.0
37	Spectrogram 1	1	39.0	42.0	0	15000	American Redstart	amered	0.9909	recordings/Recording_2_Segment_04.wav	39.0
38	Spectrogram 1	1	39.0	42.0	0	15000	Black-capped Chickadee	bkcchi	0.3593	recordings/Recording_2_Segment_04.wav	39.0

すべての行は、0 Hz から 15 kHz(BirdNET のデフォルトのバンドパスフィルターの上限)までの 3 秒のウィンドウです。BirdNET は、鳴き声が周波数のどこにあるかを測定せず、一つのウィンドウに複数の種が挙がることもあります。四つの表には、合計 1,097 行があります。

検出結果の Potato へのインポート

Potato をインストールし、カットオフ 0.5 でフォルダーをインポートします。

bash
pip install potato-annotation==2.13.1
potato import -i recordings/ -f birdnet --min-confidence 0.5 -o birdnet-review/
text
Imported 4 item(s), 1 question(s), 0 answer(s) from 0 annotator(s), and 621 model suggestion(s) on 4 item(s) from BirdNET-Analyzer output.
  left out: 476 detections below confidence 0.5
  warning: 476 detection(s) below --min-confidence 0.5 were left out
  wrote birdnet-review/data/recordings.jsonl
  wrote birdnet-review/media/Recording_2_Segment_01.wav
  ...
  wrote birdnet-review/config.yaml
  wrote birdnet-review/README.md
 
Run it:
  potato start birdnet-review/config.yaml -p 8000

各録音は一つの項目になり、録音の WAV ファイルは media/ にコピーされました。0.5 以上の 621 件の検出は、項目の predictions フィールドのボックスになりました。各ボックスは BirdNET のスコア、"source": "ai"、そして attributes の下の BirdNET の種コードを保持し、ボックスのラベルは BirdNET の Common Name です。

BirdNET が --min_conf を超えるものを何も見つけなかった録音には、信頼度 1.0 の nocall というラベルのプレースホルダー行が一行付きます。Potato 2.13.1 は、その行をインポートから除外します。Potato 2.12.1 は、その行を BirdNET のボックスとしてインポートし、nocall をラベルのリストに追加していたため、2.12.1 では、レビューでそれらのボックスを削除するか、インポートの前にその行を取り除いてください。この例の四つのクリップには、nocall の行はありません。

レビュー用の設定

インポートは、BirdNET が報告した十種をラベルとする一つの spectrogram_annotation スキームを持つ、動作する設定を書き出します。下の設定は、インポートの設定に三つの変更を加えます。一つ目はタスク名、二つ目は BirdNET のボックスの上限である max_freq: 15000 です。三つ目は、Powdermill の専門家が見つけたが BirdNET が報告しなかった三つの種を追加します。そうすれば、レビュアーは見逃された鳴き声にラベルを付けられます。ご自身の調査では、それらの追加の種を、サイトのリストから取ってください。この設定は完全なもので、2.12.1 で python -m potato.validate_cli config.yaml --strict を通ります。

yaml
annotation_task_name: BirdNET review, Powdermill May 8
task_dir: .
output_annotation_dir: annotation_output/
data_files:
  - data/recordings.jsonl
item_properties:
  id_key: id
  text_key: recording
user_config:
  allow_all_users: true
  users: []
instance_display:
  fields:
    - key: recording
      type: text
      label: Recording
pre_annotation:
  enabled: true
  field: predictions
  allow_modification: true
 
annotation_schemes:
  - annotation_type: spectrogram_annotation
    name: calls
    description: Check BirdNET's boxes, relabel or delete the wrong ones, and draw one box for each species BirdNET missed.
    source_field: audio_url
    max_freq: 15000
    labels:
      # The ten species BirdNET reported at 0.5 or above
      - American Redstart
      - Black-and-white Warbler
      - Black-capped Chickadee
      - Black-throated Green Warbler
      - Eastern Towhee
      - Kentucky Warbler
      - Louisiana Waterthrush
      - Ovenbird
      - Scarlet Tanager
      - Wood Thrush
      # Species on the site list that BirdNET did not report in these clips
      - Brown-headed Cowbird
      - Hooded Warbler
      - Tufted Titmouse

pre_annotation ブロックは、クリップを開いたときに、各クリップに BirdNET のボックスを描画します。最初の九つのラベルにはキー 1 から 9 が割り当てられ、残りはマウスで選びます。

ボックスのレビュー

プロジェクトフォルダーからサーバーを起動し、各レビュアーにユーザー名とパスワードで登録してもらいます。

bash
cd birdnet-review
potato start config.yaml -p 8000

誰かが始める前に、何を正しい検出と見なすかを決めてください。BirdNET は 3 秒のウィンドウにラベルを付けます。そのため、このチュートリアルの規則は、指定された種がウィンドウ内で鳴いていれば、そのボックスは正しい、というものです。レビュアーは、各ボックスにこの規則を、次の三つの方法のいずれかで適用します。

  • ボックスを変更せずに残すことで、ボックスを承認します。BirdNET のボックスは破線の縁を持ち、レビュアーがボックスを変更するまで、ラベルの隣にスコアが表示されます。
  • ウィンドウに別の種が含まれているボックスは、ボックスのラベルメニューでその種を選ぶことでラベルを付け替えます。ボックスは BirdNET のスコアと種コードを保持し、"edited": true が付きます。
  • ウィンドウに指定された種の鳴き声がないボックスは削除します。

次に、レビュアーが聞き取ったが BirdNET が報告しなかった各種について、最も明瞭な鳴き声の周りにボックスを一つ描きます。「Next」をクリックするとクリップが保存され、手を付けなかったクリップは、BirdNET のボックスがレビュアーの回答として保存されます。

スペクトログラム上のボックスからではなく、スペクトログラムの下のリストから作業してください。最初のクリップは 103 個のボックスで開き、BirdNET の高さ全体にわたる 3 秒のボックスは、5 分のクリップのスペクトログラム全体を覆います。リストの各行には、ラベルメニュー、ボックスの 3 秒を再生する「Play」ボタン、「Delete」ボタンがあります。これらのクリップには、空いているスペクトログラムは残っていません。Potato 2.13.1 では、選択されていない BirdNET のボックスの上でドラッグすると新しいボックスを描き、クリックでボックスを選択すると、その後のドラッグでボックスを動かします。見逃された鳴き声を描くには、ラベルバーで種を選び、鳴き声にわたってドラッグします。Potato 2.12.1 では、BirdNET のボックス上のドラッグは、代わりにそのボックスを動かしました。そのバージョンでは、Space でクリップを再生し、もう一度 Space で鳴き声のところで一時停止し、N で一時停止位置にボックスを追加します。矢印キーは選択したボックスを動かし、Shift と矢印キーでボックスのサイズを変えます。+ ボタンは、時間方向に最大 16 倍まで拡大します。

このページの裏付けとなったテスト実行

このページの数値は、Powdermill の専門家のボックスを正解キーとして使った、Potato 2.12.1 でのスクリプト化されたレビュアーによるものです。インポートと Raven エクスポートは Potato 2.13.1 で再実行しており、このページのその出力は 2.13.1 のものです。スクリプトは、アノテーションページが送るのと同じリクエストで各クリップを保存しました。BirdNET のボックスは、同じ種の専門家のボックスがそのボックスのウィンドウと少なくとも 0.1 秒重なる場合に承認されました。ウィンドウに、同じウィンドウで BirdNET が報告しなかったラベルリスト上の別の種の専門家のボックスがあればラベルが付け替えられ、それ以外は削除されました。専門家が見つけたがどの残ったボックスにも名前が挙がっていない各種について、スクリプトは専門家の最も長いボックスを描きました。621 個の BirdNET のボックスのうち、601 個が承認され、12 個のラベルが付け替えられ、8 個が削除され、見逃された種のために 7 個のボックスが描かれました。各ウィンドウを聞く人間は、ウィンドウの端にある鳴き声を、0.1 秒の規則とは異なって判断することがあります。

Raven セレクションテーブルのエクスポート

Raven エクスポートは、録音ごとに一つのセレクションテーブルを書き出します。

bash
python -m potato.export -c config.yaml -f raven -o export/

コマンドは export/Recording_2_Segment_01.selections.txt から Recording_2_Segment_04.selections.txt を、合計 620 個のボックスで書き出しました。各ファイルは録音にちなんだ名前で、Raven Pro または Raven Lite が、音声の隣にテーブルを開きます。ラベルは Annotation 列に入り、--option label_column=Species は列名を変更します。複数のレビュアーがいる場合は、Recording_2_Segment_04.alice.selections.txt のように、各ファイル名にレビュアーの名前が加わります。-f audacity_labels は、代わりに Audacity のラベルトラックを書き出します。

Potato 2.13.1 からは、Raven のテーブルが、各ボックスがレビューからどのように出てきたかを記録します。四番目のクリップのテーブルの 24 行目と 25 行目は、先に示した 39 秒から 42 秒のウィンドウに対応します。

text
Selection	View	Channel	Begin Time (s)	End Time (s)	Low Freq (Hz)	High Freq (Hz)	Annotation	Confidence	Box Source
24	Spectrogram 1	1	39	42	0	15000	Wood Thrush	0.9909	ai
25	Spectrogram 1	1	39	42	0	15000	Black-capped Chickadee	1	ai (edited)

BirdNET はそのウィンドウで American Redstart に 0.9909、Black-capped Chickadee に 0.3593 を与え、レビュアーは Redstart のボックスをコガラ(chickadee)に付け替えました。ラベルを付け替えられたボックスは信頼度 1 と Box Source の値 ai (edited) を受け取り、BirdNET が報告してレビュアーが残したボックスは BirdNET のスコアを ai として保持し、レビュアーが描いたボックスは信頼度 1 の human です。四つの表にわたって、620 個のボックスは、ai が 601、ai (edited) が 12、human が 7 に分かれます。Potato 2.12.1 には Box Source 列がなく、ラベルが付け替えられた行に Redstart のスコアを保持していたため、そのバージョンでは、下の JSONL エクスポートから編集を取得してください。

レビューからの種ごとの適合率

JSONL エクスポートは、すべてのボックスを、レビュアーが保存したまま、source、edited、BirdNET の種コードとともに保持します。

bash
python -m potato.export -c config.yaml -f jsonl -o export/

下のスクリプトは、レビューされた各ボックスについて、種コードによって BirdNET の元のラベルを調べ、各 BirdNET のボックスを、維持、ラベル付け替え、削除のいずれかとして数えます。適合率は、ある種についての BirdNET のボックスのうち、レビュアーが同じ種のまま維持した割合です。スクリプトは、クリップごとにレビュアーが一人であることを前提とします。スクリプトは birdnet-review/ で実行してください。

python
import collections
import json
 
# BirdNET's boxes as imported, and BirdNET's name for each species code
imported = collections.Counter()
name_of = {}
for line in open("data/recordings.jsonl"):
    item = json.loads(line)
    for box in item["predictions"]["calls"]:
        imported[box["label"]] += 1
        name_of[box["attributes"]["Species Code"]] = box["label"]
 
# The reviewed boxes, one record per clip and reviewer
kept = collections.Counter()
relabeled = collections.Counter()
drawn = collections.Counter()
for line in open("export/annotations.jsonl"):
    record = json.loads(line)
    for box in json.loads(record["labels"]["calls"]["_data"]):
        if box.get("source") == "human":
            drawn[box["label"]] += 1
            continue
        birdnet_label = name_of[box["attributes"]["Species Code"]]
        if box["label"] == birdnet_label:
            kept[birdnet_label] += 1
        else:
            relabeled[birdnet_label] += 1
 
print(f"{'species':30} {'BirdNET':>7} {'kept':>5} {'relab':>5} {'del':>4} {'prec':>5} {'drawn':>5}")
for species in sorted(set(imported) | set(drawn), key=lambda s: -imported[s]):
    n = imported[species]
    deleted = n - kept[species] - relabeled[species]
    precision = f"{kept[species] / n:.2f}" if n else "-"
    print(f"{species:30} {n:7} {kept[species]:5} {relabeled[species]:5} {deleted:4} {precision:>5} {drawn[species]:5}")
text
species                        BirdNET  kept relab  del  prec drawn
Wood Thrush                        389   386     2    1  0.99     0
American Redstart                   48    44     4    0  0.92     1
Louisiana Waterthrush               47    39     2    6  0.83     0
Black-throated Green Warbler        44    44     0    0  1.00     0
Scarlet Tanager                     34    31     2    1  0.91     0
Black-capped Chickadee              34    32     2    0  0.94     1
Kentucky Warbler                    12    12     0    0  1.00     1
Eastern Towhee                       5     5     0    0  1.00     0
Ovenbird                             4     4     0    0  1.00     1
Black-and-white Warbler              4     4     0    0  1.00     0
Tufted Titmouse                      0     0     0    0     -     1
Brown-headed Cowbird                 0     0     0    0     -     1
Hooded Warbler                       0     0     0    0     -     1

カットオフ 0.5 では、レビュアーは BirdNET の 621 個のボックスのうち 601 個を同じ種のまま維持し、適合率は 0.97 でした。Louisiana Waterthrush は適合率が 0.83 で最も低く、47 個の Louisiana Waterthrush のボックスのうち 6 個が削除されました。Wood Thrush は 621 個のボックスのうち 389 個を占めました。したがって、全体の適合率 0.97 は、主に Wood Thrush の指標であり、読むべきは種ごとの行です。Ovenbird の四つのうち一つのボックスが誤りであれば、Ovenbird の適合率は 1.00 から 0.75 に動いていたはずであり、ボックスが 12 個以下の種は、適合率に意味が出るまでにさらに多くのクリップが必要です。

他のカットオフでの適合率と見逃された鳴き声

Powdermill には、同定できるすべての鳴き声に専門家のボックスがあります。したがって、テスト実行での重なりの規則を使えば、二度目のレビューなしに、任意のカットオフで BirdNET の完全な表を採点できます。この表は、各スコアでの BirdNET の行を、四つのクリップの専門家のボックスと比較しています。

カットオフBirdNET のボックス正しいもの適合率
0.101,0977860.72
0.257706940.90
0.506216010.97
0.755155070.98
0.904394350.99

BirdNET のボックスのレビューは適合率を測定し、BirdNET が一度も報告しなかった鳴き声は測定できません。0.5 では、891 個の専門家のボックスのうち 687 個が、同じ種の正しい BirdNET ウィンドウに入ります。Eastern Towhee は専門家の 45 の鳴き声のうち 5 個、Ovenbird は 27 のうち 4 個、Black-capped Chickadee は 99 のうち 34 個が正しいウィンドウに入りました。Wood Thrush は 495 のうち 492 個でした。レビューで見逃された種ごとに一つのボックスを描くと、クリップごとの種の存在が分かり、見逃された鳴き声を数えるには、Powdermill のような完全な参照か、すべての鳴き声を描く人が必要です。これらの率は、一つの地点の 5 月のある朝の 20 分間によるものであり、別の地点、季節、レコーダーには、別の確認が必要です。

BirdNET の出力を確認するための他のツール

BirdNET-Analyzer の Review タブは、Wood と Kahl のワークフローを実装しています。Segments タブは各検出の音声を切り出し、Review タブでは、レビュアーが一つの種の各セグメントを陽性か陰性かで印を付けます。次にこのタブは、レビュアーの回答を BirdNET のスコアに対してロジスティック回帰し、カットオフを計算します。一人で種ごとのカットオフを選ぶなら、Review タブが最短の経路です。Raven Pro は Raven の Learning Detector を通じて BirdNET を実行し、大量の検出器のセレクションのための Selection Review インターフェースを備えており、Cornell Lab のストアは Raven Pro 1.6 を 50 から 100 ドルと記載しています。Cornell の Raven Workbench は無料でベータ版であり、Cornell は Raven Pro を Workbench のアプリに置き換える予定です。Wildlife Acoustics の Kaleidoscope Pro は、BirdNET の分類器を Kaleidoscope の機能に挙げています。Arbimon は Rainforest Connection の無料のホスト型プラットフォームで、Arbimon のヘルプセンターは、アップロードされた録音でのパターンマッチングと種の存在の検証を説明しています。

Potato は、複数のレビュアーがブラウザで確認を分担する場合、録音を自分のサーバーに置いたままにする場合、確認が、セグメントごとの「はい」か「いいえ」ではなく、ラベルの付け替えと見逃された鳴き声の描画を含む場合に適しています。カメラトラップと生物音響ツールの比較は、これらのツールを並べて比較しています。

BirdNET のレビューにおける Potato の限界

  • 検出器はありません。 Potato は BirdNET の表を読み込み、BirdNET は実行しません。BirdNET のモデルは CC BY-NC-SA 4.0 でライセンスされており、BirdNET の README は、教育と研究のすべての利用を非商用として扱っています。
  • スペクトログラムのボックスの一致度はありません。 Potato 2.13.1 は、spectrogram_annotation のボックスについて、レビュアー間の一致度を計算しません。すべてのクリップに二人目のレビュアーを置くには、二人のレビュアーによる BirdNET の設定のように、num_annotators_per_item: 2 を設定し、クリップレベルの質問を追加します。
  • 音の測定はありません。 Raven Pro と Raven Workbench は周波数、継続時間、エネルギーを測定し、Potato はボックスの辺だけを保存します。

次に読むもの

参考文献

  1. Chronister, L. M., Rhinehart, T. A., Place, A., & Kitzes, J. (2021). An annotated set of audio recordings of Eastern North American birds containing frequency, time, and species information. Ecology, 102(6). https://doi.org/10.1002/ecy.3329
  2. Kahl, S., Wood, C. M., Eibl, M., & Klinck, H. (2021). BirdNET, a deep learning solution for avian diversity monitoring. Ecological Informatics, 61, 101236. https://doi.org/10.1016/j.ecoinf.2021.101236
  3. Wood, C. M., & Kahl, S. (2024). Guidelines for appropriate use of BirdNET scores and other detector outputs. Journal of Ornithology, 165, 777-782. https://doi.org/10.1007/s10336-024-02144-5