画像を分類が PyTorch + fastai で簡単にできることがわかったのでその覚え書きです。
PyTorch + fastai だけでなく、 Lobe( https://www.lobe.ai/ ) や Google Vision AI にしてもそうですが、 無料で画像分類を試すことができます。 もう、この程度のことでは、誰も驚かない時代になった。
PyTorch, fastai はローカル環境にセットアップされていることが前提。
プロジェクト用のディレクトリを作成して、その中に images, test_images の二つのディレクトリを作成。
$ mkdir myproj
$ cd myproj
$ mkdir images
$ mkdir test_images
images ディレクトリには、画像分類を学習するためのお手本画像を用意します。 たとえば、有名な Caltech101 http://www.vision.caltech.edu/Image_Datasets/Caltech101/ を使うなど。
学習用の画像を images ディレクトリに配置するには、分類したい種類の画像ごとにサブディレクトリをつくります。 このように:
images/
├── cat
│ ├── 0060dfb7f9a468b5.jpg
│ ├── 00bdb008eb688497.jpg
~~~~~~
│ ├── 43293d56f1e626e2.jpg
│ └── 438118dbd16f942f.jpg
└── dog
├── 056_0001.jpg
├── 056_0002.jpg
~~~~~~
├── 056_0003.jpg
└── 056_0102.jpg
ここでは cat, dog のサブディレクトリを作成してそこに、猫の画像と犬の画像を入れています。 cat, dog のサブディレクトリ名がそのまま分類ラベルになるので、 必要に応じてそれとわかるより具体的なラベル名に変更しましょう。
test_images/ 以下には、機械学習させた分類器が実際意図通り画像を分類できるか試すための 画像を配置します。
ここでは test_images/my-dog.jpg があることとして説明します。
それではコードです。 学習と分類テストまで一度に実行します。
from fastai.vision.core import PILImage
from fastai.vision.all import *
import os
#
# ボイラープレート
#
def current_dir():
return os.getcwd()
def create_dls(path):
db = DataBlock(
blocks=(ImageBlock, CategoryBlock),
get_items=get_image_files,
splitter=RandomSplitter(valid_pct=0.2, seed=42),
get_y=parent_label,
item_tfms=Resize(128))
db_new = db.new(
item_tfms=RandomResizedCrop(224, min_scale=0.5),
batch_tfms=aug_transforms())
return db_new.dataloaders(path)
def learn(path):
dls = create_dls(path)
learn = cnn_learner(dls, resnet18, metrics=error_rate)
learn.fine_tune(4)
return learn
def predict(l,imagepath):
img = PILImage.create(imagepath)
what,_,probs = l.predict(img)
return f"{what} / {probs[1].item():.6f}"
#
# アプリケーション
#
targetdir = current_dir()+"/images"
cat_or_dog_detector = learn(targetdir)
testimagepath = current_dir()+"/test_images/my-dog.jpg"
result = predict(cat_or_dog_detector, testimagepath)
print(result)
実行すると、(うまく分類できた場合)機械学習が実行されたあと、dog と標準出力されます。
$ python3 main.py
epoch train_loss valid_loss error_rate time
0 1.243636 1.787962 0.421053 00:03
epoch train_loss valid_loss error_rate time
0 0.554540 0.938709 0.289474 00:02
1 0.536315 0.195117 0.105263 00:02
2 0.418964 0.078628 0.052632 00:02
3 0.328747 0.052011 0.000000 00:02
dog / 0.999295
分類する対象が数種類ならば、環境にもよりますが、30秒程度で処理が終わります。 しかし、1000種類とかになれば、どうなのでしょう。相当かかるのかもしれません。 さらに、つくった分類器が十分な精度が出ているのか(検証)とか、 十分な精度が出ていない場合に、なにをどう変更したら精度が出るようになるのかなど、それらがコントロールできるようになってはじめて、まともに使える状態になる、といったところでしょうか。
しかし、分類対象となる画像の種類があらかじめ固定されていないといけない、 もし種類を追加したい場合また学習させる必要があるなど、 この程度のことができても、実践的な応用への道のりは遠い。