【初心者向け】Flask と深層学習を使って数字画像判定サービスを作ってみよう!

目次

  • 自己紹介
  • まえがき
  • ゴール
  • Docker と Docker Compose とは
  • GAE / FE とは
  • Flask とは
  • TensorFlow とは
  • Keras とは
  • Colaboratory とは
  • 技術構成
  • 数字画像を学習
  • Python 環境の準備 ( Docker、Docker Compose )
  • Flask の実装
  • 動作確認
  • デプロイ
  • あとがき

自己紹介

こんにちは、私は株式会社ピケの古内です。

普段サーバサイドの開発を行っております。

Twitter - https://twitter.com/furuuchin

note - https://note.mu/furuchin

まえがき

この記事では以下が前提になっています。

  • Python の基礎をやったことがある
  • 深層学習の基礎をやったことがある
  • 簡単な Linux コマンドを使ったことがある

「深層学習はやってみたけどサービスにどうしたらできるの?」と思っている方のための記事です。

以下の技術で作ります。

  • Docker
  • Docker Compose
  • Google App Engine Flexible Environment ( GAE / FE )
  • Python 3.6
  • Flask
  • Keras
    • Colaboratory
    • TensorFlow

この構成にした経緯

現在 ( 2018/ 08 /28 ) Keras が Python 3.7 に対応しておらず Python 3.6 を使うことになりました。

しかし、Google App Engine Standard Environment ( GAE / SE ) の Python は 3.7 バージョンのみでした。

そのため GAE / SE での動作を諦めて柔軟に対応できる GAE / FE で Python 3.6 で実装する事になりました。

ゴール

今回はこんなものを作って見ようと思います!

このサービスは数字の画像がなんの数字か判定してくれるシンプルなサービスです。 それでは作ってみましょう!!

Docker と Docker Compose とは

Docker は動作環境を構築してくれるツールです。

Docker のメリットは個々の違うコンピュータに同じ環境を簡単に用意できることです。

例えば Python の環境や MySQL の環境など様々な環境を簡単に用意できます。

Docker Compose は Docker で作った個々の環境 ( Python、MySQL ) を連携させるツールです。

今回の記事の内容以外にも Ruby on Rails にも使ったりすることも出来ます。

Docker と Docker Compose のダウンロードリンクです。

Docker : https://docs.docker.com/install/

Docker Compose : https://docs.docker.com/compose/install/

GAE / FE とは

GAE / FE とは Google App Engine Flexible Environment の略で、世の中にサービスを公開するためのコンピュータとして利用します。

Flask とは

Flask とは Python の Web フレームワークの一つです。

特徴としてはシンプルな設計なので初心者でもわかりやすいです。

Python には他にも Web フレームワークがあり、代表的なフレームワークには Django というものがあります。

TensorFlow とは

Google が作った深層学習のためのライブラリです。

Keras とは

Keras とは TensorFlow という深層学習ライブラリを使いやすくしたライブラリです。

Colaboratory とは

Colaboratory とは無料で深層学習できるプラットフォームです。

Jupyter と呼ばれるブラウザで Python ができるものに似ています。

この記事だと Keras で書かれたコードを学習します。

数字画像を学習

数字画像を判定するために機械学習をします。 ( 参考 : https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py )

Google ドライブを開き、「新規」をクリックします。

フォルダを選択し、フォルダ名を「数字画像学習」で作成します。

「数字画像学習」フォルダを開きます。

開いたら「新規」をクリックしてその他の中の「アプリを追加」をクリックします。

検索に「colaboratory」と入力して検索します。

Colaboratory が出てくるので「接続」をクリックします。接続が完了したら検索を閉じます。

右クリックをしてその他の中の「Colaboratory」をクリックします。

しばらくするとこの画面が表示されます。

表示されたらランタイムの中の「ランタイムのタイプの変更」をクリックします。

「Python 3」と「GPU」を選択して保存します。

設定したらこのコードをコピーして貼り付けます。

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
import google.colab
import googleapiclient.discovery
import googleapiclient.http

batch_size = 128
num_classes = 10
epochs = 12

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

model.save('model.h5')

google.colab.auth.authenticate_user()
drive_service = googleapiclient.discovery.build('drive', 'v3')

saving_filename = "model.h5"

file_metadata = {
  'name': saving_filename,
  'mimeType': 'application/octet-stream'
}
media = googleapiclient.http.MediaFileUpload(saving_filename,
                        mimetype='application/octet-stream',
                        resumable=True)
created = drive_service.files().create(body=file_metadata,
                                       media_body=media,
                                       fields='id').execute()

貼り付けたら実行ボタンをクリックします。

実行すると URL が表示されるのでクリックします。

Colaboratory を使っているアカウントを選択します。

許可をクリックします。

長い文字列をコピーします。

貼り付けて Enter キーを押します。

学習が完了するとこうなります。

Google ドライブの「マイドライブ」内に model.h5 ファイルをダウンロードしておきます。

コードの解説

深層学習に必要なライブラリのインポート

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
import google.colab
import googleapiclient.discovery
import googleapiclient.http

Colaboratory に学習した成果物を保存するためのライブラリをインポート

import google.colab
import googleapiclient.discovery
import googleapiclient.http

深層学習の設定

batch_size = 128
num_classes = 10
epochs = 12

画像の準備

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

ニューラルネットワークの構築

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

学習と学習の結果

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

学習した成果物を Google ドライブに保存

model.save('model.h5')

google.colab.auth.authenticate_user()
drive_service = googleapiclient.discovery.build('drive', 'v3')

saving_filename = "model.h5"

file_metadata = {
  'name': saving_filename,
  'mimeType': 'application/octet-stream'
}
media = googleapiclient.http.MediaFileUpload(saving_filename,
                        mimetype='application/octet-stream',
                        resumable=True)
created = drive_service.files().create(body=file_metadata,
                                       media_body=media,
                                       fields='id').execute()
Takahiro Furuuchi

Takahiro Furuuchi

@furuuchin

株式会社ピケでサーバサイドエンジニアをしております。得意な技術は Python や Docker、GCP です。Frasco、Dish、Codespot を作っています。