質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.71%

kerasを用いてCSVに各エポック毎に出力したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,425

FALLOT

score 14

 kerasを用いて,画像を入力データとして,数値予測する回帰分析をしています.

CSVloggerを用いて各エポック毎にloss.val_lossを出力しているのですが,予測値の出力仕方が分かります.以下のコードに加えたいのですが,どのよううにコーディングすればよいでしょうか?

#最大応力の値の予測
from keras.models import Sequential
from keras.layers import Activation, Dense, Dropout, LeakyReLU
#from keras.layers.advanced_activations import LeakyReLU
from keras.utils.np_utils import to_categorical
from keras.optimizers import Adagrad
from keras.optimizers import Adam
from keras.models import load_model
from keras.callbacks import EarlyStopping, ModelCheckpoint, CSVLogger
from sklearn.model_selection import train_test_split
from sklearn import datasets
import numpy as np
from PIL import Image
import os
import time
import csv
import cv2
import math


start_time = time.time()
print("開始時刻: " + str(start_time))
#それぞれの画像の枚数を入力
A = 50
B = 50
sum =A+B
# 学習用のデータを作る.
image_list = []
location_list = []
#ハイパーパラメータ
#画像サイズ
x = 150
y = 75
Z = x*y #入力層のノード数
#エポック数
E = 5
#バッチサイズ
BATCH_SIZE = 32
#学習率
LR = 0.00001
#訓練データの数 train=sum
train=sum

#画像の読み込み:読み込み→リサイズ→1列に変換→正規化
print("画像の読み込み 開始")
count=1
for i in range(0,A):
    im = cv2.imread("data/image/a/"+str(i)+"a.png".format(i),1) #画像の読み込み
    print(str(i)+"a.png")
    image = np.array(Image.open("data/image/a/"+str(i)+"a.png").resize((x, y))) #画像をnum配列にしてリサイズ
    print(image.shape)
    image =np.reshape(image,Z) #2次元行列を1次元行列に変換
    print(image.shape)
    image_list.append(image / 255.) #appendは追加:1枚ずつ足しこんでいく
    print(str(count)+"/"+str(train))
    count +=1
    print('\n')

for i in range(0,B):
    im = cv2.imread("data/image/b/"+str(i)+"b.png".format(i),1) #画像の読み込み
    print(str(i)+"b.png")
    image = np.array(Image.open("data/image/b/"+str(i)+"b.png").resize((x, y))) #画像をnum配列にしてリサイズ
    print(image.shape)
    image =np.reshape(image,Z) #2次元行列を1次元行列に変換
    print(image.shape)
    image_list.append(image / 255.) #appendは追加:1枚ずつ足しこんでいく
    print(str(count)+"/"+str(train))
    count +=1
    print('\n')

print("画像の読み込み 終了")

# kerasに渡すためにnumpy配列に変換。
image_list = np.array(image_list)

#最大応力の位置_読み込み_表示
location = np.loadtxt("data/value/max_stress_value_a.csv",delimiter=",",skiprows=0)
location_list.extend(location)
location = np.loadtxt("data/value/max_stress_value_b.csv",delimiter=",",skiprows=0)
location_list.extend(location)
location_list = np.array(location_list)
print("\n最大応力の値の行列の形")
print(location_list.shape)
#print(location_list)
np.savetxt("data/value/max_stress_value_true.csv",location_list,delimiter=",")
#最大応力の位置_読み込み_終了

# モデルを生成してニューラルネットを構築
model = Sequential()

model.add(Dense(5000, input_dim=Z,kernel_initializer='random_uniform',bias_initializer='zeros')) 
#model.add(Activation("LeakyReLU"))
model.add(LeakyReLU())
model.add(Dropout(0.2))


model.add(Dense(100,kernel_initializer='random_uniform',bias_initializer='zeros'))
model.add(LeakyReLU())
model.add(Dropout(0.075))


model.add(Dense(10,kernel_initializer='random_uniform',bias_initializer='zeros'))
model.add(LeakyReLU())
model.add(Dropout(0.0))

model.add(Dense(5,kernel_initializer='random_uniform',bias_initializer='zeros'))
model.add(LeakyReLU())
model.add(Dropout(0.0))

model.add(Dense(1))
model.add(Activation("linear"))

# オプティマイザ(最適化)にAdamを使用
opt = Adam(lr=LR)

# モデルをコンパイル
#最大応力位置の予測 誤差関数:二乗誤差
model.compile(loss="mean_absolute_percentage_error", optimizer=opt)

#CSVに各エポックの学習結果の保存
csv_logger = CSVLogger('result/training_process.csv')

# 学習を実行。20%はテストに使用
#最大応力位置の予測 モデルフィット
history = model.fit(image_list, location_list, nb_epoch=E,verbose=1,callbacks=[csv_logger], batch_size=BATCH_SIZE, validation_split=0.2) 

#最大応力位置の予測 誤差の評価
loss = model.evaluate(image_list, location_list)

#最終の学習結果を書き込む
fp = open("result/RESULT.txt","w")
fp.write("\nloss:{}".format(loss))
fp.close()

#最終の誤差の表示
print("\nloss:{}\n".format(loss))

#予測値
predicted= model.predict(image_list)
#print("NNの最大応力の値 予測値")
#print(predicted)
np.savetxt("result/max_stress_value_predict_result.csv",predicted,delimiter=",")

image_list = np.array(image_list)
location_list = np.array(location_list) 
print(image_list.shape, image_list.dtype)  # (300, 11250) float64
print(location_list.shape, location_list.dtype)  # (300,) float64


def get_batch(image_list, location_list, batch_size, shuffle=False):
    '''ミニバッチを生成するジェネレーター関数
    '''
    num_samples = location_list # サンプル数
    if shuffle:# シャッフルする場合
        indices = np.random.permutation(num_samples)
    else: # シャッフルしない場合
        indices = np.random.arange(num_samples)
    num_steps = np.ceil(num_samples / batch_size).astype(int)
    print(num_steps)
    print(type(num_steps))

    for itr in range(num_steps):
        start = batch_size * itr
        excerpt = indices[start:start + batch_size]
        yield x[excerpt], y[excerpt]

# 保存用ディレクトリ
out_dirpath = 'prediction'
os.makedirs(out_dirpath, exist_ok=True)

x_train, x_test, y_train, y_test = train_test_split(image_list, location_list, test_size=0.2)

# 学習する。
epochs = E
for i in range(epochs):
    for x_batch, y_batch in get_batch(x_train, y_train, batch_size=BATCH_SIZE, shuffle=True):
        # x_batch, y_batch が生成されたミニバッチ

        # 1バッチ分学習する
        model.train_on_batch(x_batch, y_batch)

    # エポックごとにテストデータで推論する。
    y_pred = model.predict_classes(x_train)
    result = np.c_[y_pred, y_train]

    # 推論結果を保存する。
    filepath = os.path.join(out_dirpath, 'prediction_{}.csv'.format(i))
    np.savetxt(filepath, result, fmt='%.0f')



end_time = time.time()
print("\n終了時刻: ",end_time)
print ("かかった時間: ", (end_time - start_time))
ttime = end_time - start_time
fa = open("result/TIME.txt","w")
fa.write("\nかかった時間:{} ".format(ttime))
fa.close()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

prediction の結果を各エポック毎に保存するコールバック関数はないので、以下のようにする必要があります。

 手順

  1. ミニバッチを作成するジェネレーターを作る。
  2. 1 epoch 学習する。
  3. predict() を実行し、推論する。
  4. numpy.savetxt() で結果をファイルに保存する。

 サンプルコード

 モデル作成

ここは本題とは関係ありません。

import os

import numpy as np
import seaborn as sn
from keras.datasets import mnist
from keras.layers import Activation, BatchNormalization, Dense, Dropout
from keras.models import Sequential
from keras.utils.np_utils import to_categorical
from sklearn import metrics

# MNIST データを取得する。
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print('x_train.shape', x_train.shape)  # x_train.shape (60000, 28, 28)
print('y_train.shape', y_train.shape)  # y_train.shape (60000,)
print('x_test.shape', x_test.shape)  # x_test.shape (10000, 28, 28)
print('y_test.shape', y_test.shape)  # y_test.shape (10000,)

# モデルを作成する。
model = Sequential()
model.add(Dense(10, input_dim=784))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dense(10))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dense(10))
model.add(BatchNormalization())
model.add(Activation('softmax'))
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# モデルの入力に合わせて1次元配列にする。 (28, 28) -> (784,) にする
x_train = x_train.reshape(len(x_train), -1)
x_test = x_test.reshape(len(x_test), -1)

# one-hot 表現に変換する。
y_train_onehot = to_categorical(y_train)

 ミニバッチを作成するジェネレーターを作る。

def get_batch(x, y, batch_size, shuffle=False):
    '''ミニバッチを生成するジェネレーター関数
    '''
    num_samples = len(x)  # サンプル数
    if shuffle:  # シャッフルする場合
        indices = np.random.permutation(num_samples)
        # 例: num_samples=10 の場合、array([7, 8, 1, 2, 4, 6, 9, 5, 3, 0])
        # ランダムにシャッフルされている
    else:  # シャッフルしない場合
        indices = np.arange(num_samples)
        # 例: num_samples=10 の場合、array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

    num_steps = np.ceil(num_samples / batch_size).astype(int)
    # ステップ数 = ceil(サンプル数 / バッチサイズ)
    # 例 np.ceil(10 / 3) = np.ceil(3.33333333...) = 4

    for itr in range(num_steps):
        start = batch_size * itr
        excerpt = indices[start:start + batch_size]
        # [batch_size * itr, batch_size * (itr + 1)] の範囲のサンプルを yield で返す。
        yield x[excerpt], y[excerpt]

[A, B, C, D, E, F, G, H, I, J] という10個のデータがあったとしたら、
バッチサイズ3の場合、
1step目 [A, B, C]
2step目 [D, E, F]
3step目 [G, H, I]
4step目 [J]
と4stepで全部のデータを一回ネットワークに流すことになるので、4step で 1epoch である。

その下の for の部分は以下のことをしている。

num_steps = 4
batch_size = 3
num_samples = 10
indices = np.arange(num_samples)

for itr in range(num_steps):
    start = batch_size * itr
    excerpt = indices[start:start + batch_size]
    print(excerpt)
# [0 1 2]
# [3 4 5]
# [6 7 8]
# [9]

 学習する。

  1. train_on_batch() で1バッチずつ学習する。
  2. 1 epoch が終わったら、predict() 関数で推論を行う。
  3. 推論結果を np.savetxt() でファイルに保存する。
# 保存用ディレクトリ
out_dirpath = 'prediction'
os.makedirs(out_dirpath, exist_ok=True)

# 学習する。
epochs = 1
for i in range(epochs):  # エポック数分ループする。
    for x_batch, y_batch in get_batch(x_train, y_train_onehot, batch_size=128, shuffle=True):
        # x_batch, y_batch が生成されたミニバッチ

        # 1バッチ分学習する
        model.train_on_batch(x_batch, y_batch)
    # この時点で1 epoch 分の学習が完了

    # エポックごとにテストデータで推論する。
    y_pred = model.predict_classes(x_test)
    result = np.c_[y_pred, y_test]

    # 推論結果を保存する。
    filepath = os.path.join(out_dirpath, 'prediction_{}.csv'.format(i))
    np.savetxt(filepath, result, fmt='%.0f')

 追記

前提として、image_list は (サンプル数, Width * Height) の float 型の numpy 配列
location_list は (サンプル数,) の float 型の numpy 配列です。

print(image_list.shape, image_list.dtype)  # (300, 11250) float64
print(location_list.shape, location_list.dtype)  # (300, 2) float64

その場合に、質問のコードに各エポックごとに推論結果を CSV に保存するは以下のようになります。

# モデルを作成
model = Sequential()
model.add(Dense(8000, input_dim=Z, kernel_initializer='random_uniform',bias_initializer='zeros')) 
model.add(LeakyReLU())
model.add(Dropout(0.2))
model.add(Dense(100,kernel_initializer='random_uniform',bias_initializer='zeros'))
model.add(LeakyReLU())
model.add(Dropout(0.075))
model.add(Dense(50,kernel_initializer='random_uniform',bias_initializer='zeros'))
model.add(LeakyReLU())
model.add(Dropout(0.075))
model.add(Dense(10,kernel_initializer='random_uniform',bias_initializer='zeros'))
model.add(LeakyReLU())
model.add(Dropout(0.0))
model.add(Dense(2))
model.add(Activation("linear"))
model.compile(loss="mean_absolute_percentage_error", optimizer=Adam(lr=LR))

def get_batch(x, y, batch_size, shuffle=False):
    '''ミニバッチを生成するジェネレーター関数
    '''
    num_samples = len(x)
    if shuffle:
        indices = np.random.permutation(num_samples)
    else:
        indices = np.arange(num_samples)

    num_steps = np.ceil(num_samples / batch_size).astype(int)
    # ステップ数 = ceil(サンプル数 / バッチサイズ)
    # 例 np.ceil(10 / 3) = np.ceil(3.33333333...) = 4

    for itr in range(num_steps):
        start = batch_size * itr
        excerpt = indices[start:start + batch_size]
        yield x[excerpt], y[excerpt]

# 保存用ディレクトリ
out_dirpath = 'prediction'
os.makedirs(out_dirpath, exist_ok=True)

# 学習する。
epochs = 5
for i in range(epochs):  # エポック数分ループする。
    for x_batch, y_batch in get_batch(image_list, location_list, batch_size=BATCH_SIZE, shuffle=True):
        # 1バッチ分学習する
        model.train_on_batch(x_batch, y_batch)
    print('training... epoch {}'.format(i))

    # エポックごとにテストデータで推論する。
    y_pred = model.predict(image_list)
    result = np.c_[y_pred, location_list]

    # 推論結果を保存する。
    filepath = os.path.join(out_dirpath, 'prediction_{}.csv'.format(i))
    np.savetxt(filepath, result, fmt='%.0f')

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/25 16:02

    はい,ありがとうございます!
    また頼りにさせていただきます!
    最後に1つだけ,質問なんですが,
    result = np.c_[y_pred, location_list]
    だとCSVで開くと1つのセル数字2つ入っているのですが,別々のセルに入力する方法はありますか?

    キャンセル

  • 2018/10/25 16:06

    Excel で開くとという意味ですか?
    np.savetxt(filepath, result, fmt='%.0f', delimiter=',') で保存する際の区切り文字をスペースではなく、カンマにすればよいかと思います。

    キャンセル

  • 2018/10/25 16:14

    ありがとうございました!解決しました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.71%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる