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

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

ただいまの
回答率

89.52%

[deep_learning初心者]model.predictの結果が何を入れてもarray([[1.]],dtype=foat32)となってしまいます...

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 453

ysk_snn

score 5

前提・実現したいこと

deep_learningを用いて、ある製品の測定値の予測をしたいと思っています。
測定値の取得には多くの時間がかかるため、これを解決したいです。

・製品の外観写真
・製品の測定値

の組み合わせを学習させることで、製品の外観写真があれば測定を行うことなく、
製品の測定値を得られるようになるのが理想です。

発生している問題・エラーメッセージ

なんとかデータを集め、

・製品の外観写真 × 1536枚(うち1530枚を学習用、残り6枚が検証用)
・製品の測定値    × 1356個(うち1530個が学習用、残り6個が検証用)

上記のデータを学習させてみましたが

①エポックを増やしていっても損失が減らない
②predict()にどの写真を入れても同じ結果が返ってくる(array([[1.]],dtype=foat32))

といった状況になり困っています。

①に関しては勉強不足だと思うのですが、②に関してはどこか致命的なミスがあるのではないかと思っています。
コーディング自体まだおぼつかない状態で申し訳ないのですが、ご教示いただければと存じます。

該当のソースコード

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import os
import glob
import tifffile
import tqdm

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.utils import np_utils
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

pic_dir = r'C:\Users\Public\Documents\Python Scripts\pic\01' #外観写真1356枚
data_dir = r'C:\Users\Public\Documents\Python Scripts\data\data.csv' #測定値1536個の保管場所

#測定値
data_plc =  pd.read_csv(data_dir)
data = data_plc.iloc[1:,0] #1536個の測定値を抜き出す
data_array = np.array(data,dtype=float) #maxで1.283、minで-0.27程度です

#外観写真
os.chdir(pic_dir)
pic_list = glob.glob('*.TIF')
pic = []
for i in range(len(pic_list)):
    pic_a = tifffile.imread(pic_dir + '\\' + pic_list[i])
    pic.append(pic_a)
pic_array = np.array(pic) #(1536,140,140)_1536枚の140*140pixelの外観画像
pic_array_2 = pic_array.reshape(pic_array.shape[0], 19600) #140*140pixelのTIF画像を19600の長さで1行に整形
pic_array_3 = pic_array_2.astype('float32')/255 #輝度の正規化

X_train = pic_array_3 [:1530,:] #学習用_外観画像
X_test = pic_array_3 [1530:,:] #テスト用_外観画像
Y_train = data_array [:1530] #学習用_測定値
Y_test = data_array [1530:] #テスト用_測定値

#モデルの定義_人のをまねながら設定したものです
model = Sequential()
model.add(Dense(100, input_shape=(19600,)))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(50))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('softmax'))
model.compile(loss='mean_squared_error', optimizer='adam')
model.summary() 

#学習_バッチサイズが多きいほどすぐに終わる?
df_batch_size = 256
nb_epochs = 10
history = model.fit(X_train, Y_train, epochs = nb_epochs, batch_size = df_batch_size)

#損失の確認_nb_epochs = 100程度にしても多少上下しながら横ばいになります
plt.plot(history.history['loss'], label ='loss')

#予測_X_test[w]_wに0,1,2,3,4,5のどれを入れても結果は同じになります。
model.predict(X_test[0].reshape(1,-1)) #返り値は_array([[1.]], dtype=float32)

試したこと

model.add(Dense(1))
model.add(Activation('softmax'))


としてしまっていたところを

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


と変更して出力がそのまま出てくるようにした

補足情報(FW/ツールのバージョンなど)

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

ネットワークの構造に問題があります。

ネットワークの最後に

model.add(Dense(1))
model.add(Activation('softmax'))

とあります。
Dense(1)によって、データは(データ数, 1次元)に変換されます。
これに対し、ソフトマックス関数を適用するとすべて、1になって帰ってきます。

なぜなら、ソフトマックス関数はその特性から、データのすべての次元を足しあわせると1になるからです。
Denseによって1次元にされているので、1次元でかつ、合計1になるのは、出力1のみです。

さて、一般に測定値のような連続値を予測させる場合、最後の活性化関数にソフトマックス関数は採用しません。

たとえば、測定値の範囲が0~1であれば、シグモイド関数を使用しますし、-1~1であれば、ハイパボリックタンジェント関数(tanh)です。
一方、測定値が0以上の実数であれば、relu関数を使用できるでしょう。
また、たとえば、0~100の範囲に必ず収まるのであれば、シグモイド関数をかけて、さらに100を掛ける、などの方法があると思います。

測定値の範囲に応じて、最後の活性化関数を変更してみてください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/09/25 13:33 編集

    素早いご対応ありがとうございます!!
    おっしゃる通り、活性化関数をlenearに変えたところ、

    test = model.predict(X_test[i].reshape(1,-1))
    print(test[0][0])
    に対して0.08545491のような値が出力されるようになりました!
    また、学習誤差もエポック数に応じて小さくなっていきます!

    しかし、上記の式において i を変えていっても依然として出力値が変化しない状態です。
    こちらに対してもなにかお気付きの点はございませんでしょうか?

    ちなみに出力値(計測値)は、正負どちらの場合もあり、大きさに上限はありません。

    キャンセル

  • 2019/09/25 14:57

    試しに、乱数で同じ形のデータを作り、実行してみたところ、再現できました。

    おそらく、学習が進んだことによる影響だと思います。
    ネットワークの構造上、表現力が低く、平均値を出力すればある程度精度が出るだろうという方向に学習しているものと思われます。

    なぜなら、エポック数を1として実行すると、値が変わったりします。
    エポックが少ない段階ではまだ平均値にたどり着いていないのでしょう。

    解決するには、ネットワークをもう少し複雑にする必要があります。
    具体的には、
    (1) 中間のDenseのユニット数を増やす(100, 50 -> 1000, 500 など)
    (2) Dropout率を下げる
    (3) CNNなどのネットワークに変更する

    などです。
    本格的な高精度の予測をするのであれば、(3)で対応する必要があると思います。
    一先ず、動けばよいということであれば、(1)または(2)を調整するとよいです。

    キャンセル

  • 2019/09/25 15:24

    qax様がおっしゃる通り、一先ず
    中間のDenseのユニット数を増やしてみたところ、
    それぞれの画像で出力が変化しました!!!!

    本当に親身になってきいてくださってありがとうございます。
    初めてteratailを利用したのですが、良かったです!

    キャンセル

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

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

同じタグがついた質問を見る