Home About
fastai , pytorch , Python

画像分類 PyTorch + fastai 覚え書き

画像を分類が 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種類とかになれば、どうなのでしょう。相当かかるのかもしれません。 さらに、つくった分類器が十分な精度が出ているのか(検証)とか、 十分な精度が出ていない場合に、なにをどう変更したら精度が出るようになるのかなど、それらがコントロールできるようになってはじめて、まともに使える状態になる、といったところでしょうか。

しかし、分類対象となる画像の種類があらかじめ固定されていないといけない、 もし種類を追加したい場合また学習させる必要があるなど、 この程度のことができても、実践的な応用への道のりは遠い。