2
2

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 1 year has passed since last update.

KerasでCIFAR-10の画像分類をやる【①基礎】

Posted at

対象読者:CNNを用いた画像分類の基本知識があり、Kerasを用いて実装をしたいと思っている人

CIFAR-10データセットとは

CIFAR-10データセットは、32x32のカラー画像6万枚からなり、10クラス、各クラス6千枚の画像から構成されています。また、学習画像は5万枚、テスト画像は1万枚あります。

(参考:CIFAR-10 and CIFAR-100 datasets

データセットの画像の一例を以下に示します。
example_cifar10.png

実装環境

Google Colaboratoryの無料版を用いています。
Google ColaboratoryはGoogleが提供するJupyter notebook環境です。
また、Pythonのバージョンは3.7
Kerasのバージョンは2.1です。

実装

必要なモジュールのインポート

import numpy as np
import matplotlib.pyplot as plt

from keras.datasets import cifar10
from keras.utils.np_utils import to_categorical
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPool2D
from keras.layers import Dense,Activation,Dropout,Flatten
from keras.layers import BatchNormalization

データセットの読込と前処理

# CIFAR-10データセットをダウンロード
(x_train,y_train), (x_test,y_test) = cifar10.load_data()

# 画像を0~1の範囲で正規化
x_train = x_train.astype('float32')/255.0
x_test = x_test.astype('float32')/255.0

# 正解ラベルをOne-Hotベクトルに変換
y_train = to_categorical(y_train,10)
y_test = to_categorical(y_test,10)

print(x_train.shape, y_train.shape)
出力
(50000, 32, 32, 3) (50000, 10)

モデルの構築

Kerasではモデルの記述方法として、いくつかありますが、今回は一番簡単なSequentialで記述します。

今回のモデルのアーキテクチャ(構成)は、CNN-BN-ReLU-CNN-BN-ReLU-Poolをブロックとしたものを2つ繋げ、その後全結合層に接続しています。
モデルの損失関数には、多クラス分類であるため、交差エントロピーを採用しています。
また、最適化関数にはAdamを採用しています。最適化関数には他にSGDやRMSpropなどがありますが、経験的にAdamがおすすめです。

#モデルの構築
model = Sequential()

model.add(Conv2D(32,(3,3),padding='same',input_shape=(32,32,3)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(32,(3,3),padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

model.add(Conv2D(64,(3,3),padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(64,(3,3),padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(10,activation='softmax'))

model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])

#モデルの表示
model.summary()
出力画面
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 32, 32, 32)        896       
                                                                 
 batch_normalization (BatchN  (None, 32, 32, 32)       128       
 ormalization)                                                   
                                                                 
 activation (Activation)     (None, 32, 32, 32)        0         
                                                                 
 conv2d_1 (Conv2D)           (None, 32, 32, 32)        9248      
                                                                 
 batch_normalization_1 (Batc  (None, 32, 32, 32)       128       
 hNormalization)                                                 
                                                                 
 activation_1 (Activation)   (None, 32, 32, 32)        0         
                                                                 
 max_pooling2d (MaxPooling2D  (None, 16, 16, 32)       0         
 )                                                               
                                                                 
 conv2d_2 (Conv2D)           (None, 16, 16, 64)        18496     
                                                                 
 batch_normalization_2 (Batc  (None, 16, 16, 64)       256       
 hNormalization)                                                 
                                                                 
 activation_2 (Activation)   (None, 16, 16, 64)        0         
                                                                 
 conv2d_3 (Conv2D)           (None, 16, 16, 64)        36928     
                                                                 
 batch_normalization_3 (Batc  (None, 16, 16, 64)       256       
 hNormalization)                                                 
                                                                 
 activation_3 (Activation)   (None, 16, 16, 64)        0         
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 8, 8, 64)         0         
 2D)                                                             
                                                                 
 flatten (Flatten)           (None, 4096)              0         
                                                                 
 dense (Dense)               (None, 512)               2097664   
                                                                 
 activation_4 (Activation)   (None, 512)               0         
                                                                 
 dropout (Dropout)           (None, 512)               0         
                                                                 
 dense_1 (Dense)             (None, 10)                5130      
                                                                 
=================================================================
Total params: 2,169,130
Trainable params: 2,168,746
Non-trainable params: 384
_________________________________________________________________

モデルの学習

# モデルの学習
history = model.fit(x_train,y_train,
                    batch_size=128, # バッチサイズを128に設定
                    epochs=10, # エポック数を10に設定
                    verbose=1, #進捗状況をプログレスバーで表示
                    validation_split=0.1) # 訓練データの1割を検証データとして扱う
出力画面
Epoch 1/10
352/352 [==============================] - 17s 16ms/step - loss: 1.8556 - accuracy: 0.3420 - val_loss: 2.1067 - val_accuracy: 0.2288
Epoch 2/10
352/352 [==============================] - 5s 14ms/step - loss: 1.3924 - accuracy: 0.4909 - val_loss: 1.2452 - val_accuracy: 0.5358
Epoch 3/10
352/352 [==============================] - 5s 15ms/step - loss: 1.2152 - accuracy: 0.5603 - val_loss: 1.1623 - val_accuracy: 0.5936
Epoch 4/10
352/352 [==============================] - 5s 15ms/step - loss: 1.0994 - accuracy: 0.6016 - val_loss: 0.9856 - val_accuracy: 0.6396
Epoch 5/10
352/352 [==============================] - 5s 15ms/step - loss: 1.0258 - accuracy: 0.6324 - val_loss: 0.8176 - val_accuracy: 0.7106
Epoch 6/10
352/352 [==============================] - 6s 17ms/step - loss: 0.9742 - accuracy: 0.6509 - val_loss: 0.8058 - val_accuracy: 0.7172
Epoch 7/10
352/352 [==============================] - 5s 14ms/step - loss: 0.9245 - accuracy: 0.6684 - val_loss: 0.8620 - val_accuracy: 0.7020
Epoch 8/10
352/352 [==============================] - 5s 14ms/step - loss: 0.8831 - accuracy: 0.6843 - val_loss: 1.0213 - val_accuracy: 0.6504
Epoch 9/10
352/352 [==============================] - 5s 14ms/step - loss: 0.8554 - accuracy: 0.6920 - val_loss: 0.8039 - val_accuracy: 0.7184
Epoch 10/10
352/352 [==============================] - 5s 14ms/step - loss: 0.8128 - accuracy: 0.7072 - val_loss: 0.7428 - val_accuracy: 0.7446

学習結果の表示

# エポックごとの正解率とlossの取得
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

# エポック数の取得
epochs = range(len(acc))

# 正解率の表示
plt.plot(epochs, acc, label='acc')
plt.plot(epochs, val_acc, label='val_acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.show()

# lossの表示
plt.plot(epochs, loss, label='loss')
plt.plot(epochs, val_loss, label='val_loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()

accuracy_and_loss.png
エポック数が増えるにつれ、正解率は上がり、lossの値は小さくなっています。
今回は学習のエポック数10に設定しましたが、もっと学習させればより性能が上がることが期待できます。

テストデータを用いたモデルの評価

# 評価
loss,acc = model.evaluate(x_test,y_test,verbose=0)
print('Test loss:',loss)
print('Test accuracy:',acc)
出力画面
Test loss: 0.7661172151565552
Test accuracy: 0.7469000220298767

分類精度は正解率77%となりました。

ソースコード全体

import numpy as np
import matplotlib.pyplot as plt

from keras.datasets import cifar10
from keras.utils.np_utils import to_categorical
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPool2D
from keras.layers import Dense,Activation,Dropout,Flatten
from keras.layers import BatchNormalization

# CIFAR-10データセットをダウンロード
(x_train,y_train), (x_test,y_test) = cifar10.load_data()

# 画像を0~1の範囲で正規化
x_train = x_train.astype('float32')/255.0
x_test = x_test.astype('float32')/255.0

# 正解ラベルをOne-Hot表現に変換
y_train = to_categorical(y_train,10)
y_test = to_categorical(y_test,10)


#モデルを構築
model = Sequential()

model.add(Conv2D(32,(3,3),padding='same',input_shape=(32,32,3)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(32,(3,3),padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

model.add(Conv2D(64,(3,3),padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(64,(3,3),padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(10,activation='softmax'))

model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])

#モデルの表示
model.summary()


# モデルの学習
history = model.fit(x_train,y_train,
                    batch_size=128, # バッチサイズを128に設定
                    epochs=10, # エポック数を10に設定
                    verbose=1, #進捗状況をプログレスバーで表示
                    validation_split=0.1) # 訓練データの1割を検証データとして扱う


# エポックごとの正解率とlossの取得
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

# エポック数の取得
epochs = range(len(acc))

# 正解率の表示
plt.plot(epochs, acc, label='acc')
plt.plot(epochs, val_acc, label='val_acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.show()

# lossの表示
plt.plot(epochs, loss, label='loss')
plt.plot(epochs, val_loss, label='val_loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()


# 評価
loss,acc = model.evaluate(x_test,y_test,verbose=0)
print('Test loss:',loss)
print('Test accuracy:',acc)

関連記事

  • KerasでCIFAR-10の画像分類をやる【②モデルの保存と読み込み】
2
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?