2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【初心者必読】VGG16を動かしたいなら、まずはColabが正解です。

Posted at

#〜本記事でわかること〜

・VGG16の実装方法

#1.はじめに

「わたしの備忘録」 兼 「初心者向け」の内容です。

・Deep Learningって分かんないけど、とにかく動かしたい!
・原理とかは後回し、実装方法だけ知りたい!

って方は、ぜひ読んでみてください!
(Qiitaの旧アカウントから持ってきました…)

#2.動作環境
動作環境は以下の通り。

・Windows 10
・Google Colab
・TensorFlow ver.2.3

今回はGoogle Colabにて
コーディングしていくので、
OSとかは特に関係ないです。

ネット環境だけ整ってれば、とりあえずオーケー!
便利な時代になりました。

#3.前準備

本記事で取り上げるVGG16というモデルは、
深層学習の中でも「画像の分類」が得意です。

なので、まずは皆さんに
自前のデータを用意してほしいんです。

わたしはマーベル作品が大好きなので、
「キャプテンアメリカ」
「アイアンマン」
「ハルク」
「ソー」
の画像を用意しました!

画像の枚数は適当でいいのですが、
手始めに各50枚ほど用意してみましょう。

用意できましたら、
VGG16が学習しやすいように
フォルダを作っていきます。

というわけで、
以下のようにフォルダを作ってください。

    image/
       ├ train/
       │    ├ captain/
       │    ├ ironman/
       │    ├ hulk/
       │    └ thor/   
       │
       ├ valid/
       │    ├ captain/
       │    ├ ironman/
       │    ├ hulk/
       │    └ thor/   
       │
       └ test/
            ├ captain/
            ├ ironman/
            ├ hulk/
            └ thor/   

そうしましたら、
「train」・「valid」・「test」フォルダの
各「captain」・「ironman」・「hulk」・「thor」フォルダに
画像を入れていきます。

各ヒーローごとに50枚あるので、
「train」に30枚、「valid」に10枚、「test」に10枚
入れていきます。

なので、全体の画像配置は
train:150枚
valid: 50枚
test : 50枚
になりますね。

前準備はこれで終了。

#4.実装
###4−1 まずは、Google Driveへ

Google Colabでコーディングしていくのですが
そのためにも、まずGoogle Driveへ移動します。

みなさん、現代っ子のはずなので、
Googleアカウントは、さすがに持ってますよね??
(無ければこの際に作っちゃいましょ!)

Googleアカウントにログインできましたら、
Google Driveへアクセス。

先程作った「image」フォルダをアップロードします。

###4−2 実際にコードを書いてみよう

現時点では、おそらくGoogle Colabが
インストールされていないと思うので、

下に示した図のようにインストールしていきます。

###4−3 学習開始!

それでは、学習していきましょう。
まずは、Google DriveとGoogle Colabを接続します。

from google.colab import drive
drive.mount('/content/drive')

そして、VGG16のモデルを作成していきます。

import matplotlib
import numpy as np
%matplotlib inline
from tensorflow.python.keras.callbacks import TensorBoard
from tensorflow.python.keras.applications.vgg16 import VGG16

vgg16 = VGG16(include_top=False, 
              input_shape=(224, 224, 3),
              weights='imagenet')

クラスの設定をします。
ここは皆さんの用意したデータによって変えてください。

import random
classes = ['captain', 'ironman', 'hulk', 'thor']

モデルの生成とコンパイルをします。
compileのパラメータに「loss」や「optimizer」や「metrics」がありますが
これらをイジることで、解きたいタスクを変えたり、学習を収束させやすくできます。
今回は以下の値で学習させていきましょう。

from tensorflow.python.keras.models import Sequential, Model
from tensorflow.python.keras.layers import Dense, Dropout, Flatten, GlobalAveragePooling2D
from tensorflow.keras.optimizers import SGD

def build_transfer_model(vgg16):
  model = Sequential(vgg16.layers)
  for layer in model.layers[:15]:
    layer.trainable = False
  model.add(Flatten())
  model.add(Dense(256, activation='relu'))
  model.add(Dropout(0.5))
  model.add(Dense(len(classes), activation='softmax'))
  return model

model = build_transfer_model(vgg16)

model.compile(loss='categorical_crossentropy',
              optimizer=SGD(lr=1e-5, momentum=0.9),
              metrics=['accuracy']
)

ジェネレータとイテレータを生成します。
カンタンに言うと、画像の拡張やスケール変換をしています。
この処理を挟むことで、1枚の画像からでも複数枚の画像を生成することができるのです。

人間の目で見れば、「ただ左右反転したり、斜めにしてみた画像じゃん?」ってなるんですが、
学習モデルにとっては、ピクセル単位で処理していくため、違う画像に見えるわけですね。

from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
from tensorflow.python.keras.applications.vgg16 import preprocess_input

idg_train = ImageDataGenerator(rescale=1/255.,
                               shear_range=0.1,
                               zoom_range=0.1,
                               horizontal_flip=True,
                               preprocessing_function=preprocess_input
)

idg_valid = ImageDataGenerator(rescale=1/255.)

img_itr_train = idg_train.flow_from_directory(directory='/content/drive/My Drive/image/train/',
                                              target_size=(224, 224),
                                              color_mode='rgb',
                                              classes=classes,
                                              batch_size=1,
                                              class_mode='categorical',
                                              shuffle=True
)

img_itr_validation = idg_valid.flow_from_directory(directory='/content/drive/My Drive/image/valid/',
                                                   target_size=(224, 224),
                                                   color_mode='rgb',
                                                   classes=classes,
                                                   batch_size=1,
                                                   class_mode='categorical',
                                                   shuffle=True
)

モデル保存用のディレクトリの準備をします。

import os
from datetime import datetime

model_dir = os.path.join('/content/drive/My Drive/image/',
                         datetime.now().strftime('%y%m%d_%H%M')
)

os.makedirs(model_dir, exist_ok = True)
print('model_dir:', model_dir)

dir_weights = os.path.join(model_dir, 'weights')
os.makedirs(dir_weights, exist_ok = True)

学習の途中経過を保存したり、保存方法を設定します。

from tensorflow.python.keras.callbacks import CSVLogger, ModelCheckpoint
import math
file_name='vgg16_fine'
batch_size_train=1
batch_size_validation=1

steps_per_epoch=math.ceil(img_itr_train.samples/batch_size_train
)
validation_steps=math.ceil(img_itr_validation.samples/batch_size_validation
)

cp_filepath = os.path.join(dir_weights, 'ep_{epoch:02d}_ls_{loss:.1f}.h5')

cp = ModelCheckpoint(cp_filepath,
                     monitor='loss',
                     verbose=0,
                     save_best_only=False,
                     save_weights_only=True,
                     mode='auto',
                     save_freq=5
)
csv_filepath = os.path.join(model_dir, 'loss.csv')
csv = CSVLogger(csv_filepath, append=True)

そして、ついに学習です。「epochs」を50に設定しているので、学習回数は50回です。

※厳密には学習回数とepochは同じ意味ではないのですが、
今回は支障がないので名前を統一しています。

hist=model.fit_generator(
    img_itr_train,
    steps_per_epoch=steps_per_epoch,
    epochs=50,
    verbose=1,
    validation_data=img_itr_validation,
    validation_steps=validation_steps,
    shuffle=True,
    callbacks=[cp, csv]
)

model.save(file_name+'.h5')

コーディングが終わったので、
上からソースコードを実行していきます。

以下が途中経過の一例になります。
これが「Epoch 50/50」まで続きます。
それが学習終了の合図です。

Epoch 1/50
80/80 [==============================] - 18s 228ms/step - loss: 1.2106 - accuracy: 0.5000 - val_loss: 1.2738 - val_accuracy: 0.3500
Epoch 2/50
80/80 [==============================] - 22s 276ms/step - loss: 1.0407 - accuracy: 0.5875 - val_loss: 1.1765 - val_accuracy: 0.5000
Epoch 3/50
80/80 [==============================] - 34s 419ms/step - loss: 0.9078 - accuracy: 0.6375 - val_loss: 1.2011 - val_accuracy: 0.5500
Epoch 4/50
80/80 [==============================] - 31s 387ms/step - loss: 0.9747 - accuracy: 0.5625 - val_loss: 1.2541 - val_accuracy: 0.5000

###4−4 結果は・・・??

さて、学習は終了しましたが、
まだ不完全です。

それもそのはず。
大学生に例えれば「講義」を受けて「課題」を
解いたにすぎないからです。

ある一定の評価(=単位)をもらうには、
「試験(テスト)」が残っています。

といわけで、次のコードを実行しましょう。

import matplotlib.pyplot as plt
from tensorflow.python.keras.preprocessing.image import load_img, img_to_array, array_to_img

idg_test = ImageDataGenerator(rescale=1.0/255)

img_itr_test = idg_test.flow_from_directory(directory='/content/drive/My Drive/image/test/',
                                            target_size=(224,224),
                                            batch_size=1,
                                            class_mode='categorical',
                                            shuffle=True
)

score=model.evaluate_generator(img_itr_test)
print('\n test loss:',score[0])
print('\n test_acc:',score[1])

plt.figure(figsize=(10,15))

for i in range(4):
  files=os.listdir('/content/drive/My Drive/image/test/' + classes[i] + '/')
  for j in range(5):
    temp_img=load_img('/content/drive/My Drive/image/test/' + classes[i] + '/' + files[j], target_size=(224,224))
    plt.subplot(4,5,i*5+j+1)
    plt.imshow(temp_img)
    temp_img_array=img_to_array(temp_img)
    temp_img_array=temp_img_array.astype('float32')/255.0
    temp_img_array=temp_img_array.reshape((1,224,224,3))
    img_pred=model.predict(temp_img_array)
    plt.title(str(classes[np.argmax(img_pred)]) + '\nPred:' + str(math.floor(np.max(img_pred)*100)) + "%")
    plt.xticks([]),plt.yticks([])

plt.show()

結果は、こんな感じ。

 test loss: 1.0708633661270142
 test_acc: 0.550000011920929

全体の精度にして、__55%__となりました。
まぁ、まずまずといったところでしょうか。

それではもっと詳しく見ていきます。
各画像の予測結果はこんな感じ。

Screenshot from 2020-11-30 15-34-52.png

うん、アイアンマンの正答率がいい感じ。
アイアンマンが好きな私としては嬉しい結果です〜♪

画像枚数を増やしたり、パラメータや学習回数などをいじれば
もっと精度は向上するでしょうが・・・
今日のところはお開きとしたいです。

#5.おわりに

いかがでしたか??
原理などは一切説明しませんでしたが、
少しでもAIに関して興味をもってもらえると嬉しいです。

本記事では、VGG16の実装方法を紹介しましたが、
実はこのモデル、結構古いんですよね・・・。
(2015年に論文が執筆されています。詳しくはこちら。)

今は新しく精度の高いモデルも
たくさん出ているので、興味がある方は
ぜひ試してみてください!

では、よいAIライフを〜 ^^

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?