In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D
from keras.utils import np_utils
from keras.datasets import cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
Using TensorFlow backend.
In [2]:
plt.imshow(x_train[0])
print('x_train shape:', x_train.shape)
print('y_train shape:', y_train.shape)
print('x_test shape:', x_test.shape)
print('y_test shape:', y_test.shape)
df = pd.DataFrame(y_test)
df[0].unique() # カテゴリ数確認
x_train shape: (50000, 32, 32, 3)
y_train shape: (50000, 1)
x_test shape: (10000, 32, 32, 3)
y_test shape: (10000, 1)
Out[2]:
array([3, 8, 0, 6, 1, 9, 5, 7, 4, 2], dtype=int64)
In [3]:
# 入力画像を変換
X_train = x_train.reshape(x_train.shape[0], 32, 32, 3)    # Keras入力形式に変換
X_test = x_test.reshape(x_test.shape[0], 32, 32, 3)
# 32×32画素の画像3チャネル
X_train = X_train.astype('float32') / 255     # 各画素を0から1に正規化
X_test = X_test.astype('float32') /255

# onehot化
Y_train = np_utils.to_categorical(y_train, 10)
Y_test = np_utils.to_categorical(y_test, 10)

print('X_train shape:', X_train.shape)      # X_trainの配列形状
print('Y_train shape:', Y_train.shape)      # Y_trainの配列形状
print(X_train.shape[0], 'train samples')    # 訓練サンプル数
print(X_test.shape[0], 'test samples')      # 評価サンプル数
X_train shape: (50000, 32, 32, 3)
Y_train shape: (50000, 10)
50000 train samples
10000 test samples
In [4]:
plt.imshow(X_test[0].reshape([32, 32, 3]))    # 入力画像の例を表示
print(y_test[0])     # 正解データ (ラベル)
print(Y_test[0])     # 正解データ (確率の配列)
[3]
[0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
In [5]:
# CNNのモデルの作成
model = Sequential()

# 畳み込み
model.add(Conv2D(64, (3, 3), padding='SAME', activation='relu', input_shape=(32, 32, 3)))
model.add(Conv2D(64, (3, 3), padding='SAME', activation='relu'))
# 過学習防止
model.add(Dropout(0.25))
# 最大プーリング
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(128, (3, 3), padding='SAME', activation='relu'))
model.add(Conv2D(128, (3, 3), padding='SAME', activation='relu'))
model.add(Dropout(0.25))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(256, (3, 3), padding='SAME', activation='relu'))
model.add(Conv2D(256, (3, 3), padding='SAME', activation='relu'))
model.add(Dropout(0.25))
model.add(GlobalAveragePooling2D())

# 出力層
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(10, activation='softmax'))

model.summary()        # モデル情報の表示
WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:66: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:541: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:4432: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:148: The name tf.placeholder_with_default is deprecated. Please use tf.compat.v1.placeholder_with_default instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:3733: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.
Instructions for updating:
Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.
WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:4267: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 32, 32, 64)        1792      
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 32, 32, 64)        36928     
_________________________________________________________________
dropout_1 (Dropout)          (None, 32, 32, 64)        0         
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 16, 16, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 16, 16, 128)       73856     
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 16, 16, 128)       147584    
_________________________________________________________________
dropout_2 (Dropout)          (None, 16, 16, 128)       0         
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 8, 8, 128)         0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 8, 8, 256)         295168    
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 8, 8, 256)         590080    
_________________________________________________________________
dropout_3 (Dropout)          (None, 8, 8, 256)         0         
_________________________________________________________________
global_average_pooling2d_1 ( (None, 256)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               131584    
_________________________________________________________________
dropout_4 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                5130      
=================================================================
Total params: 1,282,122
Trainable params: 1,282,122
Non-trainable params: 0
_________________________________________________________________
In [6]:
batch_size = 128         # バッチサイズ(メモリ展開)
nb_epoch = 20            # 同じデータで繰り返し学習する回数
In [7]:
# 学習パラメータの設定
model.compile(loss='categorical_crossentropy',
              optimizer='adam', metrics=['accuracy'])

# モデルの学習
history = model.fit(X_train, Y_train,
                    batch_size=batch_size, epochs=nb_epoch,
                    validation_data=(X_test, Y_test))

# 学習結果の評価
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\optimizers.py:793: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:3576: The name tf.log is deprecated. Please use tf.math.log instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\tensorflow_core\python\ops\math_grad.py:1424: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where
WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:1033: The name tf.assign_add is deprecated. Please use tf.compat.v1.assign_add instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:1020: The name tf.assign is deprecated. Please use tf.compat.v1.assign instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:3005: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead.

Train on 50000 samples, validate on 10000 samples
Epoch 1/20
WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:190: The name tf.get_default_session is deprecated. Please use tf.compat.v1.get_default_session instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:197: The name tf.ConfigProto is deprecated. Please use tf.compat.v1.ConfigProto instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:207: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:216: The name tf.is_variable_initialized is deprecated. Please use tf.compat.v1.is_variable_initialized instead.

WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:223: The name tf.variables_initializer is deprecated. Please use tf.compat.v1.variables_initializer instead.

50000/50000 [==============================] - 701s 14ms/step - loss: 1.7896 - acc: 0.3025 - val_loss: 1.5344 - val_acc: 0.4418
Epoch 2/20
50000/50000 [==============================] - 658s 13ms/step - loss: 1.3008 - acc: 0.5161 - val_loss: 1.1354 - val_acc: 0.5975
Epoch 3/20
50000/50000 [==============================] - 578s 12ms/step - loss: 1.0570 - acc: 0.6153 - val_loss: 1.0274 - val_acc: 0.6570
Epoch 4/20
50000/50000 [==============================] - 557s 11ms/step - loss: 0.9083 - acc: 0.6744 - val_loss: 0.8812 - val_acc: 0.7001
Epoch 5/20
50000/50000 [==============================] - 551s 11ms/step - loss: 0.7876 - acc: 0.7196 - val_loss: 0.8049 - val_acc: 0.7206
Epoch 6/20
50000/50000 [==============================] - 548s 11ms/step - loss: 0.6971 - acc: 0.7566 - val_loss: 0.7395 - val_acc: 0.7405
Epoch 7/20
50000/50000 [==============================] - 556s 11ms/step - loss: 0.6314 - acc: 0.7812 - val_loss: 0.6897 - val_acc: 0.7623
Epoch 8/20
50000/50000 [==============================] - 561s 11ms/step - loss: 0.5695 - acc: 0.8018 - val_loss: 0.6450 - val_acc: 0.7791
Epoch 9/20
50000/50000 [==============================] - 543s 11ms/step - loss: 0.5123 - acc: 0.8212 - val_loss: 0.5922 - val_acc: 0.7967
Epoch 10/20
50000/50000 [==============================] - 543s 11ms/step - loss: 0.4713 - acc: 0.8344 - val_loss: 0.6081 - val_acc: 0.7904
Epoch 11/20
50000/50000 [==============================] - 630s 13ms/step - loss: 0.4305 - acc: 0.8486 - val_loss: 0.5835 - val_acc: 0.8023
Epoch 12/20
50000/50000 [==============================] - 729s 15ms/step - loss: 0.4028 - acc: 0.8591 - val_loss: 0.5516 - val_acc: 0.8115
Epoch 13/20
50000/50000 [==============================] - 767s 15ms/step - loss: 0.3580 - acc: 0.8762 - val_loss: 0.5499 - val_acc: 0.8136
Epoch 14/20
50000/50000 [==============================] - 749s 15ms/step - loss: 0.3302 - acc: 0.8840 - val_loss: 0.5181 - val_acc: 0.8254
Epoch 15/20
50000/50000 [==============================] - 756s 15ms/step - loss: 0.3010 - acc: 0.8951 - val_loss: 0.5662 - val_acc: 0.8060
Epoch 16/20
50000/50000 [==============================] - 767s 15ms/step - loss: 0.2793 - acc: 0.9013 - val_loss: 0.4878 - val_acc: 0.8329
Epoch 17/20
50000/50000 [==============================] - 829s 17ms/step - loss: 0.2487 - acc: 0.9113 - val_loss: 0.5421 - val_acc: 0.8245
Epoch 18/20
50000/50000 [==============================] - 862s 17ms/step - loss: 0.2338 - acc: 0.9181 - val_loss: 0.5109 - val_acc: 0.8329
Epoch 19/20
50000/50000 [==============================] - 705s 14ms/step - loss: 0.2158 - acc: 0.9238 - val_loss: 0.5339 - val_acc: 0.8249
Epoch 20/20
50000/50000 [==============================] - 706s 14ms/step - loss: 0.1924 - acc: 0.9324 - val_loss: 0.5560 - val_acc: 0.8284
Test score: 0.5559554067373276
Test accuracy: 0.8284
In [8]:
# 学習誤差グラフ
# 学習データ
plt.plot(history.history['loss'], label="loss")
# 評価データ
plt.plot(history.history['val_loss'], label="val_loss")
plt.title('Loss')
plt.legend()
plt.xlabel('epoch')
plt.yscale('log')
plt.show()

# 学習精度グラフ
# 学習データ
plt.plot(history.history['acc'], label="acc")
# 評価データ
plt.plot(history.history['val_acc'], label="val_acc")
plt.title('Accuracy')
plt.legend(loc="lower right")
plt.xlabel('epoch')
plt.show()
In [9]:
# モデルを用いた判別 (出力層のベクトル)
model.predict(X_test)[100]
Out[9]:
array([6.2956497e-07, 3.3304792e-09, 2.7416637e-03, 1.4897334e-04,
       9.8863018e-01, 1.9169938e-04, 6.7727909e-05, 8.2186284e-03,
       9.4639262e-08, 2.8939792e-07], dtype=float32)
In [10]:
# モデルを用いた判別 (ラベル)
model.predict_classes(X_test)[100]
Out[10]:
4
In [11]:
# モデルの保存と読み込み
model.save("cifar10_model.h5")
# モデルの読み込み
from keras.models import load_model
model = load_model("cifar10_model.h5")
In [12]:
# 手書き文字画像の読み込み
from PIL import Image
img = Image.open("./airplane.png")    # 画像ファイル読み込み
img = img.resize((32, 32))       # 32×32にリサイズ
img = img.convert('RGB')           # RGB化
im = np.array(img)                 # ndarray化
im = im.astype('float32') /255     # 0から1に正規化
plt.imshow(im)
Out[12]:
<matplotlib.image.AxesImage at 0x1ab8c9abcc8>
In [13]:
# 手書き文字画像の認識
im = im.reshape(1, 32, 32, 3)     # モデルの入力形式に変換
model.predict_classes(im)[0]       # モデルを用いた判別 (ラベル)
Out[13]:
0