2015-11-22 4 views
5

閉じたフォーム解を使ってTensorFlowで最小二乗係数を計算したいとします。通常、私はそうのようにこれを行う、Xyは共変量とターゲット変数に対応するTensorFlowプレースホルダです TensorFlowで計算値を定数としてキャッシュする

beta_hat = tf.matmul(
      tf.matmul(tf.matrix_inverse(tf.matmul(tf.transpose(X), X)), tf.transpose(X)), y 
) 

、それぞれでしょう。私はもちろん、私は提供しなかったエラーになるだろう

sess.run(y_pred, feed_dict={X: data_X}) 

私が実行した場合、私はその後、予測を実行したい場合は、私のような何かをするだろう

y_pred = tf.matmul(X, beta_hat) 

、プレースホルダーに必要な値はyです。私はそれを計算した後に定数としてbeta_hatを扱う柔軟性を持っていたいと思います(予測のための新しい共変量行列の新しいプレースホルダーを定義する必要はありません)。これを実現するための一つの方法は、私がセッションを実行し、定数を取得する必要もなく、着信用に別のプレースホルダを作成し、どちらもするように定数としてテンソルを治療するために、よりエレガントな方法があった場合、私は思っていた

# Make it constant. 
beta_hat = sess.run(beta_hat, feed_dict={X: data_X, y: data_y}) 
y_pred = tf.matmul(X, beta_hat) 

です予測に使用するデータ。

私が説明している状況を示すサンプルコードです。

import numpy as np 
import tensorflow as tf 


n, k = 100, 5 
X = tf.placeholder(dtype=tf.float32, shape=[None, k]) 
y = tf.placeholder(dtype=tf.float32, shape=[None, 1]) 

beta = np.random.normal(size=(k,)) 
data_X = np.random.normal(size=(n, k)) 

data_y = data_X.dot(beta) 
data_y += np.random.normal(size=data_y.shape)/3.0 
data_y = np.atleast_2d(data_y).T 

# Convert to 32-bit precision. 
data_X, data_y = np.float32(data_X), np.float32(data_y) 

# Compute the least squares solution. 
beta_hat = tf.matmul(
    tf.matmul(tf.matrix_inverse(tf.matmul(tf.transpose(X), X)), 
       tf.transpose(X)), y 
) 

# Launch the graph 
sess = tf.Session() 
sess.run(tf.initialize_all_variables()) 

print "True beta: {}".format(beta) 
print "Est. beta: {}".format(
    sess.run(beta_hat, feed_dict={X: data_X, y: data_y}).ravel() 
) 

# # This would error. 
# y_pred = tf.matmul(X, beta_hat) 
# print "Predictions:" 
# print sess.run(y_pred, feed_dict={X: data_X}) 

# Make it constant. 
beta_hat = sess.run(beta_hat, feed_dict={X: data_X, y: data_y}) 

# This will no longer error. 
y_pred = tf.matmul(X, beta_hat) 
print "Predictions:" 
print sess.run(y_pred, feed_dict={X: data_X}) 

答えて

1

おそらく反直感的に、後の工程で定数としてbeta_hatを再利用するための最も簡単な方法はtf.Variableに割り当てることであろう。

n, k = 100, 5 
X = tf.placeholder(dtype=tf.float32, shape=[None, k]) 
y = tf.placeholder(dtype=tf.float32, shape=[None, 1]) 

beta = np.random.normal(size=(k,)) 
data_X = np.random.normal(size=(n, k)) 

data_y = data_X.dot(beta) 
data_y += np.random.normal(size=data_y.shape)/3.0 
data_y = np.atleast_2d(data_y).T 

# Convert to 32-bit precision. 
data_X, data_y = np.float32(data_X), np.float32(data_y) 

# Compute the least squares solution. 
beta_hat = tf.matmul(
    tf.matmul(tf.matrix_inverse(tf.matmul(tf.transpose(X), X)), 
       tf.transpose(X)), y 
) 

beta_hat_cached = tf.Variable(beta_hat) 

# Launch the graph 
sess = tf.Session() 

print "True beta: {}".format(beta) 
# Run the initializer, which computes `beta_hat` once: 
sess.run(beta_hat_cached.initializer, feed_dict={X: data_X, y: data_y}) 
# To access the value of `beta_hat`, "run" the variable to read its contents. 
print "Est. beta: {}".format(beta_hat_cached.ravel()) 

# Use the cached version to compute predictions. 
y_pred = tf.matmul(X, beta_hat_cached) 
print "Predictions:" 
print sess.run(y_pred, feed_dict={X: data_X}) 
+0

ravel == eval? (または、この関数は文書化されていますか?) –

0

mrryは確かにエレガントな解決策を提示しました。それが本当にあなたが望むものなら、彼の答えを正しいものとしてマークすることを検討すべきです。

しかし、これは、私がプレースホルダに関する混乱の原因と感じるものを明確にするのに適していると思います...これは必ずしも質問した人に向けられたものではありませんが、この質問につきものになる多くの初心者に適しています。


プレースホルダーは機能入力のように考えるべきです。だから、最初、私は様々な入力xy与えられた出力を計算する関数を持つようにしたい場合は、その後、私は何ができる

...のは、それはPythonでどのように動作するかを確認し、[I Tensorflowに同等のフォームが表示されますしましょう私の特定のケースでは、私が持っていること、しかし

f(1,3) = 3 
f(1,4) = 4 
f(2,3) = 6 
f(2,4) = 8 

:このようなこと...

def f(x,y): 
    # For example... 
    return x * y 

具体的には、私はxyのためのさまざまな値でこの関数を呼び出すことができます固定値はyです。だから、私の場合は、引数としてyを渡すのは意味がありません。代わりに、私はyの値を関数に焼き付け、ちょうどxを変えたいと思います。私もあることを知っていれば、同様に

g(1) = 3 
g(2) = 6 

:私はgを呼び出すたび、yは3の固定値を持つことになります今

y = 3 
def g(x): 
    return x * y 

:これを行うには、私は単にyの外側の値をキャプチャすることができます今、私はを呼び出すとき

x = 2 
def h(): 
    return g(x) 

xが固定されて、私はxの外側の値をキャプチャすることができ、私は暗黙のうちにh()=g(2)=f(2,3)を呼び出しています。

これは素晴らしいですが、問題は、hを呼び出すたびにf(2,3)を呼び出すのと同じですので、乗算をやり直すことです。このようにパフォーマンスを向上させるために、私は式を評価して、ちょうどこの事前に計算値を返す関数を持つことができます。

val = h() 
def h23(): 
    return val 

どんなに私はh23を呼び出す回数、乗算が唯一のラインval = h()に(一度実行されません)。

Tensorflowにも同様の概念があります。

あなたは両方の入力を変えることができます機能を持つようにしたい場合は、あなたが両方のインスタンスのためのプレースホルダオブジェクトを作成しなければならない、とのセッションで実行しているときに、フィード辞書に値を関数に渡す:

dtype = tf.float64 
shape =() 
x = tf.placeholder(dtype, shape) 
y = tf.placeholder(dtype, shape) 
fxy = f(x,y) 
with tf.Session() as sess: 
    print(sess.run(fxy, {x:1,y:3})) 
    print(sess.run(fxy, {x:1,y:4})) 
    print(sess.run(fxy, {x:2,y:3})) 
    print(sess.run(fxy, {x:2,y:4})) 
私の値のいずれかが変更されない場合

はしかし、その後、私は直接の定数として、それを初期化し、「それに焼き」この値を使用して新しい機能を作成することができます。

y = tf.constant(3) 
gx = f(x, y) 
with tf.Session() as sess: 
    print(sess.run(gx, {x:1})) 
    print(sess.run(gx, {x:2})) 

キーポイントは、今ということであるIの値を渡す必要はありません私のフィード辞書に10。これは定数であり、式gxに取り込まれます。 xも一定であれば
同様に、私はそれを宣言する必要があります。

x = tf.constant(2) 
h = f(x,y) 
with tf.Session() as sess: 
    print(sess.run(h)) 

あなたが見ることができるように、私のすべての変数が一定であることから、私は全くフィード辞書を必要としません。これは、Tensorflowと同等のもので、引数なしで関数を呼び出す場合です(h()など)。

ただし、前と同じように、私がhを呼び出すと、毎回グラフを再評価する必要があるかもしれません。だから私は2つの選択肢があります。

  1. 結果をnumpyで計算し、その値をテンソルフロー定数でラップすることができます。
  2. 出力をテンソルフローで計算し、それをセッションで実行してnumpy値を取得し、それを定数にラップすることができます。最初のオプションで

、私はこの

fxy = tf.constant(f(2,3)) 

のようなものは、今私はTensorflowの外の関数の値を事前に計算して、私が使用できるように、定数としてその値をラップしているんだろうそれは他のテンソルフロー関数である。

逆に、あなたの関数は、いくつかの複雑なTensorflow組み込み関数を使用している場合、あなたは唯一のオプション2を検討する、またはあなたの関数を実行するために本当に時間がかかる場合、あなたはそれがTensorflowでパソコンに速くなると思う:

with tf.Session() as sess: 
    fxy = tf.constant(sess.run(h)) 

へここで何が起こっているかを理解し、

h = f(tf.constant(1), tf.constant(3)) 

は、だから私はフィード辞書を渡す必要はありませんことを思い出してください。スニペットsess.run(h)は、テンソルフロー内でその乗算を実行し、Numpy配列として返します。最後に、その値をtf.constantでラップして、他のTensorflow関数でも使用できるようにします。

関連する問題