iTAC_Technical_Documents

アイタックソリューションズ株式会社

ブログ名

【第16回】簡易体積算出アルゴリズム 入出力に関する検討2(結果)

今回の概要

  • 入力に画像サイズの情報を付与した結果について
  • ニューラルネットの評価
  • アンサンブル学習の準備

入力に画像サイズの情報の付与した結果について

探索項目と構築ネットワークが大きく時間がかかりましたので、途中までの結果を示します。
結果は以下の通りで、前回と同等の結果となりました。

以前と比較すると、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と比較的低い結果となりました。
ニューラルネットと決定木では得意とする入力・出力形式が異なるため、これを考慮しなければ良い精度は得られないと考えられます。
もともと、この入力はニューラルネットの中間層を抜き取ったものですので、そのことも影響していると考えられます。

次回の予定

次回は、精度が低下の理由を調査します。


次の記事へ

前の記事へ 戻る