学習に用いたコード(上:learning.py)と評価に用いたコード(下:evaluation.py)を載せておきます。
from __future__ import print_function import os import struct import numpy as np from keras.models import Sequential from keras.layers.convolutional import Convolution2D, MaxPooling2D from keras.layers.core import Dense, Dropout, Activation, Flatten from keras.optimizers import RMSprop from keras.utils import np_utils from keras.callbacks import EarlyStopping, ModelCheckpoint from sklearn.model_selection import KFold from sklearn.model_selection import train_test_split from keras.preprocessing.image import ImageDataGenerator # 各種パラメータ nb_filters1 = 32 # 畳み込みフィルタ1の数 nb_filters2 = 64 # 畳み込みフィルタ2の数 nb_conv1 = 3 # 畳み込みフィルタ1の縦横pixel数 nb_conv2 = 2 # 畳み込みフィルタ2の縦横pixel数 nb_pool = 2 # プーリングを行う範囲の縦横pixel数 nb_classes = 3 # 分類するクラス数 nb_epoch = 50 # 最適化計算のループ回数 batch_size = 32 # 計算効率化のために分割された訓練データの1グループあたりのデータ数 img_rows, img_cols = 100, 100 # 入力画像の縦横pixel数 all_filenumber = 90 # 訓練用 & 評価用画像の数 bytesize = 3 # 画像のbyte数(24bit = 3byte) pixelnum = img_rows*img_cols index = 0 # 配列の確保 X_train_binary = [0 for j in range(bytesize*pixelnum*all_filenumber)] X_train_int = [0 for j in range(bytesize*pixelnum*all_filenumber)] y_train_int = [] # 画像&ラベルデータの読み込み filenameX_train = "blood_total.raw" filenameY_train = "blood_total_label.txt" path1 = "/Users/satoshi/blood_data/" rf1 = open(path1+filenameX_train, "rb") rf2 = open(path1+filenameY_train, "r") X_train_binary = rf1.read(bytesize*pixelnum*all_filenumber) # 画像データの格納(バイナリから整数(char型)に変換して) for i in range(bytesize*pixelnum*all_filenumber): X_train_int[i] = struct.unpack("B", X_train_binary[i]) # ラベルデータの格納 for item in rf2: y_train_int += list(item) rf1.close() rf2.close() # numpy配列に格納 X_train = np.array(X_train_int) y_train = np.array(y_train_int) # 画像を4次元配列に X_train = X_train.reshape(all_filenumber, 3, img_rows, img_cols) # 画像を0.0~1.0の範囲に変換 X_train = X_train.astype("float32") X_train /= 255 # 画像の前処理としての正規化 def normalization(X_train): X_train = X_train.reshape(all_filenumber, 3*img_rows*img_cols) for filenum in range(0, all_filenumber): X_train[filenum] -= np.mean(X_train[filenum]) X_train = X_train.reshape(all_filenumber, 3, img_rows, img_cols) return X_train normalization(X_train) # Kflodによる交差検証 kf = KFold(n_splits=5, shuffle=True) for train_index, eval_index in kf.split(X_train): X_tra, X_eval = X_train[train_index], X_train[eval_index] y_tra, y_eval = y_train[train_index], y_train[eval_index] model_weights = "/Users/satoshi/blood_data/blood_CNN_model[%d].h5" % index index = index+1 # データの水増し(Data Augmentation) datagen = ImageDataGenerator( rotation_range=180, horizontal_flip=True, fill_mode='nearest') # 水増し画像を訓練用画像の形式に合わせる datagen.fit(X_tra) # クラスラベル y (数字の0~2)を、one-hotエンコーディング型式に変換 Y_tra = np_utils.to_categorical(y_tra, nb_classes) Y_eval = np_utils.to_categorical(y_eval, nb_classes) # CNNのモデル model = Sequential() model.add(Convolution2D(nb_filters1, nb_conv1, nb_conv1, border_mode ="same", input_shape=(3, img_rows, img_cols))) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool))) model.add(Convolution2D(nb_filters2, nb_conv2, nb_conv2, border_mode ="same")) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool))) model.add(Flatten()) model.add(Dense(256)) model.add(Activation("relu")) model.add(Dropout(0.5)) model.add(Dense(nb_classes)) model.add(Activation("softmax")) #モデルのコンパイル model.compile(loss="categorical_crossentropy", optimizer="rmsprop", metrics=["accuracy"]) # 過学習の抑制 early_stopping = EarlyStopping(monitor='val_loss', patience=10 , verbose=1) # 評価に用いるモデル重みデータの保存 checkpointer = ModelCheckpoint(model_weights, monitor='val_loss', verbose=1, save_best_only=True) # リアルタイムに水増し生成されるバッチ画像に対するモデルの適用 model.fit_generator(datagen.flow(X_tra, Y_tra, batch_size=batch_size), samples_per_epoch=X_tra.shape[0], nb_epoch=nb_epoch, verbose=1, validation_data=(X_eval, Y_eval), callbacks=[early_stopping, checkpointer]) # 評価に用いるモデル構造の保存 def save_model(model): json_string = model.to_json() if not os.path.isdir("cache"): os.mkdir("cache") json_name = "architecture.json" open(os.path.join("cache", json_name),"w").write(json_string) save_model(model)
learning.py
from __future__ import print_function import os import struct import numpy as np from keras.models import model_from_json # 各種パラメータ img_rows, img_cols = 100, 100 test_filenumber = 1 bytesize = 3 pixelnum = img_rows*img_cols # 配列の確保 X_test_binary = [0 for j in range(bytesize*pixelnum*test_filenumber)] X_test_int = [0 for j in range(bytesize*pixelnum*test_filenumber)] test_pred = [] # テスト画像の読み込み filenameX_test = "blood_01.raw" path1 = "/Users/satoshi/blood_data/" rf = open(path1+filenameX_test, "rb") X_test_binary = rf.read(bytesize*pixelnum*test_filenumber) # 画像データの格納(バイナリから整数(char型)に変換して) for i in range(bytesize*pixelnum*test_filenumber): X_test_int[i] = struct.unpack("B", X_test_binary[i]) rf.close() # numpy配列に格納 X_test = np.array(X_test_int) # 画像を4次元配列に X_test = X_test.reshape(test_filenumber, 3, img_rows, img_cols) # 画像を0.0~1.0の範囲に変換 X_test = X_test.astype("float32") X_test /= 255 # 画像の前処理としての正規化 def normalization(X_test): X_test = X_test.reshape(test_filenumber, 3*img_rows*img_cols) for filenum in range(0, test_filenumber): X_test[filenum] -= np.mean(X_test[filenum]) X_test = X_test.reshape(test_filenumber, 3, img_rows, img_cols) return X_test normalization(X_test) # 保存したモデル重みデータとモデル構造の読み込み for index in range(0,5): model_weights = "/Users/satoshi/blood_data/blood_CNN_model[%d].h5" % index json_name = "architecture.json" model = model_from_json(open(os.path.join("cache", json_name)).read()) model.load_weights(model_weights) # 各モデルにおける推測確率の計算 test_pred.append(model.predict(X_test)) test_average = np.array(test_pred[0]) # 5種類のモデルの推測確率の平均 for i in range(1,5): test_average += np.array(test_pred[i]) test_average /= 5 print(test_average)
evaluation.py