Pythonで画像認識をするときは、学習済みモデルで推論するところから始め、足りなければ自前の画像で転移学習します。使うライブラリは「どれか1つ」ではなく、学習はPyTorch、画像の読み込みと前処理はOpenCV、学習済みモデルはtorchvision・timm・Ultralytics、本番の推論はONNX Runtime、というように役割ごとに組み合わせます。本記事では2026年11月5日時点のPyPI最新版をもとに、画像認識の手順、役割別のライブラリの選び方、商用利用でつまずくライセンス、OSやCPUの違いで入らない組み合わせを整理し、PyTorch 2.15で動作を確認したコードを示します。
まとめ:Pythonで画像認識をする手順とライブラリの要点
- 手順は「学習済みモデルで推論→自前の画像で転移学習→ONNXで書き出し」。最初から学習させず、まず既存モデルで足りるかを確かめます。
- 学習フレームワークは迷ったらPyTorch(2.15.0)。timm・Ultralytics・Hugging Face Transformersなど画像系の主要なモデル集がPyTorchを前提にしています。2.15からPython 3.11以上が必要です。
- TensorFlowを選ぶ理由は既存資産とKeras 3。Keras 3はJAX・TensorFlow・PyTorchに対応し、組み込み層やバックエンド非依存APIで書いたモデルは後からバックエンドを替えられます。
- 前処理はOpenCV 5.0。ただし5.0ではHaar Cascade(
cv2.CascadeClassifier)が標準パッケージからcontribへ移り、古い入門記事の顔検出コードはそのままでは動きません。 - Ultralytics YOLOとAlbumentationsXはAGPL-3.0。クローズドな製品に組み込む前に、ライセンスの線引きを必ず確認します。
- 旧Albumentations(2025年7月)とLabelImg(2024年2月)はアーカイブ済み。新規案件ではtorchvisionのtransforms.v2とLabel Studioを使います。
- 本番推論はONNXに書き出してONNX Runtimeで動かすと、学習側のフレームワークに縛られません。
画像認識ライブラリの役割分担:学習・前処理・モデル集・推論の4層
「画像認識 ライブラリ」で検索すると、OpenCVとTensorFlowとPyTorchが同列に並べて比較されがちです。実際には担当する層が違うため、同列には比べられません。本記事ではOpenCVを画像入出力・前処理、TensorFlowやPyTorchをディープラーニングの学習に使います。ただし、役割は排他的ではなく、OpenCVにも従来型機械学習の機能があり、5系ではMLモジュールがcontribへ移されています。まず層ごとに候補を絞ります。
| 層 | ライブラリ | 最新版(PyPI) | ライセンス |
|---|---|---|---|
| 学習 | PyTorch(torch) | 2.15.0 | BSD-3-Clause系 |
| 学習 | TensorFlow | 2.21.0 | Apache-2.0 |
| 学習(高水準API) | Keras | 3.15.1 | Apache-2.0 |
| 学習(従来型の機械学習) | scikit-learn | 1.9.1 | BSD-3-Clause |
| 前処理 | OpenCV(opencv-python) | 5.0.0.93 | Apache-2.0 |
| 前処理 | Pillow | 13.0.0 | MIT-CMU |
| データ拡張 | AlbumentationsX | 2.6.0 | AGPL-3.0/商用 |
| モデル集 | torchvision | 0.29.2 | BSD |
| モデル集 | timm | 1.0.31 | Apache-2.0 |
| モデル集(検出) | Ultralytics | 8.4.202 | AGPL-3.0/Enterprise |
| モデル集 | Transformers | 5.22.1 | Apache-2.0 |
| アノテーション | Label Studio | 1.23.2 | Apache-2.0 |
| 推論 | ONNX Runtime | 1.31.1 | MIT |
版はいずれも2026年11月5日にPyPIのJSON APIで確認した値です。Ultralyticsはほぼ毎日新しい版が出るため、導入時はpip index versions ultralyticsで最新を確かめてください。scikit-learnは、手書き数字のような小さな画像の画素値をそのまま特徴量として扱い、従来型の機械学習で分類するときの選択肢です。写真のように画素数が多い画像では、ディープラーニングの方が精度を出しやすくなります。
Pythonで画像認識をする手順:推論から転移学習・書き出しまで
画像認識の開発を、最初からモデルを一から学習させる作業だと考える必要はありません。公開されている学習済みモデルで足りるかを先に確かめ、足りない部分だけを自前の画像で学習させる順に進めると、必要な画像の枚数も計算資源も小さく済みます。Pythonでの作業は次の6段階です。
- 環境を作る:Python 3.11以上の仮想環境に
torch・torchvision・opencv-pythonを入れます。Intel Macは最新のtorchが入らないため、後述の動作環境の章を先に確認します。 - 学習済みモデルで推論する:torchvisionのResNetなどImageNetで学習済みのモデルに画像を通し、上位の分類結果を見ます。認識したい対象がImageNetの1,000クラスに含まれるなら、ここで終わることもあります。
- 画像を集めてラベルを付ける:分類なら
train/クラス名/画像とval/クラス名/画像のフォルダに分けるだけで、torchvisionのImageFolderが読み込めます。物体検出なら矩形のラベル付けが必要なので、Label Studioを使います。 - 転移学習する:学習済みモデルの特徴抽出部を固定し、出力層だけを自分のクラス数に差し替えて学習させます。数百枚の画像でも、CPUで数分の学習から始められます。
- 検証データで評価する:学習に使っていない画像で正解率を測ります。精度が足りなければ、画像の追加、データ拡張、特徴抽出部も含めた再学習(ファインチューニング)の順に手を打ちます。
- 書き出して推論に組み込む:ONNX形式に書き出し、ONNX Runtimeで推論します。推論サーバーや端末にPyTorch本体を入れずに済みます。
手順2・6と手順4は、記事後半の「動作確認済みコード」の章にそれぞれ実行できる形で載せています。画像認識の仕組みや業種別の活用例、開発会社に依頼するときの進め方は画像認識AIとは?仕組み・できること・開発の進め方をわかりやすく解説で扱っています。手順3〜5の学習データ作りと精度の追い込みを外部に任せる場合は、一創の画像認識AIモデル構築でも相談を受け付けています。
学習フレームワークの選び方:PyTorchとTensorFlow・Keras 3
PyTorch 2.15とtorchvision 0.29:画像系モデル集の前提
新規に学習コードを書くならPyTorchを選びます。理由はフレームワーク単体の性能差ではなく、周辺のモデル集がPyTorchで作られていることです。timm、Ultralytics、Hugging Face Transformersの画像モデルはいずれもPyTorchを依存先に持ち、論文の公式実装もPyTorchで公開されることが多いため、最新モデルを試すまでの距離が短くなります。
2026年10月28日に公開されたPyTorch 2.15では、リリースノートによると、Python 3.10向けのwheelが配布されなくなり、PyPIのGPU版の既定がCUDA 13.2になりました。CUDA 12.6や13.0の環境を使い続けるなら2.14に固定します。Apple SiliconのGPU(MPS)は2.15からmacOS 15以上が必要で、macOS 14ではtorch.backends.mps.is_available()がFalseを返します。
torchvision 0.29の公式ドキュメントは、前処理とデータ拡張に従来のtorchvision.transformsではなくtorchvision.transforms.v2を使うよう推奨しています。v2はバウンディングボックスやマスクも画像と同時に変換できるため、物体検出やセグメンテーションでも別ライブラリを足さずに済みます。PyTorch自体の特徴はPyTorchとは?読み方・できること・TensorFlowとの違いと入れ方【2.14対応】で詳しく扱っています。
TensorFlow 2.21とKeras 3.15:マルチバックエンド化後の位置づけ
Keras 3は、JAX・TensorFlow・PyTorchのいずれかの上で動くAPIです。TensorFlow 2.16からはKeras 3が既定のKerasになりました。Kerasの組み込み層やkeras.opsなどで構成したモデルはバックエンドを切り替えられます。ただし、TensorFlow固有の演算や学習ループを使う部分は移植が必要です。
TensorFlowを選ぶ理由が残るのは、既存のTensorFlowモデルやTFXの運用基盤がある場合と、既存のTensorFlowからLiteRTへの変換経路を継続する場合です。LiteRTにはPyTorchモデルの公式変換経路もあるため、端末への配布だけを理由にTensorFlowへ変更する必要はありません。TensorFlowを選んだうえで標準的な画像分類や転移学習を実装するなら、まずKerasの高水準APIを使います。独自の学習ループや勾配計算が必要な部分では、TensorFlowの低水準APIを検討します。KerasとTensorFlowの関係はKerasとは?読み方・TensorFlowとの違いとKeras 3の使い方【3.15対応】、LiteRTへの変換はTensorFlow Lite(LiteRT)とは?改称後の位置づけ・モデル変換・NPU実行を実装目線で解説を参照してください。
動作環境の落とし穴:Intel MacとネイティブWindowsで起きること
ライブラリ選定で見落とされやすいのが、開発機のOSとCPUです。PyPIに公開されている最新版のwheel(ビルド済みパッケージ)を確認すると、対応プラットフォームに次の差があります。
| パッケージ | Intel Mac | Apple Silicon | Windows | Linux |
|---|---|---|---|---|
| torch 2.15.0 | なし | あり | あり | あり |
| tensorflow 2.21.0 | なし | あり | あり | あり |
| onnxruntime 1.31.1 | なし | あり | あり | あり |
| opencv-python 5.0.0.93 | あり | あり | あり | あり |
Intel Macではpip install torchが最新版を入れられず、古い版を明示して入れることになります。古いtorchはNumPy 1系でビルドされている一方、OpenCV 5系のwheelはNumPy 2以上を要求するため、同じ環境に両方の最新を同居させられません。Intel Macで開発しているなら、学習と推論はLinuxのクラウド環境やDocker上で行う方が早く片付きます。本記事のコードも、Intel Mac上のDocker(Linux)で最新版を動かして確認しました。
WindowsでGPU学習をする場合も注意が必要です。TensorFlowの公式インストールガイドは、ネイティブWindowsでGPUに対応した最後の版を2.10とし、2.11以降はWSL2へ入れるよう案内しています。PyTorchはネイティブWindowsでもCUDA版を入れられるため、Windows機でGPUを使うならPyTorchの方が手間は少なくなります。
前処理とデータ拡張のライブラリ:OpenCV 5.0・Pillow・transforms.v2
OpenCVとPillowの使い分け:BGR順とHaar Cascadeの削除
画像の読み込み・リサイズ・色変換・カメラや動画からのフレーム取得はOpenCVが担います。Pythonで画像を読み込むだけなら、OpenCVはcv2.imread("a.jpg")、PillowはImage.open("a.jpg")の1行です。2026年6月6日にリリースされたOpenCV 5.0では、dnnモジュールが型付きの演算グラフを土台にしたエンジンへ作り直され、軽い推論であればOpenCV単体でONNXモデルを動かせます。
色順に注意が必要です。cv2.imreadは、既定のカラー読み込みでは画素をBGRの順で返します。torchvisionやtimmの学習済み重みはRGBを前提に学習されているため、そのまま渡すと赤と青が入れ替わった画像で推論することになります。後述のコードではcv2.cvtColorでRGBに直してから渡しています。
もう1つ、OpenCV 5.0ではHaar Cascadeによる顔検出(cv2.CascadeClassifier)が標準パッケージから外れ、公式の移行ガイドのとおりopencv_contribのxobjdetectモジュールへ移りました。opencv-python 5.0系を入れた環境でhasattr(cv2, "CascadeClassifier")を確かめるとFalseが返り、「Pythonで画像認識」の入門記事で今も定番のカスケード分類器のコードはAttributeErrorで止まります。contrib版のopencv-contrib-python(5.0.0.93)を入れるとcv2.CascadeClassifierは戻りますが、4系まで同梱されていたhaarcascade_frontalface_default.xmlなどの学習済みファイルはcv2.dataのフォルダに入っておらず、別途用意しないと読み込みに失敗します。新しく書くなら顔検出はYuNet(cv2.FaceDetectorYN)を使い、既存コードを手を入れずに動かすだけならpip install "opencv-python<5"で4系に留めます。OpenCVの基本操作と5.0での変更点はOpenCVとは?Pythonでの使い方入門|pip installから画像処理・顔検出まで【5.0対応】、カスケード分類器のような古典的手法とディープラーニングの使い分けは画像処理AIとは?古典的手法とディープラーニングの使い分けを実装判断で解説にまとめています。
Pillowは画像の開閉や簡単な加工に限れば十分で、torchvisionのデータセットも内部でPillowを使います。2026年10月16日公開の13.0.0では多数の脆弱性が修正されており、13.0.0未満の環境は更新の対象です。13系はPython 3.11以上が必要です。利用者がアップロードした画像を自動で開く処理がある場合は、Pillow 脆弱性:CVE-2026-96639ほか13.0.0で直った43件の確認とPython 3.10の更新手順で影響範囲を確認してください。
Albumentationsの保守終了とAlbumentationsX・transforms.v2
データ拡張の定番だったAlbumentationsは、公式リポジトリが2025年7月10日にアーカイブされ、READMEにも保守を終了した旨が記載されています。PyPIの最終版は2025年5月27日公開の2.0.8です。後継として同じチームが開発しているAlbumentationsXは、ライセンスがMITからAGPL-3.0と商用ライセンスの二本立てに変わりました。
既存コードでimport albumentationsを使っている場合、そのまま動き続けますが、新しいPythonやNumPyへの追随は期待できません。新規案件では、まずtorchvisionのtransforms.v2で足りるかを確かめ、足りない変換が必要になったときにAlbumentationsXのライセンス条件を確認してから採用する順番が安全です。後述の転移学習のコードも、データ拡張はtransforms.v2だけで書いています。
学習済みモデル集:torchvision・timm・Ultralytics・Transformers
画像分類の土台にするtorchvisionとtimm
画像分類で転移学習をするなら、torchvisionの学習済みモデルから始めるのが最短です。ResNet・EfficientNet・ViTなど代表的な構造が、重みと前処理の設定込みで提供されています。
より多くの構造を比べたいときはtimmを使います。timm 1.0.31を入れてtimm.list_models()を実行すると、登録されているアーキテクチャは1,371種、pretrained=Trueで数えた学習済み重みのタグは1,826件でした。同じtimm.create_model("名前", pretrained=True)の1行で構造を差し替えられるため、精度と速度の比較実験に向きます。
物体検出のUltralytics YOLO:共通APIとAGPL-3.0の条件
物体検出・セグメンテーション・姿勢推定を共通のCLIやPython APIで試したい場合は、Ultralyticsを候補にします。学習・評価・推論・エクスポートが1つのCLIとPython APIにまとまっており、ONNXやTensorRT形式への書き出しも同じAPIで行えます。
ただしUltralyticsはAGPL-3.0で、社内システムやSaaSに使う場合でも公式のライセンス案内ではEnterprise Licenseの対象として挙げられています。検出モデルの選択肢自体を比べたい場合は物体検出とは?仕組み・代表手法の比較から実装判断までエンジニア向けに解説を、ライセンスの考え方は次章を参照してください。
Hugging Face Transformers 5系:ViT・DETR系と画像言語モデル
Transformers(5.22.1)は自然言語処理の印象が強いものの、ViTやDETR系の画像モデル、画像と文章を同時に扱うモデルも同じAutoModel系のAPIで読み込めます。Hugging Face Hubに公開されたモデルをそのまま試せる点が強みで、「画像を説明文にする」「画像について質問に答える」といったタスクはtorchvisionやtimmではなくこちらの守備範囲です。
ライセンスで選ぶ:商用製品に組み込む前に確認すること
画像認識のライブラリ選定で、技術面より後から問題になりやすいのがライセンスです。表の大半はApache-2.0・BSD・MITで、商用製品に組み込んでもソースコードの公開義務はありません。AGPL-3.0を採るUltralyticsとAlbumentationsXは重点確認の対象です。ただし、表はライブラリ本体のライセンスであり、学習済み重みの条件まで保証しません。timmなどで読み込む重みは、モデルカードや配布元のライセンスを別途確認します。timmのREADMEは、ImageNetが非商用の研究目的で公開されたデータセットであることを挙げて重みの商用利用には法的な確認を勧めており、FacebookのWSL・SSL・SWSL系ResNeXtの重みは明示的に非商用(CC-BY-NC 4.0)だと記しています。
同じAGPL-3.0でも、両者の公式の説明は線引きが違います。Ultralyticsのライセンスページは、プロジェクト全体をAGPL-3.0で公開せずに使う場合はEnterprise Licenseが必要だとし、その対象に「Internal business tools or private company applications」「SaaS platforms, APIs, or cloud systems that use YOLO behind the scenes」を挙げています。一方AlbumentationsXのREADMEは「Commercial, proprietary, internal, or production status alone does not require a commercial license.」と書き、社内利用や本番利用という事実だけでは商用ライセンスは不要という立場です。
実務では、次の順で判断します。
- 製品として配布する、または外部向けSaaSで提供する予定があるなら、Ultralyticsは学習・推論の両方でEnterprise Licenseの見積もりを先に取る。
- 見積もりが合わなければ、MITやApache-2.0で公開されている検出モデル(RT-DETRの公式実装、YOLOv9のMIT版など)を候補にする。
- AlbumentationsXは、配布やネットワーク経由の提供の形を法務と確認してから採用する。迷うならtransforms.v2で代替する。
検出モデルごとのライセンスの違いはRT-DETRとは?読み方・仕組み・YOLOとの違い・ライセンスとv2〜v4の比較とYOLOv9のGitHub実装3種の選び方|MIT版・GPL版のライセンスと実行手順で比較しています。
アノテーションツール:LabelImgの開発終了とLabel Studio
独自データで学習するには、画像に正解ラベルを付けるアノテーションが必要です。かつて定番だったLabelImgは、公式リポジトリが2024年2月29日にアーカイブされ、READMEで開発の終了とLabel Studioコミュニティへの合流が案内されています。PyPIの最終版は2021年10月の1.8.6です。
新規ではLabel Studio(1.23.2・Apache-2.0)を使います。pip install label-studioで入り、ブラウザ上で分類・矩形・ポリゴン・キーポイントのラベル付けを行い、YOLO形式やCOCO形式で書き出せます。画像分類だけなら、クラス名のフォルダに画像を振り分ければラベル付けは済みます。ラベルの定義の決め方や作業者間の一致率の測り方はデータラベリングとは?ラベル設計・一致率・自動化を実装目線で解説を参照してください。
推論と配布のライブラリ:ONNX Runtime・LiteRT・OpenCV dnn
学習したモデルを本番で動かす段階では、配布サイズや実行先の制約に応じて、学習に使ったフレームワークを持ち込むかを決めます。PyTorchやKerasのモデルをONNX形式に書き出し、ONNX Runtimeで推論すれば、推論サーバーにPyTorch本体を入れずに済み、コンテナや端末へ配る容量を抑えられます。
- ONNX Runtime:CPU版は
onnxruntime、GPU版はonnxruntime-gpuで、CPU版とどちらか一方だけを入れます。CUDA Execution Providerの要件によると、1.27以降のPyPIのGPU版はCUDA 13.0でビルドされています。CUDA 12系を使う場合は別配布の対応パッケージを選び、CUDA 12.8以上を用意します。インストール手順のページには「12.x since 1.19.0」という古い記述が残っているため、要件ページの表を正としてください。1.31系はPython 3.11以上が必要です。 - LiteRT:Android・iOS・マイコンなど端末側で動かす場合の選択肢です。TensorFlowのモデルに加え、PyTorchのモデルもLiteRT Torchで
.tflite形式に変換できます。 - OpenCV dnn:前処理と推論をOpenCVだけで完結させたい、依存を最小にしたい場合に使います。
PyTorchの公式ドキュメントでは、torch.onnx.exportの書き出し方式としてdynamo=Trueが推奨かつ既定になっており、既定値はPyTorch 2.9で切り替わりました。この方式はonnxscriptパッケージを使うため、pip install --upgrade onnx onnxscriptを先に実行しておきます。ONNXファイルの中身や変換時のつまずきはONNXとは?読み方・.onnxファイルの中身・変換とONNX Runtimeでの推論【onnx 1.23/ORT 1.31対応】で解説しています。
動作確認済みコード:学習済みモデルの分類・転移学習・ONNX変換
手順の章の2・4・6を、それぞれ単体で動くコードにしました。どちらも次のコマンドで入れた環境で実行し、掲載の出力を得ています。CPU版のPyTorchだけを入れるため、PyTorchのCPU用配布先を指定しています。画面表示を使わないサーバーやコンテナでは、OpenCVはGUI機能を省いたopencv-python-headlessを入れます。手元のPCでcv2.imshowを使うならopencv-pythonに替えてください。
# 確認した環境:Docker の python:3.12-slim(Linux x86_64・CPUのみ)で次の2行を実行
pip install --index-url https://download.pytorch.org/whl/cpu torch torchvision
pip install opencv-python-headless onnx onnxscript onnxruntime
# torch 2.15.0 / torchvision 0.29.2 / opencv 5.0.0 / onnx 1.23.2 / onnxscript 0.7.2 / onnxruntime 1.31.1 / numpy 2.5.4
学習済みResNet18による分類とONNX Runtimeとの出力差の確認
OpenCVで画像を読み、torchvisionの学習済みResNet18で分類し、ONNXに書き出してONNX Runtimeで同じ結果が出るかを確かめます。実行前に、分類したい画像を作業ディレクトリへdog.jpgという名前で保存してください。初回実行では学習済み重みをダウンロードするため、ネットワーク接続も必要です。掲載出力の再現には、PyTorch Hubのimagesディレクトリにあるdog.jpgを作業ディレクトリに保存して使います。
import cv2
import numpy as np
import torch
from torchvision.models import resnet18, ResNet18_Weights
weights = ResNet18_Weights.DEFAULT
model = resnet18(weights=weights).eval()
preprocess = weights.transforms() # 重みと対になる前処理(リサイズ・正規化)
bgr = cv2.imread("dog.jpg") # OpenCVはBGR順で読む
if bgr is None: # 読めないときはNoneが返る
raise FileNotFoundError("dog.jpg を作業ディレクトリに置いてください")
rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB) # 学習済み重みはRGB前提
x = preprocess(torch.from_numpy(rgb).permute(2, 0, 1)).unsqueeze(0)
with torch.no_grad():
probs = model(x).softmax(dim=1)[0]
top = probs.topk(3)
for p, i in zip(top.values, top.indices):
print(weights.meta["categories"][i], f"{p:.3f}")
# ONNXへ書き出し、ONNX Runtimeで推論結果を照合する
torch.onnx.export(model, (x,), "resnet18.onnx",
input_names=["input"], output_names=["logits"])
import onnxruntime as ort
sess = ort.InferenceSession("resnet18.onnx", providers=["CPUExecutionProvider"])
logits = sess.run(None, {"input": x.numpy()})[0]
with torch.no_grad():
ref = model(x).numpy()
print("max diff:", np.abs(logits - ref).max())
PyTorchのHubリポジトリにあるサンプル画像(サモエドの写真)で実行した出力は次のとおりです。
Samoyed 0.883
white wolf 0.047
Arctic fox 0.045
max diff: 9.536743e-06
この画像1枚では、PyTorchとONNX Runtimeのlogitsの最大絶対差は約0.0000095でした。書き出しはPyTorch 2.9以降の既定であるdynamo方式で行われ、実行中に[torch.onnx] Obtain model graphから始まる進捗が表示されます。この入力で出力が近いことは確認できますが、モデル全体の変換精度を評価するには複数の検証画像と許容誤差を用意します。重みのダウンロードを含めた実行時間は約18秒でした。
自前の画像による転移学習:アリとハチの2クラス分類
自分で集めた画像で学習させる例です。PyTorchの公式チュートリアルが配布しているhymenoptera_data.zip(アリとハチの写真)を展開して使います。中身はtrain/ants・train/bees・val/ants・val/beesのフォルダ構成で、自前の画像も同じ形に並べればそのまま読み込めます。学習済みResNet18の特徴抽出部の重みを固定し、出力層だけを2クラスに差し替えて3周学習させます。
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.models import resnet18, ResNet18_Weights
from torchvision.transforms import v2
torch.manual_seed(0)
weights = ResNet18_Weights.DEFAULT
train_tf = v2.Compose([
v2.RandomResizedCrop(224), v2.RandomHorizontalFlip(), # データ拡張
v2.ToImage(), v2.ToDtype(torch.float32, scale=True),
v2.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
train_ds = datasets.ImageFolder("hymenoptera_data/train", transform=train_tf)
val_ds = datasets.ImageFolder("hymenoptera_data/val", transform=weights.transforms())
train_dl = DataLoader(train_ds, batch_size=16, shuffle=True)
val_dl = DataLoader(val_ds, batch_size=32)
print("classes:", train_ds.classes, "train:", len(train_ds), "val:", len(val_ds))
model = resnet18(weights=weights)
for p in model.parameters():
p.requires_grad = False # 学習済みの特徴抽出部は固定する
model.fc = nn.Linear(model.fc.in_features, len(train_ds.classes)) # 出力層だけ差し替える
opt = torch.optim.SGD(model.fc.parameters(), lr=0.001, momentum=0.9)
loss_fn = nn.CrossEntropyLoss()
for epoch in range(3):
model.train()
for x, y in train_dl:
opt.zero_grad()
loss_fn(model(x), y).backward()
opt.step()
model.eval()
correct = 0
with torch.no_grad():
for x, y in val_dl:
correct += (model(x).argmax(1) == y).sum().item()
print(f"epoch {epoch + 1}: val acc {correct / len(val_ds):.3f}")
torch.save(model.state_dict(), "ants_bees_resnet18.pt")
実行した出力は次のとおりです。
classes: ['ants', 'bees'] train: 244 val: 153
epoch 1: val acc 0.856
epoch 2: val acc 0.765
epoch 3: val acc 0.941
なお、requires_grad = Falseで止まるのは重みの更新だけです。model.train()の間は、特徴抽出部にあるBatchNorm層の平均・分散の統計値は学習データに合わせて更新されます。統計値も学習済みのまま使いたい場合は、学習ループのmodel.train()の直後で、nn.BatchNorm2dの層だけに.eval()を呼び直します。
学習用244枚・検証用153枚で、3周目の検証データの正解率は94.1%になりました。コンテナから見える論理CPU数は4で、3周の学習と評価にかかった時間は約54秒でした(CPUの型番で大きく変わります)。2周目で76.5%に下がっているように、この規模のデータでは1周ごとの正解率が大きく上下します。実務では最後の周ではなく、検証データの正解率が最も高かった周の重みを保存する処理を加えます。精度が足りなければ、画像を増やすか、model.layer4など出力に近い層の固定を外して小さい学習率で再学習します。
よくある質問
Pythonで画像認識をするなら、まずどのライブラリを入れればよいですか?
PyTorch・torchvision・OpenCVの3つです。この3つで画像の読み込み、学習済みモデルでの分類、転移学習まで一通り試せます。物体検出をすぐに試したい場合はUltralyticsを足しますが、商用利用の予定があるならライセンスを先に確認してください。
TensorFlowとPyTorchはどちらを選ぶべきですか?
新規ならPyTorchです。画像系の主要なモデル集がPyTorchを前提にしているためです。既存のTensorFlow資産や運用基盤を引き継ぐ場合はTensorFlowとKeras 3を選びます。LiteRTへの配布はPyTorchからも可能なので、それだけでTensorFlowを選ぶ必要はありません。Keras 3の組み込み層やバックエンド非依存APIで実装すれば、バックエンドを後から切り替えられます。
OpenCVだけで画像認識はできますか?
学習済みのONNXモデルを推論させるだけなら、OpenCVのdnnモジュールで可能です。ただしOpenCVにはディープラーニングの学習機能が無いため、独自データで学習するにはPyTorchやTensorFlowが必要です。また、OpenCV 5.0ではHaar Cascadeによる顔検出が標準パッケージからcontribへ移ったため、カスケード分類器を使う古いコードは、4系に固定するか、contrib版と学習済みファイルを用意して移行する必要があります。
画像認識の学習には何枚の画像が必要ですか?
転移学習なら、数百枚から始められます。本記事の例は学習用244枚・検証用153枚の2クラス分類で、検証データの正解率は3周目で94.1%でした。必要な枚数はクラスの見分けにくさで変わるため、少ない枚数で一度学習させ、検証データの正解率を見ながら足していくのが確実です。
YOLOは商用利用できますか?
Ultralytics版のYOLOはAGPL-3.0で、ソースを公開しない商用製品・社内システム・SaaSで使う場合は、公式案内ではEnterprise Licenseが必要とされています。ライセンス費用を避けたい場合は、MITやApache-2.0で公開されている別の検出モデルを検討してください。
GPUが無くても画像認識ライブラリは使えますか?
使えます。PyTorch・TensorFlow・ONNX RuntimeはいずれもCPU版があり、学習済みモデルでの推論ならCPUで十分に動きます。本記事のコード例は、転移学習も含めてCPUのみで実行しました。特徴抽出部も含めた再学習や、物体検出モデルの学習は計算量が大きいため、クラウドのGPUインスタンスを検討してください。