2025年はワイン画像識別と共に始まり、そして暮れゆく

Date:

Share post:

2025年最初の投稿は「Ubuntu22.04にPostgreSQL17をインストールしてみた」(1月30日)でした。
これは後々種明かしをしたように、ワインボトル画像のエンベディング結果(ベクトル)を対象とする検索を目的としたもので、最終的にはベクトル相互の距離が一定の値以下であれば同じ被写体(ワイン)であると判別するような仕組みを構築するための第一歩でした。

以来、様々な紆余曲折を経て現在に至る訳ですが、今年最後の投稿として、この1年の活動内容を総括して締めたいと思います。

第1章:ワインボトル画像による識別(1〜3月)

まずはPostgreSQLやPythonの環境を構築して、画像データをエンベディングした結果から、画像間の「距離」(コサイン距離)を算出できるようにしました(画像検索)。

エンベディングにはResNet50を使用していますが、この辺はGemini先生のお勧めをそのまま受け入れています。
後から他のモデルに関しても試してみてはいますが(画像検索の精度確認(2))、大差はないようだったのでResNet50をそのまま使い続けています。

当初は画像データのエンベディングとベクトル検索という一般的なテーマで試行錯誤を行なっていましたが、精度を向上させるためには画像の構図が重要ということが分かってきたので、対象をワイン(正確にはワインボトル)に限定しつつ、構図を合わせるために背景削除とトリミングを行うようにしました(画像検索の精度確認(3))。

また、撮影条件による画像の色合いの影響も大きいようだったので、その影響を排除する方法としてヒストグラム平坦化を試してみたりしています(画像検索の精度確認(4))。

上記施策を通して、手元にある少ないデータではある程度の成果が出せるようになったので、弊社サイト(https://wine.swailife.com/)にある大量のデータに関して識別を試みましたが、結果は惨憺たるもので、改めてワインボトル画像での識別に限界を感じるに至りました(画像検索の精度確認(5))。

第2章:ワインラベル画像の抽出(3〜7月)

ResNet50の入力画像サイズは224×224であり、この解像度でワインの特徴を十分に表現するためには、被写体をワインボトル全体ではなくラベル(エチケット)部分に限定する必要があると考えましたが、そのためには元画像からラベル部分のみを抽出する方法が必要になります。
その方法が「セマンティックセグメンテーション」でした(ラベル画像のトリミング(1))。

「U-Net」という構造を持ち、ラベルを含む元画像と、ラベル部分とそれ以外を白黒2色で色分けしたマスク画像のセット(画像マスクペア)を使って学習することで、様々なワインラベル画像からラベル部分を機械的に抽出できるセグメンテーションモデルを生成することが、この段階での目標でした(ラベル画像のトリミング(2))。
しかし、当初は思ったような成果は上げられませんでした(ラベル画像のトリミング(3))。

やはり、機械学習においてはデータの質と量は重要な模様で、まずはその点を改善しています。
特に、学習に用いる画像においては、ラベル部分の占有面積の割合が重要だったようで、その辺を調整した画像を新たに調達することで、質と量の問題を解決しました。
また、当初はハイパーパラメータの調整には及び腰だったのですが、特に「学習率」の調整は結果に大きく影響するようだったので、その辺に関しても試行錯誤を行なっています(ラベル画像のトリミング(4))。

また、データ量に関しては、どうしても調達に限界があるので、データ拡張を行うことで量と質の両面で水増しを行なっています(ラベル画像のトリミング(6))。

上記取り組みにより、ラベル部分を(ある程度納得できる精度で)抽出するセマンティックセグメンテーションモデルが生成できました。

第3章:ラベル画像に特化した特徴抽出器の生成(7〜11月)

ラベル画像が用意できるようになったので、改めてResNet50でエンベディングを実施してみましたが、相変わらず精度的には不十分なものでした(ラベル画像のエンベディング)。

ResNet50は様々な種類の画像を対象とするものであり、それらの中では「ラベル画像」自体が一つの類似した画像のグループであり、その中でさらに個々のラベルを区別しようとするのは無理があります。
よって、ResNet50をラベル識別専用のモデルとして改造する必要がありました。
その方法が「ファインチューニング」でした(ファインチューニング(1))。

ここで実施しているのは「深層距離学習(Deep Metric Learning)」というもので、あるラベル画像(アンカー)に対して、同じラベルの別画像(ポジティブ)と別ラベルの画像(ネガティブ)を組み合わせた3点セットのデータ(トリプレット)を用意し、ベースモデル(ResNet50)に対して、アンカー・ポジティブの距離を最小化し、かつアンカー・ネガティブの距離を最大化するようにパラメータを最適化することがチューニングの目的です。

こちらも、最初は満足できる成果は上げられなかったのですが、ハードサンプル中心にトリプレットを構成したり、データ拡張を駆使したりすることで、ある程度の精度向上は達成しました(ファインチューニング(3))。
しかし、及第点と呼べるレベルにはなかなか至らず、その後もハイパーパラメータの操作などを行いながら試行錯誤を繰り返していくことになります。

第4章:ベースモデルの変更(11月〜)

試行錯誤を続けること約3ヶ月、誤差レベルの精度改善しか望めない状況の中でCursor・Gemini両先生から提案されたのが、ベースモデルのEfficientNetV2Lへの変更でした。
EfficientNetV2LはResNet50よりも新しいモデルで、扱う画像サイズも384×384と大きく、それだけで期待が持てるものでした(一方で学習に要する時間は長くなりましたが)。

EfficientNetV2Lは、オリジナルのままではResNet50よりもラベル画像の識別精度が劣っていましたが、ファインチューニングにより格段に精度が向上(つまりラベル識別という限定した用途に適合)し、試験的に実施した最初のチューニングにおいて既にResNet50よりも良好な成果を出しています(ResNet50からEfficientNetV2Lへ!ファインチューニングの新章)。

また、この段階までは曖昧に扱ってきたモデルの「精度」ですが、改めてF1スコア、Fβスコアなどの標準的な指標を採用することで、ハイパーパラメータの調整結果の良し悪しを数値的に判定できるようにしました(ハイパーパラメータ調整:ファインチューニング新章(2))。

その後、継続的にハイパーパラメータの調整や学習方法の変更などを実施しながら、現在に至ります。

最新の状況

前述したように、モデルの「精度」は数値で判断したいと考えていますが、どの数値を採用するかに関しては悩ましいところでした。
F1スコア・Fβスコアいずれに関しても、これら数値が最良となる閾値(距離)を基準にした場合、適合率(つまり同じワインである確率)は100%ではありません。

適合率100%となる閾値を採用したとしても、それはあくまで手持ちのデータの範囲での話であって、新規画像に対しても100%の精度でワインを識別できる保証はありませんが、それでも最初からある程度の間違いがあり得る前提の閾値を採用するメリットが思いつきませんでしたので、現在は適合率100%の閾値を基準に再現率を向上させていく方針で調整を行なっています。

なお、前回の投稿で紹介したモデルにおける適合率100%時の再現率=0.6536ですが、内訳を見てみると大半は訓練用データであって、検証用・テスト用データに限定すれば再現率=0.0714と極端に低い値でした。
つまり、完全な過学習状態です。
よって、単にハイパーパラメータを調整するだけでなく、過学習を抑制するための施策が必要となります。
この点に関しては、Cursor先生と相談しながら以下のような改修を行なっています。

  1. オプティマイザをAdamからAdamWに変更 : 正則化の適正化
    特定のデータに強く依存しすぎることを防ぐために重みが大きくならないように制限する「L2正則化」をより確実に実施し、モデルをシンプルに保ちます。
  2. Projection Headの追加 : 情報の整理・洗練
    学習時のノイズ(枝葉の情報)を削り、本質的な特徴だけを捉えやすくします。
  3. 勾配クリッピングの導入 : 暴走(破壊)の防止
    局所的なデータに過剰反応してモデルが壊れるのを防ぎ、着実な学習を促します。
  4. Batch NormalizationのFreeze : 基準(物差し)の固定
    少ないデータに対してモデルの判断基準がブレるのを防ぎ、学習を安定させます。
    本来、Batch Normalizationはデータの偏りを整える「物差し」の役割を果たしますが、学習データが少ないとその物差し自体が変動してしまい、計算が狂う原因になります。
    そこで、あえて学習済みモデルの「完成された物差し」を固定して使うことで、土台を安定させ、新しい知識を効率よく吸収できるようになります。

ちなみに上記解説はGemini先生談ですが…今ひとつ良く分かりませんね。
で、良く分からないまま実装したら、精度が極端に悪くなってしまいました。orz
距離0.01未満のネガティブが多く残ってしまい、一方で、それ以上にポジティブとの距離が縮まっているという印象もありません。

直感的には、1のAdamWの採用には精度を大きく変えるような影響力はなさそうなので、原因は2〜4のいずれか(複数が関係している可能性もあり)と思っていますが、今のところ切り分けができていません。
あれこれと一気に詰め込み過ぎたのが仇となりました。

この辺は来年の課題としておきます。

2026年の抱負

2026年も、まずは前述したような観点で特徴抽出器の精度アップを続けますが、それだけでは限界がありそうです。
そもそも1つの特徴抽出器の結果のみで判断する必要はありませんので、違った観点に特化した特徴抽出器を複数組み合わせて判定を行うようなシステムを目指すのは面白そうです(目指せ「MAGIシステム」)。

現時点の構想としては、以下のような特徴抽出器を考えています。

文字・絵柄の識別に特化した特徴抽出器

現在の特徴抽出器の出力において、どうしても「色」の影響が大きいと感じるケースがあります。
違うラベルでも色が似通っていると距離が小さくなったり、逆に同じラベルでも撮影条件などの影響で色合いが違っていると距離が大きくなったりするようです。
色の要素を除外すれば、もっと文字や絵柄の識別に重点を置いて学習が進むようになるかもしれません。

色を無視するのは簡単で、元画像をグレースケール化すれば良いですし、ついでにヒストグラム平坦化なども行うと良いかもしれません。
注意点としては、色が違うだけで文字・絵柄が同じラベル(当然ながら別のワイン)というものもあるため、これを学習データに組み込んでしまうと極めて難易度の高いネガティブとなるため、訓練に悪影響がありそうです。
よって、データの取捨選択が必要になりそうです。

いずれにしても、現在育成中の特徴抽出器とは違った観点でエンベディングを行ってくれる存在にはなりそうです。

ボトル画像を対象した特徴抽出器

最初の頃に挫折したアプローチに戻るような話ですが、あくまで合議制での判定を前提とした場合、一票を投じる役割は担えるのではないかと思っています。

ワインによってはボトルの色が重要になる場合もあります。
過去の投稿(ファインチューニング(2))で触れた下記ケースですが、ラベルだけでは区別がつかなくてもボトルの色では簡単に区別できます。

上記のようなケースを考えると、ラベル以外の部分も考慮した特徴抽出器があれば、ラベルに特化した特徴抽出器が見落とす観点を補う存在になりそうです。

なお、ボトル画像と言っても、以前のようにボトル全体を写した画像を期待している訳ではありません。
あくまで上記例のようにラベルを中心に写した画像に対して、ラベル部分のみではなく、ボトル部分も含めた抽出を行い、それを学習対象とするということです。
識別に使用する画像はあくまで1つで、それを異なる観点で加工し、それぞれの観点に特化した特徴抽出器でエンベディングした結果を既存のデータと比較し、総合的な判定を下すことが目的です。

蛇足ながら、上記の実現のためには、ボトル部分を切り出すセマンティックセグメンテーションモデルを用意する必要もありそうです。

まとめ

当初、画像素材としてマウスの写真を撮っていた頃を考えると、随分遠くまで来たものだと感慨深いです。
まだまだ道半ばではありますが。

最初の頃は、AI(機械学習)は難しそうなので既製品(ResNet50等)を使うだけで目的を達成しようと目論みましたが、甘かったですね。
結局はセマンティックセグメンテーションにファインチューニングと、機械学習に取り組む日々となりました。

機械学習はおろか、Pythonもまともに使ったことがない状況からここまで来られたのは、ひとえにGemini先生のおかげです。
最初はWebのGemini先生が生成したロジックを切り貼りしていましたが、昨今はCursor先生(でも中身はGemini先生だったりする)に直接ファイル生成や更新をお願いできるようになったので、ただ要求をするだけで作業が進んで行きます。
何とも凄い時代になったものです。

開発環境に関しても Mac mini(M4)、通称「弁当箱」で何とかなっています。
曲がりなりにもGPUを使った学習ができていますし。
ただ、VRAMはもっと多い方が良さそうですが(現状、結構カツカツです)。

今後もAIは益々進化し、プログラムの開発から中身まで、AI無しでは語れなくなってくるでしょう。
プログラマ人生も終焉に差し掛かっていますが、もう少しだけAIと戯れてみたいと思います。

では皆様、良いお年を。

Related articles

Packerを使用してVagrant Boxを作成...

久しぶりの投稿になってしまいました・・...

マルチポイント対応のイヤホンが便利すぎる

スマートフォンで音楽を聴きながら仕事...