본문으로 건너뛰기
튜토리얼22분 분량

스펙트로그램에서 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의 표에서 내보낸 결과까지 검토 하나를 따라갑니다.

녹음과 전문가 상자

예시 데이터는 펜실베이니아주 렉터(Rector)의 Powdermill Nature Reserve에서 가져왔으며, 이곳에서 AudioMoth 녹음기가 2018년 4월부터 7월까지 새벽 합창을 기록했습니다(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.1kHz이고 데이터셋의 README는 32kHz 녹음을 설명합니다. Dryad 사본에서의 BirdNET 점수는 아래의 점수와 약간 다를 수 있습니다. 이 튜토리얼은 wav_Files.zip(1.4GB)과 annotation_Files.zip의 Zenodo 사본을 사용하며, 2018년 5월 8일 오전 5:32부터 녹음한 Recording 2의 처음 네 구간을 가져옵니다. 이 20분에는 13종에 대한 전문가 상자 891개가 있습니다.

BirdNET-Analyzer 실행

BirdNET-Analyzer는 PyPI에서 설치하며 Python 3.11 이상이 필요합니다. 첫 실행은 약 224MB의 모델을 내려받습니다. 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월 둘째 주 Powdermill에서 기대하는 BirdNET의 분포 모델 150종으로 BirdNET을 제한합니다. BirdNET은 한 해를 한 달에 넷씩 48주로 나눕니다. --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

모든 행은 0Hz에서 BirdNET의 기본 대역 통과 필터의 상한인 15kHz까지의 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이 보고하지 않은 종마다 가장 또렷한 울음소리 주위에 상자 하나를 그립니다. 다음을 클릭하면 클립이 저장되며, 손대지 않은 클립은 BirdNET의 상자를 검토자의 답변으로 저장합니다.

스펙트로그램의 상자가 아니라 스펙트로그램 아래의 목록으로 작업하세요. 첫 클립은 상자 103개로 열리며, BirdNET의 전체 높이 3초 상자는 5분 클립의 스펙트로그램 전체를 덮습니다. 목록의 각 행에는 라벨 메뉴, 상자의 3초를 재생하는 재생 버튼, 삭제 버튼이 있습니다. 이 클립들에는 빈 스펙트로그램이 남아 있지 않습니다. 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이 같은 창에서 보고하지 않은 라벨 목록의 다른 종의 전문가 상자가 있으면 상자의 라벨을 바꿨고, 그렇지 않으면 삭제했습니다. 전문가가 찾았지만 남은 상자 중 지명한 것이 없는 종마다 스크립트는 전문가의 가장 긴 상자를 그렸습니다. BirdNET 상자 621개 중 601개가 수락되고 12개가 라벨이 바뀌고 8개가 삭제되었으며, 놓친 종에 대해 7개의 상자를 그렸습니다. 각 창을 듣는 사람은 창 가장자리의 울음소리를 0.1초 규칙과 다르게 판단할 수 있습니다.

Raven 선택 표 내보내기

Raven 내보내기는 녹음마다 선택 표 하나를 씁니다.

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

이 명령은 총 620개의 상자가 든 export/Recording_2_Segment_01.selections.txt부터 Recording_2_Segment_04.selections.txt까지를 썼습니다. 각 파일은 녹음 이름을 따르며, 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으로 가장 낮은 정밀도였으며, Louisiana Waterthrush 상자 47개 중 6개가 삭제되었습니다. Wood Thrush가 621개 상자 중 389개를 차지했습니다. 따라서 전체 정밀도 0.97은 대부분 Wood Thrush의 척도이며, 읽어야 할 것은 종별 행입니다. Ovenbird의 네 개 중 상자 하나가 틀렸다면 Ovenbird의 정밀도는 1.00에서 0.75로 움직였을 것이며, 상자가 열두 개 이하인 종은 그 종의 정밀도가 의미를 가지려면 더 많은 클립이 필요합니다.

다른 기준값에서의 정밀도와 놓친 울음소리

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는 Kaleidoscope의 기능에 BirdNET 분류기를 나열합니다. 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