ラベル keras の投稿を表示しています。 すべての投稿を表示
ラベル keras の投稿を表示しています。 すべての投稿を表示

2017年11月12日日曜日

Fine tuning (VGG16モデル) (Keras + Jupyter Notebook + tensorflow)

概要

Keras公式サイトの 
をやってみる。
少ないサンプルからディープラーニングで優位なモデルを作る。
ステップとしては、
  • スクラッチで作る。
  • bottleneck featureで学習済みモデル使う
  • Fine tuningを使う

画像の用意

まず、クラス分けする画像の用意をする。今回は猫と犬のクラス分け。
kaggleからcats and dogsのデータをダウンロードする。このデータセットは25000枚あるが、今回は少ないデータセットでのモデル構築が目的なので、トレーニングデータとしてcats, dogs 1000枚ごと、テストデータとして400枚ごと取り出してフォルダに分ける。

- cats_and_dogs_1000
  - train
    - cats (1000枚)
    - dogs (1000枚)
  - validation
    - cats (400枚)
    - dogs (400枚)

切り分けたコマンド
<code>
ll dog* | head -1000 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/train/dogs/
ll cat* | head -1000 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/train/cats/
ll dog* | tail -400 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/validation/dogs/
ll cat* | tail -400 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/validation/cats/
<code>

前処理とデータ増加

画像を少し加工しながらデータを増やす。これには過学習を防いでモデルを、一般化する効果があるらしい。
Kerasでは keras.preprocessing.image.ImageDataGenerator class を使ってこれを実現できる。

必要なライブラリのインポート
<code>
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
<code>

画像増やす。
<code>
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')
<code>

スクラッチの畳み込み演算トレーニング



<code>
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])
<code>

正解率は以下のようになった。

Epoch 50/50
125/125 [==============================] - 13s - loss: 0.4843 - acc: 0.7900 - val_loss: 0.4923 - val_acc: 0.7950

Bottleneck feature

学習済みモデルの最終層を削除して、そのモデルを特徴抽出として使うことをbottleneck featureと呼ぶらしい
ここはよく理解できなかったのでスキップ

Fine Tuning

最後に、FineTuningで予測して見る。
ステップとして

  • VGG16モデルを読み出して、パラメータをロードする。
  • 前で作ったモデルをトップに積んで、パラメータをロードする。
  • VGG16の層をfreezeする。
  • モデルのコンパイル
  • トレーニング


必要なKerasのクラスロード
<code>
from keras import applications
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Model
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
<code>

使用する変数の定義
<code>
# path to the model weights files.
weights_path = '../keras/examples/vgg16_weights.h5'
top_model_weights_path = 'bottleneck_fc_model.h5'
# dimensions of our images.
img_width, img_height = 150, 150

train_data_dir = 'images/cats_and_dogs_1000/train'
validation_data_dir = 'images/cats_and_dogs_1000/validation'
nb_train_samples = 2000
nb_validation_samples = 800
epochs = 50
batch_size = 16
<code>

VGG16モデルをロードして、bottleneck featureで作成したモデルをトップに積む。
<code>
# build the VGG16 network
base_model = applications.VGG16(weights='imagenet', include_top= False, input_shape=(150, 150, 3))
print('Model loaded.')

# build a classifier model to put on top of the convolutional model
top_model = Sequential()
top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(1, activation='sigmoid'))

# note that it is necessary to start with a fully-trained
# classifier, including the top classifier,
# in order to successfully do fine-tuning
top_model.load_weights(top_model_weights_path)

# add the model on top of the convolutional base
# model.add(top_model)
model = Model(input= base_model.input, output= top_model(base_model.output))
<code>

最初の25レイヤーはパラメータをアップデートしないようにする。
<code>
# set the first 25 layers (up to the last conv block)
# to non-trainable (weights will not be updated)
for layer in model.layers[:25]:
    layer.trainable = False
<code>

モデルのコンパイル
<code>
# compile the model with a SGD/momentum optimizer
# and a very slow learning rate.
model.compile(loss='binary_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])
<code>

画像データの用意
<code>
# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='binary')
<code>

モデルの学習
<code>
# fine-tune the model
model.fit_generator(
    train_generator,
    samples_per_epoch=nb_train_samples,
    epochs=epochs,
    validation_data=validation_generator,
    nb_val_samples=nb_validation_samples)
<code>

 結果は以下のようになり、精度が上がったことが確認できた。

Epoch 50/50
125/125 [==============================] - 151s - loss: 0.5791 - acc: 0.9250 - val_loss: 1.1987 - val_acc: 0.8813

参考

2017年6月6日火曜日

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる4 MINIST

Kerasチュートリアルの第4弾、今回はConvolutional Neural Networkここも参考になった)を組んで精度を上げてみる。ここページを参考にしている。

まず必要なライブラリをインポートする。
いろいろ見た事ないものがあるので、調べてみると、
Flattenは2次元のデータを1次元のベクターにするのに使うらしい。
Conv2Dは2次元配列の畳み込み演算するのに使う。
MaxPooling2Dは、画像の圧縮をするのに使う。

import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
K.set_image_dim_ordering('th')


そしてお馴染みのランダムにシードの設定

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)


第1層がConv2Dになるのだが、そこに読み込める形にデータを整形する。
KerasのConv2Dに入力するためには、[画像数][pixles(グレースケールは1)][width][height]の4次元配列にする必要があるのでshapeを使う。

# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# reshape to be [samples][pixels][width][height]
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')



前回もやった0 - 255を0 - 1にNormalizeと教師データの整形を今回もやる。

# normalize inputs from 0-255 to 0-1
X_train = X_train / 255
X_test = X_test / 255
# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]



モデルの定義をする。
1層目はConv2Dで32フィルター、フィルタのサイズ5 x 5、input_shapeは[1(グレースケール)][width][height]で指定。

2層目はMaxPooling2Dを使って画像を圧縮。slidesは指定がなければ、pool_sizeと同じになるようなので、2 x 2の領域が1つのPixcelにされるので14 x 14 の配列になるはず。

3層目はDropoutを使って20%のneuronsを伝播させない。これを入れるとover fittingを避けられるらしい。

4層目は2次元配列を1次元のベクターに変更

5層目は全結合のレイヤーで128 output

6層目は0 - 9の10のoutputでsoft max関数で確立に変換している。

# create model
model = Sequential()
model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
# Compile model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])


そしてモデルの学習。前回と同じように200サンプルごとにパラメタのアップデートして、10回繰り返し。

# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))



最終出力は以下。おお、エラー率が1%以下になっている。99%は判別できるという事。素晴らしい。


Train on 60000 samples, validate on 10000 samples
Epoch 1/10
172s - loss: 0.2310 - acc: 0.9347 - val_loss: 0.0825 - val_acc: 0.9743
Epoch 2/10
170s - loss: 0.0736 - acc: 0.9780 - val_loss: 0.0467 - val_acc: 0.9841
Epoch 3/10
175s - loss: 0.0531 - acc: 0.9839 - val_loss: 0.0432 - val_acc: 0.9856
Epoch 4/10
165s - loss: 0.0401 - acc: 0.9878 - val_loss: 0.0406 - val_acc: 0.9869
Epoch 5/10
179s - loss: 0.0337 - acc: 0.9893 - val_loss: 0.0346 - val_acc: 0.9886
Epoch 6/10
156s - loss: 0.0275 - acc: 0.9916 - val_loss: 0.0309 - val_acc: 0.9893
Epoch 7/10
163s - loss: 0.0232 - acc: 0.9927 - val_loss: 0.0359 - val_acc: 0.9877
Epoch 8/10
158s - loss: 0.0204 - acc: 0.9937 - val_loss: 0.0324 - val_acc: 0.9887
Epoch 9/10
164s - loss: 0.0166 - acc: 0.9947 - val_loss: 0.0300 - val_acc: 0.9901
Epoch 10/10
178s - loss: 0.0143 - acc: 0.9958 - val_loss: 0.0310 - val_acc: 0.9905
Baseline Error: 0.95%


ちなみに今回構築したモデルを可視化すると以下のようになっていた。







2017年6月3日土曜日

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる3 MINIST

Kerasチュートリアル第3弾。

機械学習のモデルを評価する時によく使われる、MINIST(手書き文字の認識をする)問題のコードを追っていく。
解説している記事をみながら、コードを追ってみる。

使う画像のサイズは28 x 28ピクセル。
60000イメージはモデル構築のために、10000イメージはテストのために使う。

いいモデルはエラー率1%以下になるらしい。

では実際にコードを見ていく。

実際の文字イメージ画像群(データセット)をダウンロードする必要があるが、Kerasでは便利なスクリプトが用意されているらしい。(~/.keras/datasets/mnist.pkl.gz にダウンロードされる)

以下はダウンロードしてプロットするスクリプト。

# Plot ad hoc mnist instances
from keras.datasets import mnist
import matplotlib.pyplot as plt
# load (downloaded if needed) the MNIST dataset
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# plot 4 images as gray scale
plt.subplot(221)
plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))
plt.subplot(222)
plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))
plt.subplot(223)
plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))
plt.subplot(224)
plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))
# show the plot
plt.show()


ふむ、Jupiter Notebook上でも綺麗に表示された。

ではデータはダウンロードされたので、今回使うライブラリたちを読み込む。
Dropoutというのは、過学習を避けるためにランダムに伝播をさせずに、ネットワークをFatにさせないテクニックらしい。
詳しい論文

keras.unilsはその名の通り、kerasの便利クラス。モデルのシリアライズしたりするメソッドがある。https://keras.io/utils/


import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.utils import np_utils



前回と同じように、再現性を持たせるためにseedをセット。

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)



でMINISTのデータを読み込む

# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()


読み込んだトレーニングセットは3次元の配列(白黒の場合)だが、モデルに食わせるためには、Vector(1次元の配列)にする必要があるらしい。28 x 28の画像だから784要素の配列する。

# flatten 28*28 images to a 784 vector for each image
# print(type(X_train))
num_pixels = X_train.shape[1] * X_train.shape[2] # 28 * 28
X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32') # 60000 , 784
# 784要素のArrayが60000個ある2次元配列になった。
# print(X_train.shape)
X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32')


グレースケールは0 to 255で表しているが、これを255で割って0 to 1のスケールにする。

# normalize inputs from 0-255 to 0-1
X_train = X_train / 255
X_test = X_test / 255


教師データのラベルは0,1,2,3と正解の数値で表されているが、これを
0だったら [1,0,0,0,0,0,0,0,0,0]
5だったら [0,0,0,0,1,0,0,0,0,0]
と表すように変換する。

# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]


ついにモデルの定義をする。
1層目は入力784、出力784
2層目は入力784、出力10、活性化関数にsoftmaxを使っている。ざっくり言うと出力を確率に変えてくれるらしい。

損失関数はcategorical_crossentropy = Logarithmic loss


# create model
model = Sequential()
model.add(Dense(num_pixels, input_dim=num_pixels, 
                kernel_initializer='normal', activation='relu'))
model.add(Dense(num_classes, kernel_initializer='normal', activation='softmax'))
# Compile model
model.compile(loss='categorical_crossentropy', 
              optimizer='adam', metrics=['accuracy'])


データを与えて、モデルを最適化する
200イメージごとにモデルのパラメータをアップデートして、20回繰り返す。

最後にテストデータでテストしたスコアをプリント!

# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=20, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))




Baseline Error: 1.61%

が最終出力。つまり10000のイメージでテストしてみて、1.61%はこのモデルでの予想とはずれたが、98.4%は正解になったということ

こんなシンプルな2層のネットワークでも98.4%正解になると驚きだった。まあ人間がやれば99.9%ぐらい成功できるだろうけど。

ただこのチュートリアルはシンプル 編なようなので、次週もっと正解率を高めるモデル構築を見ていく。

たぶん使ってないDropoutを使うんだろうな。





2017年5月27日土曜日

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる2

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる1の続き。

前回は環境構築して、簡単なチュートリアルを試してみた。今回はそのコードをこまかく見ていく。

まず必要なライブラリ群のインポート

from keras.models import Sequential
from keras.layers import Dense
import numpy
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot

SVG, model_to_dotはモデルの可視化に使う。その他はKerasのプロジェクトではだいたいimportしないといけないはず。

次にランダムな数を生成した時に再現性を持たせるためにseedを設定。

# fix random seed for reproducibility
numpy.random.seed(7)

学習するデータを読み込みする。このチュートリアルでは糖尿病患者のデータをcsvから読み込み。X, Yの変数に読み込む、Xには全行の0から7の8列の2次元配列のデータ、Yには全行、8列目の1次元配列のデータが入る。
どうやらXには予想のためのデータ、Yにはその結果、0(陰性)、0(陽性)が入っているよう。

# load pima indians dataset
dataset = numpy.loadtxt("../tutorial/1/pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]



次はモデルを定義していく。

KerasではSequentialというモデルを作り、そこにNWの層を追加していく形が基本らしい。
1層目は通常の全結合NWレイヤーで、入力が8 個、出力が12個の物を積んでる。 activationは活性化関数をどうするかというところ、ここではrelu(ランプ関数)が指定されている。現在は一般的にランプ関数を指定した方が精度がいいとされているらしい。

2層目は入力12個で、出力が8個

3層目は入力8個で、出力1個、activationにsigmoid(シグモイド関数)を使って出力を0 or 1 の整数にしている。


# create model
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

モデルの定義が終わったあと、モデルをコンパイルする。
引数は3つとり、optimizer(最適化手法)、loss(損失関数)、metrics(評価指標のリスト)が必要、詳しくはここ参照

最適化手法はadam
損失関数はbinary_crossentropy = logloss
metricsは一般的にはaccuracyを使うらしい。


# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])


コンパイル後、実際に学習を始める。
XはテストデータのNumpy配列、Yは教師データのNumpy配列を与える。
epoches(反復回数)とbatch(何サンプルでgradient disent の更新をするか)も指定する。

model.fit(X, Y, epochs=50, batch_size=10)

最後にモデルの評価を行う。
XはテストデータのNumpy配列、Yは教師データのNumpy配列を与える。

evaluate後モデルの評価スコアが帰ってくる。

# evaluate the model
scores = model.evaluate(X, Y)
print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))



非常に簡単に使えるので、ぜんぜんTensorFlowより敷居が低そう。ただ機械学習、ニューラルネットワークの基礎はしっている必要があるので、CourseraのMachine larning(とくに)week4 week5あたりをやっておくといいと思う。


2017年5月13日土曜日

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる1

Tensorflowを昔やってみたのだが、挫折したのでもっと直感的と言われているKerasを試してみる。

インストール

pyenv

Pyhonデータ分析ライブラリたちが入る
Anaconda https://docs.continuum.io/anaconda/install-macos
pyenv使ってるのでこちらを参考にした
http://qiita.com/takehilo/items/1ffe5b266ed6a64690c8

jun-mac:keras jun-ishioka$ pyenv install -v anaconda3-4.2.0
jun-mac:keras jun-ishioka$ pyenv global anaconda3-4.2.0
jun-mac:keras jun-ishioka$ python --version
Python 3.5.2 :: Anaconda 4.2.0 (x86_64) 
source /Users/jun-ishioka/.pyenv/versions/anaconda3-4.2.0/bin/activate 
Tensorflow, KerasはAnacondaのパッケージ管理出あるcondaでインストール

Googleの機械学習ライブラリ
Tensorflow  https://www.tensorflow.org/install/install_mac

conda install -c conda-forge tensorflow

Tensorflowのラッパー、より直感的に操作できる
Keras https://keras.io/#installation

conda install -c conda-forge keras

もろもろインストール後、Jupiter Notebookという対話しきのPytyon GUIを起動(これはAnacondaにデフォルトで含まれているみたい)

jupyter notebook

ブラウザが立ち上がりファイラーが表示される。
 適当なフォルダを作って、NewからPython [conda root]を選択。
 そうすると、ノートブックが出来上がる。

このセルの中にはマークダウンでドキュメントを書いたり、コードを書いて実行したりできる。

ここのチュートリアルをやってみた。
http://machinelearningmastery.com/tutorial-first-neural-network-python-keras/
実行したいときはCell -> Run Cells
 無事実行完了、Jupyter Notebook素敵すぎる。コードの管理とかかなり楽になりそう。

Kerasのコードの内容まで踏み込みたいのだが、環境構築に手こずってしまったので今日はここまで。