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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Q&A

解決済

1回答

6757閲覧

画像認識を用いた回帰分析

FALLOT

総合スコア16

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

0グッド

0クリップ

投稿2018/10/23 05:38

編集2018/10/23 07:42

この画像が今回の入力データです
今回の入力データです.二値化しています.

誤差が減らない

kerasを用いて画像を用いた回帰分析をしています.
以下のコードでは誤差が下がりません.
結果はこんな感じです.

Epoch 84/500
1600/1600 [==============================] - 5s 3ms/step - loss: 14.8227 - val_loss: 5.6889
Epoch 85/500
1600/1600 [==============================] - 5s 3ms/step - loss: 15.6330 - val_loss: 6.1703
Epoch 86/500
1600/1600 [==============================] - 5s 3ms/step - loss: 15.7420 - val_loss: 6.5914
Epoch 87/500
1600/1600 [==============================] - 5s 3ms/step - loss: 15.3729 - val_loss: 3.6529

原因が分かる方は宜しくお願い致します.
今回用いているのは
活性化関数:LeakyReLU
損失関数:相対誤差

#最大応力の値の予測 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 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 = 1000 B = 1000 sum =A+B # 学習用のデータを作る. image_list = [] location_list = [] #ハイパーパラメータ #画像サイズ x = 150 y = 75 Z = x*y #入力層のノード数 #エポック数 E = 500 #バッチサイズ 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(8000, input_dim=Z,kernel_initializer='random_uniform',bias_initializer='zeros')) #model.add(Activation("LeakyReLU")) model.add(LeakyReLU()) model.add(Dropout(0.5)) model.add(Dense(100,kernel_initializer='random_uniform',bias_initializer='zeros')) model.add(LeakyReLU()) model.add(Dropout(0.2)) model.add(Dense(50,kernel_initializer='random_uniform',bias_initializer='zeros')) model.add(LeakyReLU()) model.add(Dropout(0.2)) model.add(Dense(10,kernel_initializer='random_uniform',bias_initializer='zeros')) model.add(LeakyReLU()) model.add(Dropout(0.2)) 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=",") 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()

追記
出力層の活性化関数をlinearにしたところ誤差が25%まで下がりましたが,それ以降が下がらないです.

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tabuu

2018/10/23 05:44

画像を認識して、何を分析したいのでしょうか?
FALLOT

2018/10/23 05:50

私の研究で,画像ごとに数値を与えて,画像のパターンごとに数値を予測するという形.
FALLOT

2018/10/23 05:51

詳しくいうと,複合材料を模式した画像から,中の物質の配置関係でどれくらい大きな内部の力が発生しているのか予測しています.
guest

回答1

0

ベストアンサー

なにを回帰分析したいのでしょうか?

パット見た感じ、全結合層が多すぎる気がするのですが。。
画像なら CNN を使ったほうがよいかと思います。

追記

predictがニューラルネットの結果を出力しているもの

その認識であっていますよ。
整理すると、以下のようになります。

dropout: 学習時に設定した確率に従い、ランダムにニューロンを脱落させる処理。推論時は適用されない

  • predict(): ニューラルネットワークの予測値: 推論時なので dropout なしのネットワーク計算された値。
  • evaluate(): ニューラルネットワークの損失関数の値: 推論時なので dropout なしのネットワーク計算された値。
  • fit() 時に表示される val_loss: 推論時なので dropout なしのネットワークで計算された値。
  • fit() 時に表示される loss: 学習時の dropout ありのネットワークで計算された値。

なぜ fit() 時に表示される loss は14%なのに、evaluate() 時の誤差は2.6%なのか
なぜ fit() 時に表示される loss は14%で val_loss は2%代なのか

これらは上記の通り、loss の値は dropout が適用されたネットワークで計算した値で、その他は推論時なので dropout を適用していないネットワークで計算した値だからです。

最終エポック終了時の予測,あわよくば各エポック毎をcsvに出力する方法はありますか?

CSVLogger を使うと、各エポックごとの結果をファイルに残せます。

csv_logger = CSVLogger('training.log') model.fit(X_train, Y_train, callbacks=[csv_logger])

投稿2018/10/23 05:43

編集2018/10/23 12:37
tiitoi

総合スコア21954

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FALLOT

2018/10/23 05:56

上記に示すように画像ごとに数値を与えて,画像のパターンごとに数値を予測するという形です.複合材料の機械学習の適用例が少ないので,まずはMLPから初めています. CNNもやろうとはしたのですが,それぞれの画像の特徴量が少なく,画像サイズも正確に決めていないので断念しました..
tiitoi

2018/10/23 06:02

> 画像ごとに数値を与えて 画像ごとにラベルがついてる普通のクラス分類問題ということでしょうか? > 画像サイズも正確に決めていない 異なる複数の大きさの画像があるということでしょうか? リサイズすればいいかと思います。 画像のクラス分類問題であれば、CNN を使ったほうがいいです。 質問のコードのように沢山全結合層を重ねても過学習してうまくいかないと思います。
tiitoi

2018/10/23 06:04

出力層が Activation("softmax") なのに、損失関数が mean_absolute_percentage_error となっているのはどういうことなのでしょうか?クラス分類をやりたいのか、回帰問題を解きたいのかどちらなのでしょうか
FALLOT

2018/10/23 06:05

CNNは画像サイズええおいつでも変更しても使えるのですか? 基本的に,上記のコードやっているのですが,多少の変更でCNNができるのでしょうか. プーリングのところがイマイチ分からなくて...
FALLOT

2018/10/23 06:13

> 画像ごとに数値を与えて 基本的には,回帰問題だと思っています.ある材料の中に異なる材料が入ることにより,内部で発生する力が異なります.そのため1mmでもずれると力が変わります.その内部の位置関係によって力が異なるのでそれを予測したいと考えています.
FALLOT

2018/10/23 06:14

> 画像サイズも正確に決めていない 画像を大きくすれば,材料の小さいな変動も考慮できるので,いつもリサイズで大きさ変更してチューニングしています.
tiitoi

2018/10/23 06:36

整理すると、 入力: 画像 (データを可視化したグラフ?) 出力: なんらかの値 ということでしょうか?入力画像がどのようなものかわからないので、質問欄を編集して貼ることはできますか?
FALLOT

2018/10/23 06:52

できました!
tiitoi

2018/10/23 07:01 編集

画像を拝見しました。この円が期待する出力によって微妙に違うのでしょうか?微妙な位置の差が重要になってくるようですと、Max Pooling で情報が消える可能性があるので、全結合層でもいいかもしれませんね。ただ、上記のコードは全結合層が多すぎる気がします。 多ければよいというものではないので、最初は3層とか少なめでやったほうがいいと思います。 あと、回帰問題をやりたいのであれば、Activation("softmax") は消して、出力層の活性化関数は恒等写像 (つまり、なにも変換しない) にしましょう。
FALLOT

2018/10/23 07:46

素早いご返信,ありがとうございます. 3層に変更し,出力層の活性化関数は恒等関数にしました. バリデーションの誤差の方が小さいため,過学習しているのかもしれないです. 追記 画像をリサイズして小さくしてしまうと,画像は同じでも数値が同じになってしまうかもしれません.
tiitoi

2018/10/23 08:26

過学習は学習誤差は下がるのに、バリデーション誤差は下がらない現象ですので、バリデーション誤差が下がっているのであれば、過学習ではないです。
FALLOT

2018/10/23 08:43

なるほど そのあたりは勉強不足でよくわかってないです. なぜ,バリデーション誤差の方が低いのでしょうか?単純な考えとしては,データ数が少ないため,学習が十分に出来ずに誤差が高くなりました.
FALLOT

2018/10/23 08:46

もう1つ疑問に思ったのですが, 訓練中のkerasが表示する誤差は Epoch 497/500 1600/1600 [==============================] - 5s 3ms/step - loss: 14.8476 - val_loss: 4.6440 Epoch 498/500 1600/1600 [==============================] - 5s 3ms/step - loss: 14.4474 - val_loss: 4.8210 Epoch 499/500 1600/1600 [==============================] - 5s 3ms/step - loss: 14.4875 - val_loss: 3.1096 Epoch 500/500 1600/1600 [==============================] - 5s 3ms/step - loss: 14.2740 - val_loss: 2.8100 2000/2000 [==============================] - 0s 216us/step loss:2.593585350036621 このように,14%まで下がらないのですが,最終の予測値と正解の値を比較すると誤差が約2.6%でした. なぜでしょうか?
tiitoi

2018/10/23 09:00

> なぜ,バリデーション誤差の方が低いのでしょうか? 学習がうまくいっているか、バリデーション用のデータ数が少ないのでたまたま学習誤差より低くなったかのどちらかでしょう。 前者なら問題ないと思いますが。 結局、学習に使用してないデータで推論して誤差が低ければいい話なので、まず最初にデータ全体を http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html で学習用、テスト用に分けておき、学習用のデータで学習し、テスト用のデータで推論して誤差が少なければうまくいったと判断してよいでしょう。
FALLOT

2018/10/23 10:44

ありがとうございます. コマンドプロントに表記されている14%の誤差と最終の予測値と正解の値の誤差が2%である違いの原因,分かりますか?
tiitoi

2018/10/23 10:59 編集

evaluate() したときの誤差と fit() 時に表示される誤差は同じ条件で計算されてないので、比較することは無意味です。 * 学習時の学習誤差計算は image_list のうち、validation_split=0.2 としているため、2割は計算には使用していない。一方、evaluate() 時は全部使用している。 * 学習時は dropout が有効になっているため、evaluate() 時とはネットワークが異なる。 バリデーション誤差の計算時も dropout は無効になっているため、そう考えると、学習誤差がバリデーション誤差より悪いのは dropout の影響の可能性がありますね。 dropout(0.5) ということは、学習時はランダムに半分のニューロンが無効になっているということを意味します。各層の dropout の値を調整してみて、最適な値を探したらどうでしょうか。
FALLOT

2018/10/23 11:17

なるほど 単純に考えれば,dropoutを使わないニューラルネットのほうが結果がいいってことですね笑 model.predict(image_list)で出力した結果はニューラルネットの結果だと考えているのですが.. そのmodel.predictの予測値と正解値の誤差の平均が2.56%なのですが,どうしてなんでしょうか
tiitoi

2018/10/23 11:25

ニューラルネットワークの学習で得られるのは、あくまで目標関数に対する近似なので、誤差が生じるのは必然だと思いますが。もちろん、パラメータやモデルを調整する、学習データを増やす等で誤差をまだ減らせる余地はあります。
FALLOT

2018/10/23 12:04

model.predictでた予測値はニューラルから出てきた値ですよね?エポック中では,14%なのに,なぜ最後に急に2%みたいによくなるのかと..
tiitoi

2018/10/23 12:08

先程も説明した通り、学習中に表示される 14%というのは dropout が有効になったネットワークで計算した値ですよね。 一方、model.predict() では推論時なので、dropout が無効になったネットワークで計算した値です。なので、そうのような結果になることも考えられます。 dropout の仕組みは理解されているのでしょうか?
FALLOT

2018/10/23 12:22

てっきり,predictがニューラルネットの結果を出力しているものだと思ってました.dropoutの仕組みはおおかた把握してるつもりです..多分.. もともと,1エポック毎にそれぞれのデータの予測データをcsvに出力したかったのですが,メモリが持たず最終の予測値を出力しようと思い,evaluateを使っていました.
FALLOT

2018/10/23 12:23

最終エポック終了時の予測,あわよくば各エポック毎をcsvに出力する方法はありますか?
tiitoi

2018/10/23 12:46

回答に追記しました。
FALLOT

2018/10/23 12:59

ありがとうございます.私自身もCSVLoggerを使用しているのですが,CSVにepoch,loss,val_lossを出力しています.しかし,例えば,データが1000個の場合,1エポック毎に1000個の予測値を出力することは可能ですか?
FALLOT

2018/10/23 13:01

こんなにも畳み掛けて質問をしても的確に丁寧に答えてくださりありがとうございます. フォローさせていただきました.
tiitoi

2018/10/23 13:11

誤差が fit() 時に表示される値と evaluate() で異なる点について、疑問は解消できましたでしょうか? CSVの件は回答するので、別途質問を立てていただけますか。
FALLOT

2018/10/23 13:21

はい!ありがとうございます! 質問を立てて頂くので少々お待ち願えますか?
FALLOT

2018/10/23 13:29

kerasを用いてCSVに各エポック毎に出力したい という題名で質問を立てました! 宜しくお願いします.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問