Python 在TensorFlow中将计算值缓存为常量

Python 在TensorFlow中将计算值缓存为常量,python,numpy,constants,linear-regression,tensorflow,Python,Numpy,Constants,Linear Regression,Tensorflow,假设我想用闭式解计算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.r

假设我想用闭式解计算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})

也许与直觉相反,在后续步骤中将
beta_hat
重新用作常数的最简单方法是将其指定给:


mrry确实提出了一个优雅的解决方案。如果你确实想要的话,你应该考虑把他的答案标记为正确。 然而,我认为这是一个很好的地方来澄清我认为是关于占位符的混乱来源。。。这不一定是针对提出问题的人的,但我相信这对很多无意中发现这个问题的初学者来说是有意义的


占位符应被视为类似于函数输入。首先,让我们回顾一下它在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
的值。它是常量,并在表达式
gx
中捕获
类似地,如果
x
也是一个常数,那么我应该这样声明:

x = tf.constant(2)
h = f(x,y)
with tf.Session() as sess: 
    print( sess.run( h ) )
正如您所看到的,由于我所有的变量都是常量,所以我根本不需要提要字典。这是Tensorflow,相当于调用不带参数的函数,如
h()

但是,与前面一样,当我调用
h
时,每次可能都需要重新计算图形。所以我有两个选择

  • 我可以用numpy计算结果,然后用tensorflow常量包装该值
  • 我可以在tensorflow中计算输出,在会话中运行它以获得numpy值,然后将其包装为常量 在第一个选项中,我会这样做

    fxy = tf.constant( f(2,3) ) 
    
    现在我已经在Tensorflow之外预先计算了函数的值,然后将该值包装为常量,以便在其他Tensorflow函数中使用

    相反,如果函数使用了一些复杂的张紧流内蕴,或者如果函数占用了很长时间,并且您认为在TysFoeSoT中计算机的速度会更快,则只考虑选项2:

    with tf.Session() as sess: 
        fxy = tf.constant( sess.run( h ) )
    
    要了解这里发生了什么,回想一下

    h = f( tf.constant(1), tf.constant(3) )
    
    因此我不需要传递提要dict。代码段
    sess.run(h)
    在tensorflow内部运行乘法,并将其作为Numpy数组返回。最后,我用tf.constant包装该值,以便在其他Tensorflow函数中使用它

    拉威尔==评估?(或该功能是否有文档记录?)
    with tf.Session() as sess: 
        fxy = tf.constant( sess.run( h ) )
    
    h = f( tf.constant(1), tf.constant(3) )