ネズミを一度も捕まえたことのないネズミ捕り

Raspberry Pi 5、2台のカメラとマイクで作った給餌器モニタリングシステム:訓練セットと赤外線イメージングを修正して初めて、夜間の野鼠の検出率が本当に上がった。著者は、旧検証セットではなぜ問題も修正も見えなかったのかも明記している。

日本語
コピー
插画:夜色里一台带天线的摄像头打出光锥照向鸟食罐,右下角一只老鼠被绿色的检测框圈住,背景是树影

このプロジェクトは、Raspberry Pi 5、カメラ、マイクで組んだセンサー一式を使って、餌台の周りに来る鳥と害獣を見分けようというものだ。著者は最初、夜に出るネズミを検出できず、その後トレーニングデータセットを修正し、赤外線画像向けの調整を加えて野ネズミの検出精度を上げた。同時に、最初の検証工程の欠陥も露呈した。

何もない空しか見たことのない検出器が、そこに動物を一匹見つける。

-Ron

餌台を設置した。鳥が来る。それが目的だ。ネズミも餌台に寄ってくるので、これは趣味ではなくプロジェクトになった。ポールに登るネズミは野生の一場面ではなく、景色を背景にした鼠害だ。

そこで餌台を監視して何が来たかを教えてくれるセンサー一式を組んだ。鳥は属と種まで識別し、害獣に印を付け、すべてをサムネイル付きで記録して、後から判断を検証できるようにする。作り始めてから、この最後の点が思っていたよりずっと重要だと気づいた。

中身

Raspberry Pi 5 にカメラ2台とマイク2本を接続し、物体検出は Hailo-8 NPU、それ以外はすべて Pi の CPU が担当する。全体はバッテリーとソーラーで動き、屋外に設置してある。

部品役割
Raspberry Pi 5, 4GBすべてを実行
Raspberry Pi AI HAT+, Hailo-8, 26 TOPS物体検出
2x Arducam IMX477, 6mm CS lens12MP、IR-cut フィルター付き、昼夜対応
2x Adafruit SPH0645 I2S microphones鳥のさえずりを収録
Waveshare UPS HAT とソーラーパネル屋外給電
Elecrow 2.13″ e-paper panelその日のカウントを表示、ターミナル不要

これが初版の筐体で、失敗だった。8.3 × 6.3 × 3.9 インチの密閉ボックスは、Pi 5、AI アクセラレータ、バッテリー HAT、カメラ2台を収める空間も放熱の余裕もなかった。交換版にはサーモスタットとファンを付けた——太陽の下で NPU を回す密閉ボックスに本当に必要なのはこれだ。この教訓は筐体1個分の出費で済んだ。

もう一つ間違えたのはレンズだ。このレンズにはソフトウェアによるフォーカス制御が一切なく、ピント合わせは筐体上で手で回すリングだ。結局、小さな Web ビューアを書いて、ネイティブセンサーピクセルの 1:1 クロップをスマホに表示することにした。拡大縮小したフレームはどのレンズ位置でもそれなりに見えてしまうからだ。拡大縮小はフィルターの一種で、まさに判断したい細部を覆い隠す。

仕組み

まず動きを見る。320×240 の背景差分で画面内に動くものがあるかを判断し、動きがなければニューラルネットワークは一切走らせない。ソーラー給電では、最も省エネな推論は実行しない推論だ。

動きがあれば、コードは動きの領域を中心に 4056×3040 のセンサー画像から最大2つの 640×640 ウィンドウを切り出し、NPU 上の YOLOv8n に渡す。YOLOv8n は来訪者を鳥、リス、ネズミ、猫、未知の動物に分類する。鳥なら iNaturalist のデータで訓練した MobileNet V2 分類器に送り、965 種を識別できる。これは自分が気にしている米国西部の餌台の鳥50種をカバーする。すべての結果はサムネイルとともに SQLite に書き込まれる。ちなみにアクセラレータはボトルネックではない。パイプライン全体はカメラ1台あたり約 9.3 フレーム毎秒で動き、詰まっているのは CPU 上のリサイズ処理だ。

マイクは独立した検出器で、このパイプラインには属さない。独自の取得スレッド、独自のゲーティングを持ち、BirdNET が CPU 上で動いて3秒ウィンドウあたり約 62 ミリ秒——2チャンネルでリアルタイムの約48倍、コア1個の4パーセントしか使わない。2つの経路が交わるのはデータベースの中だけだ。間にビューを挟んで両者を union し、その行がどちらの感覚から来たかを示す列を付ける。カメラが止まっても耳は動き続ける。これがプロジェクト全体で最も役に立った判断だと分かったが、その理由は事前には予想していなかった。

6件の検出を保存されたまま並べたもの。この部分は機能している。

そしてデータベースを読んだ

庭に数週間置いた後、保存された検出をすべて引き出し、サムネイルでコンタクトシートに並べた。4,073 行。鳥は問題なかった。2,432 行、ほとんどが本物で、正しく識別された割合も残しておく価値があるほど高かった。

それ以外のカテゴリはすべてゴミだった。

リスが 607 件、残ったサムネイルに写っていたのはイトスギと餌台の上にしゃがむ鳥だった。未知の動物が 518 件——雲、吊り下げられた植木鉢、シェパーズフック。猫が 101 件、うち猫はゼロ。雲と同じ植木鉢だ。ネズミが6件、うち2件はあのシェパーズフックだった。

動物と天気を分ける信頼度のしきい値をずっと探していたが、そんなものは存在しないと分かった。本物の鳥は信頼度が 0.45 から 0.97 までばらつく。データベース内で最も信頼度が高い猫は雲で、0.81 だった。しきい値を上げると、捨てられるのは鳥で、残るのは空だ。

次に検出結果を時間ごとにバケット分けし、2つのセンサーを並べて見た。21:00 から 04:00 の間、カメラが報告した検出数はゼロ。同じ8時間で、マイクは 10,060 件を報告した。ボックスには通電し、データも処理していた。映像の経路は暗闇では何も見えない——部品表に赤外線照明はなく、動かせる赤外カットフィルターも、赤外光を出すものが何もなければ何の役にも立たない。

ネズミは夜行性だ。ネズミ検出と名付けたこのプロジェクトは、一度もネズミを見る機会がなかった。

検証セットこそが嘘だった

モデルは自分の検証セットで mAP@0.5 が 0.751 だと報告した。rat クラスは 0.762 で、bird より高い。数字は本物だが、それが測っているもののうち、俺が関心を持つものは一つもない。

どちらのデータセットも Open Images 由来だ。スタジオとアマチュアの写真、動物は中央に寄り、画面いっぱいに収まり、昼間に撮影され、「ここには何もない」が正解の画像は一枚もない。訓練アノテーション 9,730 件、背景画像ゼロ。これで訓練した検出器には「空の空」という概念がない。だから画面の中で一番動物らしいものにボックスを置く。晴れた午後なら、それは雲だ。

rat クラスはもっと酷い。Open Images に rat ラベルはないので、最初のパイプラインは Mouse で代用した。形が近いから大体足りるだろうと俺は言った。実際に切り出された画像を見ると、全部ペットのハムスターだ。ゴールデンハムスターとジャンガリアンハムスターが、ケージの中、毛布の上、人の手のひらに乗せられ、キッチンの照明の下にいる。24 枚のうち野生のネズミらしいのは 2 枚程度。モデルが学んだのは「屋内、近距離、大柄、毛むくじゃらの齧歯類の顔」だ。探す必要があるのは夜の屋外、遠く、横向きの小さなシルエット。この二つはほとんど重ならない。

0.762 はペット写真の中でハムスターを見つけるモデルの能力を正直に反映している。俺がそれを別のものとして読んだだけだ。

夜のために訓練し直す

座って手を動かして直し始めて、ようやく気づいたことがある。夜は暗い昼ではない。別のドメインだ。

IR-cut フィルターが外れると、3 つのカラーチャンネルはすべて赤外を見る。画像は実質モノクロだ。植生は明るく反射し、毛の反射率はその動物が昼間にどう見えるかとはほぼ無関係。昼間のカラー画像で訓練したモデルにとって夜は分布外だ。雲の上でとっくに分布外だったのとまったく同じ話だ。直すつもりだったのはネズミというクラスだった。実際に直す必要があったのは、白黒で、遠くにいて、夜にいるネズミというクラスだ。

まずハムスターを追い出す。本物の野ネズミは iNaturalist の Rattus norvegicus と Rattus rattus の研究グレードの観察記録から取る。iNaturalist にバウンディングボックスはないので、オープンボキャブラリ検出器に rat、brown rat、rodent、mouse というプロンプトを与えて候補を出させ、コンタクトシートを一枚ずつ見て人手で確認した。ヒット率は約 59%。ボックスが出なかった写真は捨てて、背景には使わない。ネズミが写っている写真に空ラベルを付けるのは、モデルが本来見つけるべきものを否定するよう教えるのと同じだ。

これで手に入るのは本物のネズミであって、あのドメインではない。iNaturalist のデータセットで測ると、暗所・モノクロの画像が 3.2%、ネズミの高さが画面の 35% を超えるものが 51.3%、観察記録の 55.3% に「dead」が付いている。死んだネズミの昼間の接写ポートレート集だ。うちのフィーダーが捉えるのは数メートル先にいる生きたネズミで、近赤外、画面の高さの 17% ほど。

雲の問題は別に直す。背景画像 1,500 枚に空のラベルファイルを付けて、訓練セットの約 11% を占める。最初に集めたときは植生の隣の建物、窓、椅子、テーブルを選んだが、コンタクトシートが返ってきたら会議場と街頭の人物ばかりだった。動物が写っていないのは確かだが、それは「庭のカメラが実際に見る光景には動物がいない」をモデルに教えることにはならない。今のスクリプトは植生を必須にして、屋内の特徴を排除する。

このデータは赤外カメラ由来だ。LILA BC のデータセットがちょうど合う。カメラは固定され、夜になると自動で赤外に切り替わり、アノテーションボックスは研究チームが手で描いている。同じカメラ群から動物がいないと確認済みの空フレームも取った。夜間赤外のシーンにとって、これが現実に最も近い難負例だ。

このステップにはダウンロードそのものより大事な細かい点が三つある。

画面に写る人間、昆虫、蛾、クモは残すがボックスは付けない。この検出器に human クラスを学ばせてはいけないし、850nm の補助照明を横切る蛾は、夜間カメラ史上最も古典的な誤検出源だ。これらのフレームだけが「蛾は何でもない」とモデルに教える唯一の訓練信号になる。

分割はカメラ単位で行い、ランダムにはしない。一台のカメラは数秒のうちにほぼ同一のフレームを連写する。同じ動物、同じ背景。ランダム分割で測れるのは記憶力だけだ。カメラごと丸ごと留保し、116 台のうち 27 台を外した。

もう一台、上限を設ける必要があった。micronesia_cam06 はおとりカメラで、1,372 フレーム、1 フレームあたり平均 7.5 匹のネズミが写り、これ一台でデータセット全体のネズミインスタンスの 64.8% を占めていた。300 フレームに制限し、3 匹を超えるフレームは捨てた。うちのフィーダーには一度に一匹しか来ないからだ。

これが rat クラスに与えた実際の影響:

ハムスター野ネズミ赤外カメラ追加後
ネズミのアノテーションボックス7042,9256,624
夜間・モノクロなし3.2%49.0%
ボックス高さの中央値屋内の接写画面の 35.7%画面の 17.6%

ここからが強調したい部分だ。古い検証セットは俺が何も成し遂げていないと示していた。mAP 0.782 対 0.784。ところがモデルが一度も訓練していない 27 のカメラ地点では、rat の AP50 が 0.235 から 0.745 に上がった。夜間フレーム 938 枚だけを見ると 0.279 から 0.759、夜間の空フレーム 224 枚での誤検出は 5 回から 3 回に減った。問題が見えないデータセットには、修正も見えない。変更はそれが狙ったドメインで測れ。

NPU 向けの量子化にいくら払っているのかも、ようやく測った。ずっと後回しにしていた。同じ夜間フレームで、rat の AP50 は浮動小数点の 0.658 から INT8 の 0.622 に下がり、デプロイ閾値での再現率は変わらなかった。代償は適合率に出る。知っている方が仮定するよりいい。

そのどれも要所では検証できていない。補光灯がまだ発注中だからだ。届けば、さらに3つの問題が増える。透明なドアの内側に付ければ、光はポリカーボネートで反射してそのままレンズに戻り、映像は真っ白に飛ぶ。だから外側に付けるか、レンズ室から隔離する必要がある。自動露出には今のところ上限がなく、補光灯の下で長時間露光すると動くネズミにブレが乗る——小型で高速なターゲットを台無しにする、まさにその種のアーティファクトだ。それに電源。バッテリーパックは約78Wh、実測負荷は10〜14W。ここに6Wが加われば、稼働時間は約4.3時間に落ちる。しかもその消費は、ソーラーパネルが何も貢献しない時間帯にちょうど重なる。

別のビルダーに伝えること

検証セットとは実験そのものだ。 残りは全部ただの記帳だ。ホールドアウトが訓練データのあらゆるバイアスを引き継いでいるなら、良いスコアは自分の仮説を測っているにすぎない。

mAPだけでなく、1時間あたりの誤検出数を報告しろ。 本当に効いてくる失敗は、昼光下の約15時間で1,232件の誤検出が出たことで、空シーンを含まないセットではmAPがこの数字をまったく表せない。

クラス名には実際に入っているものを書け。 中身がハムスターなのに「rat」と名付ければ、その欠陥は裏庭のポールの上のあのボックスまでずっと引き継がれる。

動物に割り当てられたピクセル数は、モデルに施すどんな工夫よりも効く。 家朱雀をこのPiが撮った実映像に合成すると、フルフレームでは100回中1回も見つからず、クロップウィンドウでネイティブ解像度なら38回見つかった。種の識別にはさらにピクセルが要る。鳥が約150ピクセルなら一致率は約85%、66ピクセルなら約9%。カメラが遠すぎる分は、訓練では埋め合わせられない。

暗い映像は別の映像だ。 夜間の赤外はそれ自体が独立した視覚ドメインで、訓練データにない状況もすべて同じことが言える。センサーの見ているサムネイルを見て自分のデータだと分からないなら、訓練しているものは配備向けではない。

第二の知覚モダリティは対照であって、機能ではない。 マイクを足したのは鳥の声を録るためだった。実際に果たしたのは、カメラが夜間に盲目であることの証明だ——カメラのデータだけでは到底導けなかった。音もなく壊れるものには、違う壊れ方をする証人が必要だ。

できていないこと

Webインターフェースはない。clip writerは構築され、columnも読み込まれるが、その間でそれを呼び出すものが一切ない。だから全4,073行のうちclip_pathはnullで、clipsディレクトリも空だ。監査をして初めて気づいた。それに、今に至るまでネズミを1匹も検出していない。

次はilluminator、検出器が見た640×640のウィンドウをそのまま保存する採取モードで、このbox自身に訓練データを生成させる。加えてこの庭でホールドアウトのフレームを一式取り、夜間に手作業でラベル付けする。空のフレームも含めて。

そうして初めて、これらが効いたのかどうかが分かる。

コードはgithub.com/rondilley/RatCatcher_AI、GPL-3.0-or-later。BirdNETの重みは私が再ライセンスするものではない。CC BY-NC-SA 4.0で、インストーラが実行時にZenodoから取得する。商用利用の前に条項を読んでほしい。

出典: iamnor← ホームへ戻る