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

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

ただいまの
回答率

90.51%

  • Python

    11683questions

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

  • 機械学習

    956questions

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

  • TensorFlow

    919questions

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,863

zakio49

score 21

前提・実現したいこと

こちらの記事のソースコードを参考に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()

`

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

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

ここが間違っています。

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

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

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

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

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/01 18:17

    ご指摘ありがとうございます。損失関数を偏微分する過程で重みとバイアスを最適化し、誤差自体が重要ではないということは大変に勉強になりました!

    入力と重みとバイアスの値からどう推定するか? という式を再利用したいのですが、モデルの組み方が異なるかで躓いています。ご教授いただけないでしょうか?

    キャンセル

  • 2017/07/01 18:21 編集

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

    キャンセル

  • 2017/07/01 20:37

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

    キャンセル

+2

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

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

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

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

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

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

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

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

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/01 18:25

    ニューラルネットワークの基本的な誤りなど、あやふやだった言葉の使い方など・理解がとても明瞭になり勉強になりました。ありがとうございます。

    入力と重みとバイアスの値からどう推定interface()式を再利用したいのですが、モデルの組み方が異なるかで躓いています。ニシコクンさま、ご教授いただけないでしょうか?

    キャンセル

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

  • Python

    11683questions

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

  • 機械学習

    956questions

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

  • TensorFlow

    919questions

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