LoginSignup
3
7

More than 3 years have passed since last update.

Kerasの使い方~簡単なモデル生成からCNNまで~

Posted at

この記事でやること

ディープラーニングでは、使用するバックエンドによって実装手順がことなる。そのため、公式のドキュメントを読み込んだり、解説している参考書などを参照しながら使い方を学んでいく。この記事ではその使い方の流れを説明している。

kerasを使った場合の実装手順

1.訓練データを定義する

2.入力値を目的値にマッピングする複数の層からなるネットワークを定義する。

3.損失関数、オプティマイザ、監視する指標を選択することで学習プロセスを設定する。

4.モデルのfitメソッドを呼び出すことで、訓練データを繰り返し学習する。

kerasのpython環境の構築

anaconda上に新しい仮想環境を作り、tensorflow及びkerasをインストールする。今後は作った環境の上で実行していく。anaconda prompt上で以下を実行する。

conda create -n keras_env python=3.6 #仮想環境の作成
conda activate keras_env #環境の切り替え
conda install tensorflow==1.12.0
conda isntall keras==2.2.4

具体的な手順

データセットの読み込み

from keras.datasets import imdb

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

データの前処理

データのベクトル化

ニューラルネットワークの入力値と目的値はすべて浮動小数点のデータのテンソルでなければならない。音声、画像、テキストなど、処理しなければならないデータがどのようなものであったとしても、まずそれらをテンソルに変換する必要がある。
クラス分類のラベルをベクトル化するにはone-hotエンコーディングを行う。

from keras.utils.np_utils import to_categorical

one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)

データの正規化

画像データは0~255の範囲のグレースケール値を表す整数としてエンコードされている。このデータをニューラルネットワークに供給するためには、float32型でキャストしてから255で割ることで0~1の範囲の浮動小数点に変換する。
ネットワークに範囲の異なる特徴量を供給するのはどう考えても問題である。そこで範囲を同じにするために正規化を行う。特徴量の平均値を引き、標準偏差で割るという処理を行う。そうすると、特徴量の中心が0になり、標準偏差が1になる。

モデルの定義

各層ごとに活性化関数とニューロン数を設定する。順伝播させたい順にadd()で追加していけば良い。

from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.add(Dense(200))
model.add(Activation("relu"))


モデルのコンパイル

オプティマイザと損失関数を選択する。以下の場合は文字列で指定しているが、これが可能なのはkerasの一部としてパッケージ化されているためである。

model.compile(optimizer='rmsprop',#文字指定
              loss='binary_crossentropy',
              metrics=['accuracy'])

オプティマイザのパラメータ引数を指定したい場合は以下のようにオプティマイザクラスのインスタンスを指定して、メソッドを呼び出す。

from keras import optimizers

model.compile(optimizer=optimizers.RMSprop(lr=0.001),#メソッド指定
              loss='binary_crossentropy',
              metrics=['accuracy'])

独自の損失関数や指標関数を使用したい場合は、lossパラメータか、metricsパラメータに引数として関数オブジェクトを指定する。

from keras import losses
from keras import metrics

model.compile(optimizer=optimizers.RMSprop(lr=0.001),
              loss=losses.binary_crossentropy,
              metrics=[metrics.binary_accuracy])

検証データセット(validating data set)の設定

全く新しいデータでモデルを訓練するときに正解率を監視するには、もとの訓練データセットから取り分けておいたサンプルを使って検証データセットを作成する。以下では10000個のサンプルを取り出す場合。

x_val = x_train[:10000] #検証データの取り出し
partial_x_train = x_train[10000:] #

y_val = y_train[:10000] #正解検証データの取り出し
partial_y_train = y_train[10000:]

k分割交差検証

データの数が少ないと検証データはかなり小さなものになってしまう。結果として、検証と訓練にどのデータ点を選択したかによって検証スコアが大きく変化することになるかもしれない。つまり、検証データセットの分割方法によっては、検証スコアの分散が高くなり、過学習に陥ってしまう。それを防ぐ最適な方法がk分割交差検証である。詳しくは説明しないので、調べてみてほしい。

モデルの訓練

8のミニバッチで20エポックの訓練を行う。xは訓練データyは正解データであることが多い。
取り分けておいた10000サンプルでの損失値と正解率を監視する。検証データはvalidation_dataパラメータに引数として渡す。

history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=20,
                    batch_size=8,
                    validation_data=(x_val, y_val))

fitメソッドは1エポックごとに訓練した出力と、検証データの出力を辞書型で返す。今回はhistoryオブジェクトに保存している。以下のコードを実行すると

history_dict = history.history
history_dict.keys()

dict_keys(['val_acc', 'acc', 'val_loss', 'loss'])
となる。

訓練データと検証データでの損失値をプロット

損失値をmatplotlibを使ってプロットする。historyオブジェクトに訓練の記録がされているのでここから呼び出す。この結果を元にしてハイパーパラメータを調整する。

import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

CNNで画像認識する場合の手順

画像のコピー

訓練画像(train)を保存するフォルダと検証画像(validation)を保存するフォルダを作り、学習に使うために集めた画像をコピーして振り分ける。検証データの画像枚数はかんで決めるが、だいたい全画像数のの20%~40%で調整するといいだろう。後の前処理の工程で出てくるflow_from_directory()のフォルダパスにここで作ったフォルダのパスを指定する。

CNNのインスタンス化

from keras import layers
from keras import models

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(Dense(2))
model.add(Activation("softmax"))

CNNの入力テンソルの形状は(image_height,image_width,image_channels)だ。第3引数は画像のチャンネル数である。RGB画像の場合はチャンネル数が3になる。
Conv2D(出力特徴の深さ,フィルタサイズ) padding='same'の引数を指定すると出力の幅と高さが入力と同じになるようにパディングする。
ちなみにmodel.summary()で作成したモデルを確認できる。
画像分類の場合、最終層はDense(全結合層)にし、引数には分類するクラス数を指定する。出力は判定の確率になるので損失関数はsoftmaxを選択する。

モデルのコンパイル

損失関数とオプティマイザの設定。

from keras import optimizers

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])

データの前処理

データをCNNに供給するには、その前に浮動小数点型のテンソルとして適切に処理しておく必要がある。手順は以下の通り、
1.画像ファイルを読み込む
2.JPEGファイルの内容をRGBのピクセルグリッドにデコードする。
3.これらのピクセルを浮動小数点型のテンソルに変換する。
4.ピクセル(0~255)の尺度に取り直し、[0,1]の範囲の値にする。
kerasには、上記の手順を自動的に処理するユーティリティが用意されている。ImageDataGeneratorクラスを利用すれば、ディスク上の画像ファイルを前処理されたテンソルのバッチに自動的に変換できるpythonジェネレータをセットできる。

ImageDataGeneratorを使ってディレクトリから画像を読み込む

from keras.preprocessing.image import ImageDataGenerator

# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=20,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary')

モデルの訓練

モデルを訓練させるにはfit_generator()関数を利用する。
steps_per_epochは1エポックで進行するステップ数。validation_stepsは1エポックの中で何枚ずつ画像を検証するかを表す。

history = model.fit_generator(
      train_generator,
      steps_per_epoch=10,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=5)

ネットワークの保存

訓練を終えたネットワークのパラメータを保存するにはsave()関数を利用する。kerasでは.h5という拡張子のファイルで保存される。h5ファイルを呼び出せば次回以降はこのパラメータで画像の予測をさせることができる。

model.save('cats_and_dogs_small_1.h5')

正解率のプロット

import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

保存したネットワークでの推定

model = models.Sequential()にしていた部分を以下のように変えるだけ。load_modelの引数には保存したネットワークファイルのパスを指定する。
学習済みネットワークを使うので、学習のときにあったadd()系は不要。学習したモデルがそのまま読み込まれる。

model=keras.models.load_model('cats_and_dogs_small_1.h5')

参考

https://qiita.com/GushiSnow/items/8c946208de0d6a4e31e7#%E5%85%B7%E4%BD%93%E7%9A%84%E3%81%AA%E5%AE%9F%E8%A3%85%E4%BE%8B
https://qiita.com/tsunaki/items/608ff3cd941d82cd656b
https://qiita.com/tomo_20180402/items/e8c55bdca648f4877188
https://ymgsapo.com/2019/02/28/keras-dog-and-cat/

3
7
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
3
7