假设我想使用闭合形式解决方案计算TensorFlow中的最小二乘系数。通常情况下,我会这样做,
beta_hat = tf.matmul(
tf.matmul(tf.matrix_inverse(tf.matmul(tf.transpose(X), X)), tf.transpose(X)), y
)
X
和y
分别是与协变量和目标变量对应的TensorFlow占位符。
如果我想进行预测,我会做类似的事情,
y_pred = tf.matmul(X, beta_hat)
如果我要执行,
sess.run(y_pred, feed_dict={X: data_X})
我当然会收到错误,因为我没有为占位符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})
答案 0 :(得分:2)
也许与直觉相反,在后续步骤中重复使用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})
答案 1 :(得分:0)
但是,我认为这是一个清理我认为是占位符混淆来源的好地方......这不一定针对提出问题的人,但我相信它会与许多偶然发现这个问题的初学者有关...
占位符应该被视为功能输入。首先,让我们回顾一下Python中的工作方式,然后我将在Tensorflow中显示相应的表单......
如果我想有一个函数来计算给定各种输入x
和y
的输出,那么我可以这样做......
def f(x,y):
# For example...
return x * y
具体来说,我可以使用x
和y
的各种值调用此函数:
f(1,3) = 3
f(1,4) = 4
f(2,3) = 6
f(2,4) = 8
但是,在我的特定情况下,我的固定值可能为y
。所以在我的情况下,将y
作为参数传递是没有意义的。相反,我想将y
的价值烘焙到函数中,然后改变x
。为此,我可以简单地捕获y
的外部值:
y = 3
def g(x):
return x * y
现在每当我致电g
时,y
的固定值为3:
g(1) = 3
g(2) = 6
同样,如果我也知道x
已修复,我可以捕获x
的外部值:
x = 2
def h():
return g(x)
现在,当我致电h
时,我隐含地呼叫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} ) )
关键是现在我不需要在我的Feed字典中传递y
的值。它是常量并在表达式gx
中捕获
同样,如果x
也是一个常量,那么我应该这样声明:
x = tf.constant(2)
h = f(x,y)
with tf.Session() as sess:
print( sess.run( h ) )
正如您所看到的,由于我的所有变量都是不变的,因此我根本不需要输入字典。这是Tensorflow等效于调用不带参数的函数,如h()
。
但是,和以前一样,当我调用h
时,可能需要每次重新评估图表。所以我有两个选择。
在第一个选项中,我会做这样的事情
fxy = tf.constant( f(2,3) )
现在我已经预先计算了Tensorflow之外的函数的值,然后将该值包装为常量,以便我可以在其他tensorflow函数中使用它。
相反,如果你的函数使用了一些复杂的Tensorflow内在函数,或者你的函数需要很长时间才能运行,并且你认为Tensorflow中的计算机速度会更快,你只会考虑选项2:
with tf.Session() as sess:
fxy = tf.constant( sess.run( h ) )
要了解这里发生了什么,请回忆一下
h = f( tf.constant(1), tf.constant(3) )
所以我不需要传递一个feed字。代码段sess.run( h )
在tensorflow内运行该乘法,并将其作为Numpy数组返回。最后,我用tf.constant包装该值,以便我可以在其他Tensorflow函数中使用它。