ここまで、
について紹介してきました。
しかしシステムは、プログラムが一度動けば完成というわけではありません。
毎日の観測で使うには、
いつ起動しても同じように動くこと
が非常に重要です。
そこで今回のシステムではDocker Composeを利用しています。
機械学習プログラムには、多くの依存関係があります。
例えば、
Python
機械学習ライブラリ
画像処理ライブラリ
Webサーバー
データベース関連ライブラリ
などです。
PCへ直接インストールすると、
「このPCでは動くが別のPCでは動かない」
「ライブラリを更新したら動かなくなった」
という問題が起こりやすくなります。
Dockerを使えば、必要な実行環境をコンテナとしてまとめられます。
概念的には、今回の環境は次のように考えられます。
┌──────────────────────┐
│ Docker Compose
│
│ worker
│ ・判定
│ ・学習関連処理
│ ・日次処理
│
│ review
│ ・Web UI
│
└──────────────────────┘
│
│
観測データ
処理担当とWeb UIを分けておけば、それぞれの役割が明確になります。
Dockerを使うときに重要なのが、観測データの保存場所です。
コンテナは作り直したり削除したりすることがあります。
そのため、重要な観測画像やデータベースまでコンテナ内部だけに保存してしまうと危険です。
そこでホストPC上のフォルダをDockerへマウントします。
イメージとしては、
Windows
C:\...\capture
│
│ volume mount
▼
Docker
/observation/capture
です。
Docker側のプログラムはLinux風のパスを使っていても、実体はWindows側の観測フォルダに保存できます。
レビューサービスを起動したら、Tailscaleを使って別PCからアクセスします。
これで観測用PCでは、
撮影
検出
AI処理
を行い、
普段使うPCでは、
レビュー
だけを行うという役割分担ができます。
最終的には、利用者が毎日意識する操作をできるだけ少なくすることが重要です。
現在の運用イメージは、
1. 観測する
2. ブラウザでレビューする
3. 必要な日次処理を実行する
です。
システム内部では機械学習モデル、データベース、Docker、画像処理などいろいろなものが動いています。
しかし、利用者が毎日それらすべてを意識する必要はありません。
良い自動化システムは、
内部が複雑でも、日常の操作は単純
であるべきだと思います。
今回、流星検出へ機械学習を導入するところから始めました。
観測
↓
検出
↓
AI判定
↓
レビュー
↓
教師データ
↓
モデル改善
↓
再び観測
機械学習を導入するというと、
「どのモデルを使うか」
「精度は何%か」
という話になりがちです。
もちろんそれも重要です。
しかし長期間使うシステムでは、
間違えた結果を人が確認できること
その修正を次の学習に利用できること
簡単に起動・停止・更新できること
も同じくらい重要です。
今回作ったのは「完成した流星判定AI」というより、
観測を続けることで少しずつ改善されていく流星観測環境
です。
今後は、モデルごとの性能比較、誤判定データの優先学習、判定根拠の可視化、複数観測地点への展開なども試していきたいと思っています。
このあたりは、またシステムが発展したところで紹介したいと思います。
※記事の作成にAIを使用しました。
]]>機械学習モデルを作ったあと、
「これで完成」
としてしまう方法もあります。
しかし今回のシステムでは、モデルを固定したものとは考えていません。
実際の観測データを使いながら少しずつ改善していくことを前提にしています。
レビュー画面では、人間がAIの判定結果を確認します。
例えば、
AI判定 非流星
人間判定 流星
というケースが出てきます。
これは単なる「AIの失敗」ではありません。
次の学習にとって非常に価値の高いデータです。
現在のモデルが、
「どこを理解できていないのか」
を教えてくれるからです。
通常、機械学習モデルを作るには教師データを準備する必要があります。
しかし流星画像だけを大量に集めて、すべて人間が分類するのは大変です。
そこで、
日々の観測とレビュー作業を、そのまま教師データ作成につなげる
ことにしました。
流れは次のようになります。
新しい観測
↓
AIが判定
↓
人間が確認
↓
正しいラベルを保存
↓
教師データに追加
↓
再学習
これなら、特別に「今日は教師データを作ろう」と作業しなくても、普段のレビューを続けることでデータが増えていきます。
例えばモデルが1000枚すべてを正しく判定したとします。
もちろんそのデータにも意味はあります。
しかしモデル改善という意味では、
モデルが自信を持って間違えた画像
や、
判定スコアが境界付近だった画像
のほうが興味深い場合があります。
現在のモデルにとって難しい例だからです。
これはActive Learningと呼ばれる考え方にも近いものです。
人間がすべての画像に同じ労力を使うのではなく、モデルにとって価値の高いデータを重点的に確認する方法です。
新しい教師データが増えたからといって、毎回無条件に新しいモデルへ交換するのは危険です。
再学習したモデルが必ず以前より良いとは限りません。
ある種類の画像では性能が上がっても、別の種類では悪化することがあります。
そのため本来は、
現在のモデル
│
├── 評価データ
│
新しいモデル
│
└── 評価データ
として両者を比較し、
を確認してから切り替える必要があります。
実際の運用では、毎日複数のコマンドを手作業で実行するのは面倒です。
そこで処理をまとめて実行できるようにしています。
例えば日次処理は、
docker compose run --rm worker daily
のように実行します。
内部ではシステムの状態に応じて必要な処理を進めます。
利用者側から見ると、
観測する
↓
レビューする
↓
daily処理
という単純な運用にできます。
自動更新を考えると、
「今どのモデルを使っているか」
を追跡できることも重要です。
例えば、
model_001
model_002
model_003
のようにモデルを残しておけば、問題があった場合に以前のモデルへ戻せます。
さらに各判定結果に、
使用モデル:model_003
という情報を保存しておけば、
「この判定はどのモデルが行ったのか」
を後から確認できます。
AIを長期間運用する場合には、モデルそのものもソフトウェアと同じようにバージョン管理する必要があります。
最終的に作りたいのは、
「一年に一度、人間が大量の教師データを作ってモデルを作り直すシステム」
ではありません。
日々の観測の中で、
間違える
↓
人間が直す
↓
学ぶ
↓
少し改善する
というサイクルが自然に回る仕組みです。
この構成なら、観測環境固有の特徴にも少しずつ適応していけます。
次回は連載の最後として、
この仕組みを実際に毎日動かすためのDocker環境と、日常の運用方法
について紹介します。
]]>機械学習モデルで自動判定できるようになると、次に必要になるのが、
「その結果をどう確認するか」
です。
最初は画像ファイルをフォルダから開いて確認する方法でも運用できます。
しかし件数が増えてくると、
画像を開く
↓
動画を探す
↓
判定する
↓
結果を記録する
という操作そのものが面倒になってきます。
そこで専用のWebレビュー画面を作りました。
レビューUIはWebブラウザから利用します。
これにはいくつかメリットがあります。
専用アプリを各PCにインストールする必要がなく、
ChromeやSafariなどからアクセスできます。
また、観測プログラムがWindows上で動いていても、MacBookから同じ画面を利用できます。
レビュー画面で特にこだわったのが、
画像と動画を同時に確認できること
です。
最初は静止画だけでも十分だと思っていました。
ところが実際の観測データを見ると、時間方向の情報が非常に重要でした。
例えば静止画では一本の光跡に見えていても、動画では、
などの違いがあります。
これは流星、人工衛星、飛行機などを区別するうえで強い情報になります。
人間が確認するときには、
も表示します。
これにより、
「これはAIも迷っている」
「AIは強く非流星と判断したが、実際には流星だった」
といったケースを発見できます。
こうしたデータは後のモデル改善でも特に重要です。
レビュー作業は毎日のように行う可能性があります。
そのため、一件判定するために何度も画面を切り替えるようなUIでは、少しの手間でも積み重なると大きな負担になります。
理想的には、
見る
↓
判断する
↓
ボタンを押す
↓
次の画像
という流れだけで処理できるようにします。
UIを作る目的は見た目を豪華にすることではなく、
1件あたりの確認時間をできるだけ短くすること
です。
このレビュー画面は観測用PCだけでなく、別のPCから利用できるようにしています。
現在使用しているのがTailscaleです。
Tailscaleを使えば、許可された端末同士で仮想的なプライベートネットワークを構成できます。
そのため、
インターネットに公開
ではなく、
自分の端末同士だけ接続
という形にできます。
自宅や観測場所にあるPCを離れた場所から操作・確認するときにも便利です。
機械学習システムというと、どうしてもモデル精度に注目しがちです。
しかし実際に運用すると、
「人間がAIの結果をどう確認するか」
も同じくらい重要です。
モデルの精度が少し上がっても、レビュー画面が使いにくければ毎日の作業負担は減りません。
今回レビューUIを作ったことで、
機械学習モデル
↓
レビューUI
↓
人間
という接点ができました。
そして、この人間の判断結果が次の学習データになります。
次回は、
レビュー結果を利用して、機械学習モデルをどう更新していくか
について紹介します。
]]>前回までで、観測データからイベント候補を取り出すところまで説明しました。
しかし、候補の中には流星だけでなく、
などが含まれています。
これらを毎回すべて人間が確認していては、自動検出のメリットが小さくなります。
そこで候補画像を機械学習モデルに入力し、一次判定を行います。
今回の問題を最も単純化すると、
入力:観測画像
出力:
流星
非流星
という画像分類問題になります。
モデル内部では画像から特徴を取り出し、最終的に「どちらに近いか」を数値として出力します。
例えば、
Meteor score = 0.94
なら、モデルはかなり強く流星だと判断している、と解釈できます。
処理の概念をコードにすると次のようになります。
score = predict(image)
if score >= threshold:
label = "meteor"
else:
label = "non_meteor"
実際には画像サイズの調整や正規化などの前処理もありますが、利用側から見ると基本的な流れはこれだけです。
ここで重要になるのが threshold、つまり判定の境界値です。
例えば、
threshold = 0.5
なら、0.5以上を流星とします。
しかし、0.5という値が必ず正しいわけではありません。
観測システムでは、
「非流星をどれだけ除外したいか」
だけではなく、
「本物の流星をどれだけ取りこぼしたくないか」
を考えて閾値を決める必要があります。
機械学習による判定には、大きく二種類の間違いがあります。
一つは、
実際:非流星
AI :流星
です。
これはfalse positive、偽陽性に相当します。
もう一つは、
実際:流星
AI :非流星
です。
こちらはfalse negative、偽陰性です。
流星観測では後者のほうが問題になります。
偽陽性は人間が余分な画像を確認すれば済みます。
しかし偽陰性を自動削除につなげてしまうと、本物の流星を失う可能性があります。
そのため、単純に「正答率が高いモデル」を目指すだけでは不十分です。
例えば一晩に1000件の候補があり、そのうち流星が10件しかないとします。
極端な話、すべてを「非流星」と答えるだけでも、
990 / 1000 = 99%
の正答率になります。
しかし本物の流星10件をすべて見逃しています。
観測システムとしてはまったく使えません。
そのためモデルを評価するときは、
などを分けて見る必要があります。
モデルの出力は、単にその場で使って終わりにはしません。
例えば、
ファイル名
判定ラベル
判定スコア
使用したモデル
人間によるレビュー結果
といった情報を紐づけて保存します。
これにより後から、
「AIは何と判定していたのか」
「人間はどう修正したのか」
「どのモデルで誤判定が増えたのか」
を追跡できます。
機械学習システムを実運用するうえでは、この履歴がかなり重要になります。
システムには、モデルの判定結果を利用して不要なデータを整理する機能も考えられます。
ただし、自動削除を使う場合は特に注意が必要です。
安全側に寄せるなら、
高い確率で流星
↓
保存
判断が難しい
↓
人間が確認
極めて高い確率で非流星
↓
設定に応じて処理
というように、グレーゾーンを残す設計が向いています。
AIの結果を「正解」とするのではなく、
どこまでAIに任せるかを設定可能にする
ことが重要です。
最初に学習させたモデルが、すべての観測条件に対応できるとは限りません。
例えば季節や天候が変われば、これまであまりなかった画像が出てきます。
そうした画像に対してモデルが間違えると、人間がレビュー画面で修正します。
この修正結果は、新しい教師データになります。
つまり、実際の観測そのものがデータ収集になります。
このシステムで機械学習に期待しているのは、
「人間の代わりに100%正しい判断をすること」
ではありません。
むしろ、
大量の候補の中から、人間が見るべきものを効率よく仕分けること
です。
この位置づけにすると、機械学習の弱点とも付き合いやすくなります。
次回は、このAIの判定結果を実際に人間が確認するために作った、
ブラウザベースのレビューUI
について紹介します。
※記事の作成にAIを使用しました。
]]>前回は、今回作ったシステム全体について紹介しました。
処理の流れは大きく、
観測
↓
イベント検出
↓
機械学習による判定
↓
人間によるレビュー
となっています。
今回は、その最初の「イベント検出」について考えます。
流星観測では、カメラは長時間空を撮影し続けます。
しかし、人間が一晩分の映像を最初から最後まで見続けるのは現実的ではありません。
そこでまず必要になるのが、
何か変化が起きた時間だけを取り出す処理
です。
ここでは、いきなり「これは流星だ」と判断する必要はありません。
重要なのは、
「確認する価値のあるイベントが起きた」
ことを検出することです。
検出処理を作るとき、
「誤検出を減らしたい」
と考えたくなります。
もちろん誤検出が少ないほうが確認作業は楽になります。
しかし流星観測の場合、それ以上に重要なのが、
本物の流星を取りこぼさないこと
です。
例えば二つの検出方法があったとします。
A
本物の流星10件 → 10件検出
誤検出 → 90件
B
本物の流星10件 → 8件検出
誤検出 → 10件
Bのほうが一見優秀に見えます。
確認するデータは18件しかありません。
しかし、本物の流星を2件失っています。
後からどれだけ優秀なAIを使っても、この2件を復活させることはできません。
そのため今回の考え方では、最初の検出器にはある程度余裕を持たせ、
候補は多めに拾い、その後で絞り込む
という方針を取っています。
この違いを整理すると、次のようになります。
検出器
「何か起きたか?」
↓
分類器
「それは流星か?」
検出器は候補を見つけます。
分類器は、その候補について判断します。
この二つを一つの処理にしてしまうと、
「流星らしくないから検出しない」
ということが起きやすくなります。
一方、二段階にしておけば、
多少怪しいイベントでもまず保存し、AIや人間が後から確認できます。
検出されたデータを確認すると、本物の流星以外にもさまざまなものがあります。
このような比較画像は、機械学習モデルを作るときにも重要です。
人間には明らかに違って見えても、画像だけを見たモデルにとっては似た特徴を持つ場合があります。
特に、
などは、モデルにとって混同しやすい場合があります。
イベントが検出されると、後から確認できるように関連する画像や動画を保存します。
ここで静止画だけでなく動画も残しておくことが、その後のレビューで役立ちます。
例えば人工衛星は、一枚の画像だけなら流星に似て見える場合があります。
ところが動画を見ると、
「一定速度で長時間移動している」
ことが分かります。
飛行機なら点滅が確認できる場合もあります。
時間方向の情報は非常に強い判断材料になります。
ここで初めて機械学習の出番です。
検出処理で広めにイベントを拾い、
候補100件
が生成されたとします。
その100件を機械学習モデルに入力して、
流星らしい 15件
流星ではなさそう 85件
のように分類します。
人間はすべてを同じ優先度で見る必要がなくなります。
AI判定を使って表示順を変えたり、確認対象を絞ったりできます。
この構成には、もう一つメリットがあります。
将来、機械学習モデルを変更しても、元の候補データが残っていれば再判定できます。
例えば、
2026年モデル
↓
判定結果A
だった画像を、
2027年モデル
↓
判定結果B
として再評価することも可能です。
検出結果そのものとAI判定を分けて保存しておくことで、モデルが進歩した後にも過去データを活用できます。
今回の設計を一言で表すなら、
最初から賢く見つけようとしすぎない
ということになります。
まず広めに拾う。
その後AIに判断させる。
さらに必要なら人間が確認する。
この役割分担によって、観測データを失うリスクを抑えながら、確認作業を減らせます。
次回は、ここで抽出されたイベントを、
機械学習モデルがどのように「流星らしい/流星ではなさそう」と判定するのか
を紹介します。
※記事の作成にAIを使用しました。
]]>それが「観測データの確認」です。
以前に流星観測画像を機械学習で分類するという記事を書きました。今回はそれをさらにアップグレードしてみたいと思います。
屋外カメラを24時間作動させて観測すると、多数の画像や動画が生成されます。その中から流星が写っているものを探しますが、検出されるのは流星だけではありません。
飛行機、人工衛星、雲、虫、ノイズ、周囲の光など、さまざまなものが「何かが起きたイベント」として検出されます。
観測を始めたころは一つずつ確認することもそれほど苦になりません。しかし、観測日数が増えるにつれて、この確認作業は無視できない量になってきます。
そこで今回、
流星候補の検出から機械学習による判定、人間による最終確認までを一つにつないだ観測支援システム
を作ることにしました。
最初に考えるのは、
「画像認識AIで流星かどうかを判定すればよいのではないか」
という方法です。
現在の画像認識技術を使えば、画像を「流星」と「流星ではないもの」に分類するモデルを作ること自体は可能です。
しかし、実際の観測に使うとなると、一つ大きな問題があります。
AIは必ず間違える、ということです。
例えば飛行機を流星と誤判定しても、人間が確認するときに余計な画像が一枚増えるだけです。
一方、本物の流星を「流星ではない」と判定し、その結果だけを信じてデータを削除してしまうと、観測データそのものを失います。
この二つの間違いは、同じ「1件の誤判定」でも意味がまったく違います。
そのため今回のシステムでは、
AIは一次判定を担当し、最終的な確認は人間が行う
という構成にしました。
もう一つ重要なのが、
流星を検出する処理と、それが本当に流星なのかを判定する処理を分離する
という考え方です。
最初の検出段階では、多少の誤検出があっても構いません。
仮に一晩で100件のイベントが検出され、その中に本物の流星が10件しかなかったとしても、その10件をすべて拾えているのであれば、後から残り90件を取り除けます。
ところが最初の検出処理で本物の流星を見逃してしまえば、そのデータは後段のAIにも届きません。
そこで、
「検出は広めに拾う」
「判定は後から行う」
という二段構成にしています。
これは機械学習を実際のシステムに組み込むうえでも重要な考え方だと思います。
検出されたイベントについて、画像を機械学習モデルに入力し、
「流星らしい」
「流星ではなさそう」
という一次判定を行います。
イメージとしては次のような処理です。
score = model.predict(image)
if score >= threshold:
result = "meteor"
else:
result = "non_meteor"
実際の処理はモデルの出力形式や前処理などを含みますが、基本的な考え方はシンプルです。
重要なのは、ここで返された結果を「絶対の正解」とは扱わないことです。
AIの判断結果は、次のレビュー処理へ渡します。
AIの判定結果を確認するため、専用のWeb UIも作りました。
レビュー画面では、静止画と動画を並べて表示します。
動画を表示するようにしたのには理由があります。
静止画だけでは流星のように見えても、動画にすると一定速度で移動する人工衛星だったり、点滅する飛行機だったりすることがあります。
静止画と動画の両方を見られることで、最終判定がかなりしやすくなります。
レビューした結果は、
といった形で保存します。
レビュー画面はWebブラウザで動作するため、観測用PCの前に座る必要はありません。
現在はTailscaleを利用し、別のPCやスマートフォンから観測用PCに接続できるようにしています。
例えば、
観測用Windows PC
│
│ Tailscale
│
PC or スマートフォン
│
└─ Webブラウザ
という構成です。
観測用PCでは撮影や処理を続けながら、普段使っているPCからブラウザを開き、結果だけを確認できます。
これは実際に運用してみるとかなり便利です。
レビューUIを作った理由は、単に見やすくするためだけではありません。
人間が確認した結果は、非常に価値の高い教師データになります。
例えば、
AI :非流星
人間 :流星
というデータがあったとします。
これは、現在のモデルが苦手としている例そのものです。
そこでレビュー結果を蓄積し、次のモデル学習に利用できる仕組みにしました。
つまり、
観測
↓
AI判定
↓
人間による修正
↓
教師データとして蓄積
↓
再学習
という循環ができます。
流星観測では、最初からあらゆる状況の教師データを用意するのは困難です。
流星そのものが頻繁に現れるわけではありませんし、天候、空の明るさ、カメラ、観測地点などによって画像の特徴も変わります。
そのため、
最初から完璧なAIを作るより、実際の観測データを使いながら徐々に改善する
という方法が現実的だと考えました。
今回作っているのは単なる「流星判定AI」ではなく、
観測・AI・人間の判断を一つの循環にした観測システム
です。
次回は、その一番最初にある、
「大量の観測データから、そもそもどうやって確認すべきイベントを取り出すのか」
という検出処理について紹介します。
※記事の作成にAIを使用しました。
]]>今回のお目当ては、なんといっても「挂甲の武人」。群馬県太田市で出土した埴輪で、教科書などでもおなじみの国宝です。
そして「びじゅチューン!」で知っているチビたちも、本物を前にちょっと興奮気味。画面や本で見ていたものを実際に目の前にすると、やっぱり感じるものがあるようです。
もう少し大きくなったら、今度は国立博物館にも連れていきたい。そんな楽しみがひとつ増えた、久しぶりの博物館でした。
]]>まずは松本城へ。立派なお城を眺めながら、城の前で記念撮影。やっぱり実際に見る松本城は存在感があります。
その後はアルプス公園へ向かい、展望台から遠くアルプスの山々を眺めました。景色と山並みがとてもきれいで、しばらくのんびり景色を楽しみました。
帰り道には、「ドキュメント72時間」で取り上げられた黒曜の湧き水へ。冷たい湧き水を汲んで、長野をあとにしました。
お城に山の景色、そして湧き水。長野らしい自然と風景を楽しめた、気持ちのいいドライブになりました。
]]>宿題のテーマは、身の回りにあるものの形や手触り、匂いなどを観察してまとめるというもの。普段は何気なく見過ごしてしまうような植物や虫、自然の中にあるものをじっくり観察する良い機会になりました。
園内では、チビたちは虫を追いかけながら大はしゃぎ。夢中になって走り回る姿を見ていると、宿題というより思い切り遊びに来たような感じでした(笑)
そして、チビ③も前回の水族館に続いて虫たちに大興奮。生き物を見つけるたびに目を輝かせていて、「この子は本当に動物や生き物が好きなんだな」と改めて感じました。
宿題もしっかり進んで、子どもたちも楽しめた一日。遊びながら学べる場所は、やっぱりいいですね。
]]>