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

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

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

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

5411閲覧

Tensorflow:一度学習したものの損失関数の値を保持・復元して、新たな入力に対して予測を行いたいです。

zakio49

総合スコア29

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

2クリップ

投稿2017/06/30 20:59

編集2017/07/01 09:14

前提・実現したいこと

こちらの記事のソースコードを参考にNNを組んで見ました。
一度学習したものの損失関数の値を保持・復元して、新たな入力に対して予測を行いたいです。お知恵を拝借したいです。よろしくお願い致します。

ニューラルネットワークでプロ野球選手の給与を査定してみる
http://qiita.com/sergeant-wizard/items/9bb45c0850aebca2bc07

TensorFlowでmodelを保存して復元する
http://testpy.hatenablog.com/entry/2017/02/02/000000

TensorFlowのPythonコードの初歩を噛み砕いてみる
http://qiita.com/To_Murakami/items/5984a4891597b17fc40e

実行環境はwindows10+Anaconda+python3.5+tensorflow1.0~になります

現状の理解・躓いていると思っている箇所
*修正7/1 17:02

色々な点を修正させていただき新たな疑問として

復元したモデルを再利用する流れについては
1.変数の読み込み(csvファイル)
2.使えるデータ形式に変化()
3.学習したときに使ったinterface(score_placeholder)で使える形にモデルを作る
4.meta.ckptを復元して、重みをもとに予想を行う関数(interface)にいれる
5,sess.runを行い予想値をプリントする。

**ただ、実践データは学習データと異なり正解のデータがないのでcsvファイルの列も一つ少ないので、モデルの組み方が異なると、最初に学習の時に使ったinterface()関数をそのまま使えないのでwith tf.Session() as sess2:ないで新たに関数を定義したらmodel.ckptの値が反映できないのではないかとそのあたりで躓いています。
現状の実践データ正解データも込みで行っていますがエラーが発生しておりなかなかうまくいきません。よろしくお願いいたします
**

with tf.Session() as sess2: # 変数の読み込み #新しいデータ raw_input2 = numpy.loadtxt(open("one_record.csv"), delimiter=",") [tensor, score] = numpy.hsplit(raw_input2, [1]) #モデルつくり feed_dict_test2 ={ tensor_placeholder: tensor, score_placeholder: score, loss_label_placeholder: "loss_test" } #復元して、損失関数で定まった、重みをもとに予想を行う関数にいれる saver = tf.train.Saver() cwd = os.getcwd() saver.restore(sess2,cwd + "/model.ckpt") best_match2 = sess2.run(inference, feed_dict=feed_dict_test2) print(best_match2) print("fin") sess2.close()

エラーコード

Traceback (most recent call last): File "tensor_session.py", line 103, in <module> best_match2 = sess2.run(inference, feed_dict=feed_dict_test2) File "C:\Users\takkun\Anaconda3\envs\tensorenv\lib\site-packages\tensorflow\python\client\session.py", line 767, in run run_metadata_ptr) File "C:\Users\takkun\Anaconda3\envs\tensorenv\lib\site-packages\tensorflow\python\client\session.py", line 944, in _run % (np_val.shape, subfeed_t.name, str(subfeed_t.get_shape()))) ValueError: Cannot feed value of shape (1,) for Tensor 'tensor_placeholder:0', which has shape '(?, 1)'

二重誤差の最小値が重要ではなくて、重みとバイアスが重要であることがよくわかりました。model.ckpt.metaファイルにそれぞれのリンクの重みの値が書かれていなかったので、二重誤差の値から復元できると勘違いしていました。

↓結局、model.ckpt.metaはブラックボックスのままなのですが(制御コードとか埋め込まれており)リンクによると MetaGraphDef protocol buffer.がmodel.ckpt.metaファイルをもとにプロセスを復元するから、重みの値はその中で復元されるから、直接は書いてないよという理解をしました。
What is the TensorFlow checkpoint meta file?
https://stackoverflow.com/questions/36195454/what-is-the-tensorflow-checkpoint-meta-file/36203288#36203288

ニューラルネットワークの流れというか保持・復元のしていること(修正)
1,出力層の出力値が教師データに近づいてるのかを表す尺度として損失関数を重みやバイアスで指定した回数(10000回)偏微分を行い。2乗誤差 Eをを小さくしようとする。
2,その時の重み、ベクトル量を保持する。
3,新たな入力(実践データ)に対して、保持された重みとバイアス用いて実践データを**inference(score_placeholder)**に入れることで適当な値が予想できると思っています。

*誤差逆伝播法の理解に誤りがありました、入力ノードから次の層へのリンク一つ一つにランダムで割り当てられた重みがつき、それらの和がシグモイド関数orReLU関数に入力されて次の層のノードに入力され、行きついた値と教師データの値との間の誤差をみて、重みを変化させるフィードバックを与えるという理解をしています。
このままだとプログラムの誤差が最小の値を保持していても、復元した際のノード毎に与える重みはどこに保存されているかがわからず困っています。
→直接の値はかかれていないMetaGraphDef protocol bufferの中で復元される認識です(お手上げです)

pythonに不慣れなところもあるのですが、困っているのでぜひ答えていただけたら幸いです。

import tensorflow as tf import numpy import os cwd = os.getcwd() SCORE_SIZE = 12 HIDDEN_UNIT_SIZE = 70 TRAIN_DATA_SIZE = 45 raw_input = numpy.loadtxt(open("test.csv"), delimiter=",") [tensor, score] = numpy.hsplit(raw_input, [1]) [tensor_train, tensor_test] = numpy.vsplit(tensor, [TRAIN_DATA_SIZE]) [score_train, score_test] = numpy.vsplit(score, [TRAIN_DATA_SIZE]) def inference(score_placeholder): with tf.name_scope('hidden1') as scope: hidden1_weight = tf.Variable(tf.truncated_normal([SCORE_SIZE, HIDDEN_UNIT_SIZE], stddev=0.1), name="hidden1_weight") hidden1_bias = tf.Variable(tf.constant(0.1, shape=[HIDDEN_UNIT_SIZE]), name="hidden1_bias") hidden1_output = tf.nn.relu(tf.matmul(score_placeholder, hidden1_weight) + hidden1_bias) with tf.name_scope('output') as scope: output_weight = tf.Variable(tf.truncated_normal([HIDDEN_UNIT_SIZE, 1], stddev=0.1), name="output_weight") output_bias = tf.Variable(tf.constant(0.1, shape=[1]), name="output_bias") output = tf.matmul(hidden1_output, output_weight) + output_bias return tf.nn.l2_normalize(output, 0) def loss(output, tensor_placeholder, loss_label_placeholder): with tf.name_scope('loss') as scope: loss = tf.nn.l2_loss(output - tf.nn.l2_normalize(tensor_placeholder, 0)) tf.summary.scalar('loss_label_placeholder', loss) return loss def training(loss): with tf.name_scope('training') as scope: train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss) return train_step with tf.Graph().as_default(): tensor_placeholder = tf.placeholder("float", [None, 1], name="tensor_placeholder") score_placeholder = tf.placeholder("float", [None, SCORE_SIZE], name="score_placeholder") loss_label_placeholder = tf.placeholder("string", name="loss_label_placeholder") feed_dict_train={ tensor_placeholder: tensor_train, score_placeholder: score_train, loss_label_placeholder: "loss_train" } feed_dict_test={ tensor_placeholder: tensor_test, score_placeholder: score_test, loss_label_placeholder: "loss_test" } output = inference(score_placeholder) loss = loss(output, tensor_placeholder, loss_label_placeholder) training_op = training(loss) summary_op = tf.summary.merge_all() init = tf.global_variables_initializer() best_loss = float("inf") with tf.Session() as sess: summary_writer = tf.summary.FileWriter('data', graph_def=sess.graph_def) sess.run(init) for step in range(10000): sess.run(training_op, feed_dict=feed_dict_train) loss_test = sess.run(loss, feed_dict=feed_dict_test) if loss_test < best_loss: best_loss = loss_test best_match = sess.run(output, feed_dict=feed_dict_test) if step % 100 == 0: summary_str = sess.run(summary_op, feed_dict=feed_dict_test) summary_str += sess.run(summary_op, feed_dict=feed_dict_train) summary_writer.add_summary(summary_str, step) saver=tf.train.Saver() saver.save(sess,cwd+'/model.ckpt') print(cwd) print('Saved a model.') sess.close() with tf.Session() as sess2: # 変数の読み込み #新しいデータ raw_input2 = numpy.loadtxt(open("one_record.csv"), delimiter=",") [tensor, score] = numpy.hsplit(raw_input2, [1]) #モデルつくり feed_dict_test2 ={ tensor_placeholder: tensor, score_placeholder: score, loss_label_placeholder: "loss_test" } #復元して、損失関数で定まった、重みをもとに予想を行う関数にいれる saver = tf.train.Saver() cwd = os.getcwd() saver.restore(sess2,cwd + "/model.ckpt") best_match2 = sess2.run(inference, feed_dict=feed_dict_test2) print(best_match2) print("fin") sess2.close()
ikuwow👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

引用テキスト1,出力層の出力が教師信号に近づいてるのかを表す尺度として2乗誤差 Eがもっとも小さい値を保持する。

ここが間違っています。

TensorFlowが保持しているのは、重みやバイアスの値と、それらの値を使ってどのように推定や誤差を計算するか? という式の形です。

「2乗誤差 Eがもっとも小さい値を保持する」こともありません。

入力と重みとバイアスの値からどう推定するか? という式

入力と重みとバイアスの値から推定した値が正解の値からどのぐらい離れているか? を計算する式
を与えます。
前者が推定のモデルで、後者が損失関数です。

損失関数を重みやバイアスの変数で微分(偏微分)すると、重みやバイアスの値を正方向に動かしたら誤差が少なくなるのか、負方向に動かしたら誤差が少なくなるのか、どの値を動かしたら誤差がより小さくなるのかが計算できます。
それで重みやバイアスを動かしていくのが訓練です。
訓練によってじゅうぶんにいい値が出たと思ったら(その判断は難しいのですが)訓練をやめて tf.train.Saversave 関数で重みやバイアスを保存します。
それ が訓練によって得たモデルです。

あとは再訓練しようとするまでは、損失関数の出番はありません。
損失関数には 正解の値 が必要なことを思い出してくださいね。
未知のデータを持ってきてそれを推測しようという時に、 正解の値 が必要になる損失関数が計算できるはずはありません。

こんなところでどうでしょうか。

投稿2017/07/01 03:41

quickquip

総合スコア11029

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

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

zakio49

2017/07/01 09:17

ご指摘ありがとうございます。損失関数を偏微分する過程で重みとバイアスを最適化し、誤差自体が重要ではないということは大変に勉強になりました! 入力と重みとバイアスの値からどう推定するか? という式を再利用したいのですが、モデルの組み方が異なるかで躓いています。ご教授いただけないでしょうか?
zakio49

2017/07/01 09:22 編集

二重投稿の分を消させていただきます。
quickquip

2017/07/01 11:37

inferene関数はplaceholderを受け取って「推定のための計算グラフ」を返しますよね。 その返り値を output に代入してますよね。 sess2.run(output, {score_placeholder: score}) で計算できると思いますが(csvにどう入っているかわかりませんが)。
guest

0

正直ソースコードは見てないのですが、根本的に誤解が多いようなのでそこだけ指摘させていただきます。

損失関数の値を保持・復元
損失関数の値は逆伝搬に用いられる以外は、あくまで目安として捉えるものです。
この値が瞬間的に小さいからと言って、その瞬間のモデルが良いとは全く言えません。
モデル自体を評価したいなら、バリデーションデータに対する精度や再現率を用いてください。

二乗誤差Eがもっとも小さい値を保持する
違います。指定した回数、あるいは条件を満たすまで学習したときのパラメータが一般に保持されます。
しかし、パラメータが過学習している恐れもありますから、途中のデータも保持することが多いです。

そのときの重さは二乗誤差Eから復元できるか
全く出来ません。
二乗誤差Eがスカラー量であるのに対して、重みはリンクの本数だけの要素を持つベクトル量です。

新たな入力に対して、定められた重さと二乗誤差を用いて適切な値を予想
新たな入力と言うのが実践データだとするなら、全く見当違いです。
二乗誤差が求められるのは、正解が明確に存在する教師データだからです。
また、ニューラルネットワークのパラメータは重みだけではなく、バイアスも考える必要があります。

入力ノードの一つ一つにランダムで割り当てられた重み
重みがつくのはノードではなくてリンクですし、隠れ層のパラメータも加味すべきですね。
また、重みの初期値がランダムであることに必然的な理由はないです。

行きついた値と教師データの値との間の誤差を見てフィードバック
かなりふんわりとした表現ですが、まあこの部分は正しいと思います。

根本的に誤った記憶
ジグモイドではありません。シグモイドです。
RuLAではありません。それはドラクエの呪文です。正しくはReLUです。
また、これに関しては人によりけりなのかもしれませんが、重さより重みの方が一般的かと思います。

投稿2017/07/01 03:29

編集2017/07/01 05:13
LouiS0616

総合スコア35658

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

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

zakio49

2017/07/01 09:25

ニューラルネットワークの基本的な誤りなど、あやふやだった言葉の使い方など・理解がとても明瞭になり勉強になりました。ありがとうございます。 入力と重みとバイアスの値からどう推定interface()式を再利用したいのですが、モデルの組み方が異なるかで躓いています。ニシコクンさま、ご教授いただけないでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問