メリークリスマス。皆さんいかがお過ごしでしょうか。ポンダッドです。

今回は、深層学習(ディープラーニング)の画像分類で主流となっている「畳み込みニューラルネットワーク(CNN、Convolutional Neural Network)」を利用して数字認識を試してみました。

なんだかもの凄く難しそうな感じがしますが、深層学習ライブラリ「Keras」と学習済みモデルを利用しますので気軽に試す事が出来ます。

さて、実際に試してみましょう。

私が手書きした数字の5(下手くそな字ですね)を人工知能に見せてみます。

手書き文字をバイナリ化しました。以前scikit-learnで試した時は8×8ピクセルだったのですが、今回は28×28ピクセルです。試しにCSVデータにしてエクセルで見てみましょう。

こんな感じでズラッと数字が784セル分並んでいます。0が黒で255が白となる256段階の数値が格納されています。

今回利用するモデルは、Kerasのメイン開発者François Cholletさんが公開しているmnist_cnn.py - GitHubを利用しました。

認識率99.25%というスコアを出しているモデルです。「畳み込みニューラルネットワーク」の構造はこの様になっています。

パッと見ただけでは何をしているのか良く分からないですが、元となる画像データを何層もフィルタをかけているのが見て取れます。

通常の機械学習では、特徴量を分類する仕組みを人間が指定しますが、深層学習ではデータから機械が自ら特徴量を学習していきます。

ここでは訓練データ60,000とテストデータ10,000を元した学習結果を元に、指定されたデータが何の数字を示すのか推測します。

1
2
3
4
5
$ python3 mnist_cnn2.py
Using TensorFlow backend.
1/1 [==============================] - 0s
テストラベル: 5
予測ラベル: 5

数字「5」を正しく判別できました。

プログラムは事前に学習したモデルを読み込んでいるので意外とコンパクトです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import numpy as np
np.random.seed(1337)
from keras.datasets import mnist
from keras.models import Sequential ,model_from_json
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
from PIL import Image
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, 28, 28, 1)
X_test = X_test.reshape(10000, 28, 28, 1)
input_shape = (28, 28, 1)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
Y_train = np_utils.to_categorical(y_train, 10)
Y_test = np_utils.to_categorical(y_test, 10)
model = model_from_json(open('mnist_cnn_model.json').read())
model.load_weights('mnist_cnn_weights.hdf5')
image = Image.open("test5.png").convert('L')
image = image.resize((28, 28), Image.ANTIALIAS)
data = np.asarray(image, dtype=float)
data = data.reshape(1, 28, 28, 1)
input_shape = (28, 28, 1)
data = data.astype('float32')
data /= 255
classes = model.predict_classes(data, batch_size=32)
print("テストラベル: ", "5")
print("予測ラベル: ", classes[0])

仕組み

上記の仕組みをざっくり説明するとこんな感じになります。

  • 訓練データとテストデータを読み込む
  • 学習済みモデルを読み込む
  • 予測データを読み込む
  • 学習済みモデルから予測する

もう少し詳しくまとめてみます。

訓練データとテストデータを読み込む

KerasではデフォルトでMNIST(エムニストって読むみたいですね。最近知った)データを読み込むことが出来ます。

こんなデータが訓練データ60,000・テストデータ10,000あります。これを白黒(1次元)28×28ピクセルで読み込みます。

1
2
3
4
5
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, 28, 28, 1)
X_test = X_test.reshape(10000, 28, 28, 1)
input_shape = (28, 28, 1)

ちょっと注意が必要なのが、学習しやすい型に事前に変換しなければならない点です。ここではfloat32型(浮動小数点数32ビット)に変換します。

色調256段階は計算しやすい様に0〜1に正規化します。(色調1200.470...となります)

また、ラベルとなる数字0〜9も計算しやすい様に、10次元へと正規化します。(ラベルの数字5は10次元配列に直すと[0,0,0,0,1,0,0,0,0,0]になります)

1
2
3
4
5
6
7
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
Y_train = np_utils.to_categorical(y_train, 10)
Y_test = np_utils.to_categorical(y_test, 10)

学習済みモデルを読み込む

上述のmnist_cnn.py - GitHubで事前に学習したモデルは以下を追記する事でデータ化(jsonファイルとhdf5ファイル)出来ます。

1
2
3
model_json_str = model.to_json()
open('mnist_cnn_model.json', 'w').write(model_json_str)
model.save_weights('mnist_cnn_weights.hdf5')

データ化した学習モデルは、

1
2
3
from keras.models import model_from_json
model = model_from_json(open('mnist_cnn_model.json').read())
model.load_weights('mnist_cnn_weights.hdf5')

この様に読み込み、そのまま再利用が可能だという訳です。

予測データを読み込む

手書き文字データをバイナリ化するのには画像処理データライブラリPILを利用しました。

1
2
3
4
from PIL import Image
image = Image.open("test5.png").convert('L')
image = image.resize((28, 28), Image.ANTIALIAS)
data = np.asarray(image, dtype=float)

画像を28×28ピクセル、白黒画像で読み込みnumpyfloat型にします。

学習モデルに合わせて正規化することで、予測データとして利用出来る様になります。

1
2
3
4
data = data.reshape(1, 28, 28, 1)
input_shape = (28, 28, 1)
data = data.astype('float32')
data /= 255

学習済みモデルから予測する

Kerasの特徴はこちらのブログでズバリまとめられています。

Kerasはレゴブロックを組み合わせるかのようにして、簡単にディープラーニングのモデルを作成できる便利なライブラリです。これを使って楽しく開発できるのではないかと思います。

Elix Tech Blog

「レゴブロック(!)」の様に、様々なメソッドが用意されています。ここで使用するmodel.predict_classes()メソッドなど、まさにそんな感じです。

Sequentialモデルの API - Keras Documentation

学習済みモデルに予測データを追加することで、そのラベルが何か推測してくれます。

1
classes = model.predict_classes(data, batch_size=32)

これだけです。

まとめ

深層学習ライブラリKerasの使い方を少しまとめてみました。

「畳み込みニューラルネットワーク」に関して、正直「ブラックボックスでいいや。」と思っていたのですが、中身にも興味が出てきたので少し学習してみようかな。と思っています。

機械に勉強させるのも楽じゃないですね(笑)。ではまた。

参考書籍

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 - Amazon.co.jp

はじめての深層学習(ディープラーニング)プログラミング - Amazon.co.jp

Pythonによるスクレイピング&機械学習 開発テクニック BeautifulSoup,scikit-learn,TensorFlowを使ってみよう - Amazon.co.jp