今回の概要
- 入力に画像サイズの情報を付与した結果について
- ニューラルネットの評価
- アンサンブル学習の準備
入力に画像サイズの情報の付与した結果について
探索項目と構築ネットワークが大きく時間がかかりましたので、途中までの結果を示します。
結果は以下の通りで、前回と同等の結果となりました。
以前と比較すると、one-hot vecにすることによりaccuracyは飛躍的に良くなり、交差検証でも検証データの精度がほぼ全て"1"になるほどです。
ここに入力情報を加えることで0.002から0.004に落ちましたが、これは入力の多様性による汎化性能においては大きな差がないと考えられますので、今はこの両手法を保持しておきたいと思います。
Current best loss is 0.004090719259034131 with parameters: {'hidden_neurons1': 3600.0, 'hidden_neurons2': 1300.0, 'drop': 0.29899967194322563, 'lr': 0.0005058194828119688, 'activation': 'sigmoid'}.
その上で、このモデルについて評価を行いました。
評価に使用したソースコードを以下に示します(VGG19_evaluation3.py)。
python:VGG19_evaluation3.py import keras import numpy as np import matplotlib.pyplot as plt import os import re import csv import tensorflow as tf from sklearn.model_selection import KFold from keras.utils import np_utils from keras.models import Sequential, Model from keras.layers import Input, Conv2D, MaxPooling2D, Dense, Dropout, Activation, Flatten from keras.preprocessing.image import array_to_img, img_to_array, load_img from keras.applications import ResNet50, VGG19 from keras.callbacks import ModelCheckpoint, EarlyStopping from keras import optimizers from sklearn.model_selection import train_test_split from keras.backend import tensorflow_backend config = tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True)) session = tf.Session(config=config) tensorflow_backend.set_session(session) hidden_neurons1 = 3600 hidden_neurons2 = 1300 out_neurons = 200 batch_size = 8 nb_epochs = 1000 drop_num = 0.29899967194322563 lr = 0.0005058194828119688 X = [] X_add = [] Y_pre = [] Y = np.zeros((1000,200)) with open('X_data.csv') as f: for row in csv.reader(f): X.append(row) with open('X_add_data.csv') as f: for row in csv.reader(f): X_add.append(row) with open('Y_data.csv') as f: for row in csv.reader(f): Y_pre.append(row) X = np.array(X) X_add = np.array(X_add) Y_pre = np.array(Y_pre) for i,num in enumerate(Y_pre): j = float(num[0]) / 0.005 - 1 Y[i,int(j)]=1 X = np.concatenate([X, X_add], 1) print(X.shape) print(Y.shape) x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42, shuffle=True) print(x_train.shape, x_test.shape, y_train.shape, y_test.shape) es = EarlyStopping(monitor='val_loss', min_delta=0, patience=30, verbose=1, mode='auto') modelCheckpoint = ModelCheckpoint(filepath = 'Checkpoint.h5', monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=False, mode='min', period=1) model = Sequential() model.add(Dense(hidden_neurons1, input_shape= (25090, ))) model.add(Activation("sigmoid")) model.add(Dropout(drop_num)) model.add(Dense(hidden_neurons2)) model.add(Activation("sigmoid")) model.add(Dropout(drop_num)) model.add(Dense(out_neurons)) model.add(Activation("softmax")) model.compile(loss='categorical_crossentropy', metrics = ['accuracy'], optimizer=optimizers.Adam(lr=lr)) #model.summary() result = model.fit(x_train, y_train, batch_size=batch_size, epochs=nb_epochs, verbose=1, validation_data=(x_test, y_test), shuffle=True, callbacks=[modelCheckpoint,es]) model.load_weights('Checkpoint.h5') scores = model.evaluate(X, Y, verbose=0) print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100)) result.history.keys() # ヒストリデータのラベルを見てみる] ep =len(result.history['acc']) plt.figure() plt.plot(range(1, ep+1), result.history['acc'], label="training") plt.plot(range(1, ep+1), result.history['val_acc'], label="validation") plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.savefig('acc_test.png') plt.figure() plt.plot(range(1, ep+1), result.history['loss'], label="training") plt.plot(range(1, ep+1), result.history['val_loss'], label="validation") plt.xlabel('Epochs') plt.ylabel('loss') plt.legend() plt.savefig('loss_test.png') #可視化 model.summary() # モデル評価 print("Load test dataset") X = [] X_add = [] Y_pre = [] Y = np.zeros((1000,200)) with open('X_data_test.csv') as f: for row in csv.reader(f): X.append(row) with open('X_add_data_test.csv') as f: for row in csv.reader(f): X_add.append(row) with open('Y_data_test.csv') as f: for row in csv.reader(f): Y_pre.append(row) X = np.array(X) X_add = np.array(X_add) Y_pre = np.array(Y_pre) for i,num in enumerate(Y_pre): j = float(num[0]) / 0.005 - 1 Y[i,int(j)]=1 X = np.concatenate([X, X_add], 1) print(X.shape) print(Y.shape) model.load_weights('Checkpoint.h5') loss, accuracy = model.evaluate(X, Y, verbose=0) print('loss: '+str(loss)+' , acc: '+str(accuracy)) pred = model.predict(X_test, batch_size=1, verbose=0) print(pred) print("end of script")
学習の結果は、学習データ、検証データ共に"1"と非常に高い精度で推定することができました。
しかし、テストデータは精度が"0"となっており、全く推定できていませんでした。
もう一度ソースコードと考え方を見直して、精度が落ちる原因を探りたいと思います。
まずは、これまでシャッフルしていたデータをシャッフルせずに最適化問題を解いてみます。
アンサンブル学習の準備
前回作成したプログラムを修正して学習、検証しました。
まずはrandom forestについて修正したソースコードを以下に示します(RF_train3.py)。
python:RF_train3.py import numpy as np import matplotlib.pyplot as plt import os import re import csv import gc from sklearn.model_selection import KFold import optuna from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.metrics import precision_score from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import confusion_matrix from pandas.plotting import scatter_matrix X = [] X_add = [] Y_pre = [] Y = np.zeros((1000,200)) fold_num = 5 with open('X_data.csv') as f: for row in csv.reader(f): X.append(row) with open('X_add_data.csv') as f: for row in csv.reader(f): X_add.append(row) with open('Y_data.csv') as f: for row in csv.reader(f): Y_pre.append(row) X = np.array(X) X_add = np.array(X_add) Y_pre = np.array(Y_pre) for i,num in enumerate(Y_pre): j = float(num[0]) / 0.005 - 1 Y[i,int(j)]=1 X = np.concatenate([X, X_add], 1) print(X.shape) print(Y.shape) kf = KFold(n_splits=fold_num, shuffle=True) def objective(trial): #最適化するパラメータの設定 #中間層1のユニット数 max_depth = int(trial.suggest_discrete_uniform("max_depth", 5, 500, 10)) n_estimators = int(trial.suggest_discrete_uniform("n_estimators", 5, 500, 10)) max_leaf_nodes = int(trial.suggest_discrete_uniform("max_leaf_nodes", 4, 64, 4)) min_samples_split = trial.suggest_int("min_samples_split", 8, 16) criterion = trial.suggest_categorical("criterion", ["gini", "entropy"]) acc_all = [] for train, test in kf.split(X): random_forest = RandomForestClassifier(verbose=True, min_samples_split = min_samples_split, max_leaf_nodes = max_leaf_nodes, criterion = criterion, max_depth = max_depth, n_estimators = n_estimators, random_state = 42) random_forest.fit(X[train], Y[train]) # 予測値算出 y_pred = random_forest.predict(X[test]) #モデルを作成する段階でのモデルの識別精度 trainaccuracy_random_forest = random_forest.score(X[train], Y[train]) print('TrainAccuracy: {}'.format(trainaccuracy_random_forest)) #作成したモデルに学習に使用していない評価用のデータセットを入力し精度を確認 accuracy_random_forest = accuracy_score(Y[test], y_pred) print('Accuracy: {}'.format(accuracy_random_forest)) acc_all.append(accuracy_random_forest) del random_forest, y_pred, trainaccuracy_random_forest, accuracy_random_forest print(acc_all) return 1.0 - np.mean(acc_all) study = optuna.create_study() study.optimize(objective, n_trials=50) print("End!!") print("All trials") print(study.trials) print("Best Parameters") print(study.best_params) print("Best Value") print(study.best_value) print("end of script")
trial10までを試しに実行すると、シャッフルしていても精度が0.7と比較的低い結果となりました。
ニューラルネットと決定木では得意とする入力・出力形式が異なるため、これを考慮しなければ良い精度は得られないと考えられます。
もともと、この入力はニューラルネットの中間層を抜き取ったものですので、そのことも影響していると考えられます。
次回の予定
次回は、精度が低下の理由を調査します。