🤖

YOLOv8によるダストスポット検出AI「KlarSky」開発録:プロトタイプからMLOps、Vertex AIへの道

に公開

はじめに

写真、特に風景や空を撮影する者にとって、センサーダストは長年の課題である。作品を大判プリントした際にはじめて気づく黒い点は、作品の価値を大きく損なう。航空写真作家として活動する筆者も、この問題に長年悩まされてきた。

センサーダストの実例

この課題を解決するため、「印刷前にダストスポットの存在をAIで確実に検出する」ことを目標に、AIダストスポット検出ツール「Project KlarSky」の開発を開始した。本記事は、一個人の切実な悩みから始まったこのプロジェクトが、アイデアの着想からプロトタイピング、MLOpsパイプラインの構築ならびにクラウド(Vertex AI)での最適化と精度改善に至るまでの、技術的な試行錯誤の記録である。

課題の発見とプロトタイピング

プロジェクトの出発点は、「機械学習でダストスポットを検出できないか?」というシンプルな問いであった。ダストスポットは「小さく、黒っぽく、輪郭がぼやけている」という画像上の特徴を持っており、これは物体検出AIの得意分野であると考えられた。

技術スタックとして以下を選択し、開発に着手した。

  • 開発言語: Python
  • AIフレームワーク: PyTorch
  • 物体検出モデル: YOLOv8
  • アノテーションツール: Label Studio

開発初期の最大の壁は、AIに「ダストスポットとは何か」を教えるための教師データ作成(アノテーション)であった。手持ちの航空写真10枚に対し、地道にダストスポットを矩形で囲む作業を行なった。この少数データでの最初の学習は、もちろん実用的な精度には至らない。しかし、「データ準備 → 学習 → 結果確認」という一連のパイプラインをエラーなく通し、まずは動くものを作ることが、この段階での最も重要な目標であった。

さらに、開発のモチベーションを維持し、AIの挙動を直感的に把握するため、Gradioを用いてインタラクティブなGUIデモアプリを早期に作成した。画像をドラッグ&ドロップするだけで推論結果がリアルタイムに表示されるこのアプリの存在は、その後の複雑な開発プロセスを進める上での大きな助けとなった。

ローカル開発環境のMLOps化

プロトタイプが形になり、実験の回数が増えるにつれて、複数のPythonスクリプトが散在する場当たり的な開発スタイルに限界が見え始めた。本格的な改善サイクルを効率的に回すため、プロジェクトをMLOps(機械学習の開発・運用)の考え方に基づいたパイプラインへと昇華させることにした。

まず、プロジェクトのディレクトリ構成を整理し、「関心の分離」を行なった。メインのロジックをklarskyパッケージに、設定ファイルをconfigsに、補助的なツールをscriptsに分離し、開発基盤を整えた。その上で、以下のツールを導入した。

  1. 設定管理: Hydra学習のエポック数、バッチサイズ、使用データセットといった実験条件を、コードから分離しYAMLファイルで管理。これにより、コマンドラインからパラメータを変更するだけで柔軟に実験を組み立てられるようになり、再現性が大きく向上した。

  2. 実験管理: MLflow Hydraで実行された実験のパラメータ、学習メトリクス(mAPなど)、生成されたモデルといった成果物を自動で記録。pipenv run uiコマンド1つで、過去の全実験結果をブラウザで比較・検討できる環境を構築した。

  3. データ処理の高度化: Albumentationsと独自ロジック。限られたアノテーションデータを最大限に活用するため、Albumentationsライブラリによるデータ拡張(Data Augmentation) を導入。さらに、単に画像をリサイズするのではなく、アノテーション領域の情報を最大限保持する独自のインテリジェント・クロッピングロジック を開発し、学習データセットの品質を高めた。

これらの導入により、単なるスクリプトの集まりだったプロジェクトは、ワンコマンドで実験から分析、フィードバックまでを体系的に実行できる、本格的なMLOpsパイプラインへと進化した。

Gradio分析ツール

Vertex AIへの移行とクラウド環境の最適化

ローカルでの開発パイプラインが確立したことで、次なるステップとして、より大規模な実験と再現性の担保を目指し、GCP(Google Cloud Platform)のVertex AIへの移行を決定した。

インフラのコード化とコンテナ化

クラウドへの移行にあたり、手作業でのリソース作成を避け、すべてをコードで管理する方針を採った。

  • IaC (Infrastructure as Code): Terraform を用い、Cloud Storage、Artifact Registry、IAMサービスアカウントといったGCPリソースをコードで定義。これにより、インフラ構成の再現性と管理性を担保した。
  • コンテナ化: 再現性の肝となる学習環境はDockerfileで定義。ここで重要なのは、プレーンなPythonイメージではなく、GPUドライバとの互換性が担保されたNVIDIA公式のイメージをベースとすることである。

ローカルとクラウドの連携

クラウド移行後も、ローカルでの開発体験を損なわないための工夫も行なった。学習コード内で実行環境を判定し、MLflowの記録先をローカルのmlrunsディレクトリとVertex AI Experimentsへ自動で切り替えるように実装。これにより、既存のMLflow連携コードを一切変更することなく、すべての実験結果をVertex AI上へ集約できるようになった。

パフォーマンスチューニング

実際にVertex AIで学習ジョブを実行すると、新たな課題が見つかった。当初、n1-highmem-4インスタンスではCPU使用率が100%に張り付き、GPUが十分に活用できていない典型的なCPUボトルネックに陥っていた。リソースのモニタリンググラフを分析しながらマシンタイプを試行錯誤した結果、あるインスタンスタイプに変更することで、GPU使用率を90-100%に保ち、ほぼ同等のコストで学習速度を1.5倍へ向上させることに成功した。

コラム:GCS FUSE利用時の思わぬ落とし穴

Vertex AIでは、GCSバケットが/gcsパスにFUSEで自動マウントされ、手軽にデータへアクセスできる。しかし、この手軽さには注意が必要である。FUSE経由でのファイルアクセスは、裏側でGCSのAPI呼び出しに変換される。特に、ディレクトリのリスト表示などは高コストなClass A Operationに該当し、意図せず料金が高騰するリスクを孕んでいる。

筆者もこの仕様を知らずに利用し、GCSの操作料金だけで6,000円近い予期せぬ請求を経験した。GPU使用率が上がらない原因を調査する中で、I/Oがボトルネックになっていることに気づき、この問題が発覚した。

GCS料金内訳

この問題の原因を突き止め、I/Oの高速化とクラウド費用の適正化、ひいては学習時間の大幅な短縮を実現した。肝は変に楽をしないことである。

モデル精度向上のための体系的アプローチ

安定した実行環境をクラウドに構築したことで、いよいよプロジェクトの核心である「モデル精度」の本格的な改善に着手した。

評価指標の解像度向上

当初、評価指標としてmAP50(緩い基準での平均適合率)を主に参照していた。データセットの生成方法として、元画像をリサイズしてパディングするpadded方式と、高解像度のままタイルに分割するtiled方式を比較したところ、tiled方式がmAPスコアで圧倒的に高い性能を示した。

ところが、実際にモデルを利用すると「padded方式は誤検出が少ない」感触を得た。この定性的なフィードバックから、評価指標を深掘りした。 mAPという単一の指標だけでなく、Precision(適合率:検出結果のうち、本当に正解だったものの割合)Recall(再現率:存在する正解のうち、どれだけを検出できたかの割合) のバランスに着目した。その結果、tiledはRecallが高く、Precisionは低め(よく見つけるが、間違いも多い)、paddedはその逆というモデルの「性格」の違いを数値で把握できた。

Precision/Recallの比較グラフ

ここでは、単一のメトリクスだけを追うのではなく、その内訳を分析し、ユーザーの体感と数値をすり合わせることの重要性を学んだ。

学習プロセスの最適化と結論

モデルの「性格」を理解したうえで、次はその改善に取り組んだ。モデルサイズを大きくする(yolov8n→yolov8s)、正則化(dropout)を導入するといったアプローチは、いずれも有効な改善には繋がらなかった。

そこで、学習プロセスそのものに目を向けた。誤検出を減らすため、「紛らわしいが正解ではない」画像(雲など)を意図的に学習させるネガティブサンプリングを導入し、過学習の抑制を試みた。さらに、データ生成時の解像度と学習時の入力解像度を一致させる実験など、複数の仮説検証を繰り返した。

その結果、paddedデータセットにおいて、あえて一度高解像度で画像を生成しそれを学習時にYOLOv8のデータローダーに縮小(Downscaling)させることでモデル性能が向上するという、ある意味直感に反する知見を得ることができた。

最終的に、本プロジェクトにおける最適なデータ戦略とモデルアーキテクチャは、以下であると結論づけた。

  • 高精度重視モデル: tiled_640データセットを、imgsz=640で学習させる。
  • バランス重視モデル: paddedデータセットを、高解像度(例: 4096px)で生成し、imgsz=1024に縮小して学習させる。
  • モデルアーキテクチャ: 本タスクでは、モデルサイズを大きくしても性能向上には繋がらない。yolov8nが、計算コストと精度のバランスにおいて最適である。

現在の成果と今後の展望

一個人の悩みから始まったプロジェクトは、体系的な実験と試行錯誤を経て、実用的なツールへと進化した。

  • 高精度なAIモデル: 最適な学習戦略を発見し、実用レベルのモデルを構築。
  • 洗練された開発フロー: ローカルからクラウドまで一貫したMLOpsパイプラインを整備。
  • 成果の公開: Gradio製のデモアプリをHugging Face Spacesで公開し、誰でもその性能を試せる状態を実現。

しかし、このプロジェクトはまだ道半ばである。今後は、タイル学習したモデルのチューニングや、商用利用に適したYOLOXでのモデル学習などを検討している。そして、このプロジェクトの最終目標であるLightroomプラグインとしての実装に向け、開発を継続していく。


この記事の完全版について

この記事では開発の全体像を紹介しましたが、実際の開発の詳細な記録と具体的なノウハウをまとめた書籍を公開しました。

書籍で詳しく解説する内容

  • 実装の具体的な詳細

    • アノテーション効率化のためのCLAHEスクリプトの実装
    • 回転ラベルの座標変換ロジックとLabel Studio SDKとの格闘記
    • TerraformによるVertex AI環境構築の設定例
    • 動的ジョブ投入スクリプトの仕組み
  • 開発コストの完全内訳

    • 1か月で消費したGCP費用17,866円の分析
    • GCS FUSE問題で発生した6,000円の無駄遣いと対策
    • コスト最適化のための具体的な手順 GCP料金明細
  • 体系的な分析手法

    • mAP vs Precision/Recallの使い分けの実践例
    • モデル弱点分析のためのGradioツールの構築方法
    • 「オンザフライ縮小」発見に至る実験プロセス
  • 個人開発者の思考プロセス

    • macOSの謎のshape mismatchエラーとの格闘
    • 生成AIとのペアプログラミングでスピード開発を実現した方法
    • MLOps初心者が陥りがちな落とし穴とその回避策
  • 開発効率化のノウハウ

    • Hydra + MLflow + Gradioによる実験サイクル高速化
    • ローカル・クラウド環境の透過的な連携手法
    • 目的別分析ツールによる効果的なフィードバックループ

こんな方に特におすすめ

  • 個人でAI・機械学習プロジェクトを始めたい方
  • MLOpsの実践例を具体的に知りたい方
  • Vertex AIでの開発を検討している方
  • クラウド費用を抑えながら効率的に開発したい方
  • 趣味プロジェクトを本格的な開発に昇華させたい方

本記事で共有した、プロトタイピングからMLOps化、クラウド化そして体系的な精度改善に至るまでの一連のプロセスが、同じようにAIで身の回りの課題を解決したいと考える開発者にとって、何かのヒントとなれば幸いである。

GitHubで編集を提案

Discussion