読者です 読者をやめる 読者になる 読者になる

pythonで2次元のConvolutionalNeuralNetwork(畳み込みニューラルネット)

機械学習 深層学習 コード

内容

python+kerasを使って、MNISTのような白黒画像を分類するCNNを構築。 パラメータを変更すればカラー画像なども対応可能、のはず。

コード

# keras
import numpy
import pandas
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D
from keras.callbacks import Callback

# データ型式によって事前に決める
#  今回は 1サンプル = 5 * 20 の行列なのでこのように決める
CONV_SIZE, COL_SIZE = 5, 20

# モデルを定義する
def cnn_model():
    # create model
    model = Sequential()
    model.add(Convolution2D(10, 1, 5, border_mode='valid', input_shape=(1, CONV_SIZE, COL_SIZE), activation='relu'))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.2))
    model.add(Dense(128, activation='relu'))
    model.add(Dense(1, init='normal', activation='sigmoid'))
    # Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

# コールバック
class LossHistory(Callback):
    def on_train_begin(self, logs={}):
        self.losses = []

    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
        
# 訓練・テストデータ分割
#  今回は時系列に並んだデータなので前半後半で区切る
#  普通は train_test_split でランダムに分ける
#  そのあとCNNへの入力のため reshape する
def data_split(X, y, rate=0.2):
    n = int(X.shape[0]*(1-rate))
    return X[:n], X[n:], y[:n], y[n:]

conv_Xl, conv_yl = ... # 適当な形でデータをロードする
X_train, X_test, y_train, y_test = data_split(conv_Xl, conv_yl, rate=0.15)
X_train = X_train.reshape(X_train.shape[0], 1, CONV_SIZE, COL_SIZE).astype('float32')
X_test = X_test.reshape(X_test.shape[0], 1, CONV_SIZE, COL_SIZE).astype('float32')

# ロスの経過を確認したいので出力
history = LossHistory()

# 訓練:verbose=1を変更することで訓練中のprintを変更できる
model = cnn_model()
model.fit(X_train, y_train, validation_data=(X_test, y_test), nb_epoch=300, batch_size=50, verbose=1, callbacks=[history])
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))

出力

Train on 24000 samples, validate on 4000 samples
Epoch 1/10
102s - loss: 0.5463 - acc: 0.4962 - val_loss: 0.3690 - val_acc: 0.6785
...

損失関数の経過を確認するためには、

import matplotlib.pyplot as plt;plt.style.use('ggplot')
%matplotlib inline
plt.plot(history.losses)

f:id:misos:20161010050205p:plain

とすればいい。