Python Tensorflow:在同一操作中共享两个不同变量的值
我最近一直在试验TensorFlow(TF),我遇到了这个问题:假设我想计算函数的值和梯度 其中x的索引不同,但都指向相同的向量,J是随机常数(在物理学中,这是一个自旋玻璃模型)。然后简单地计算梯度wrt 因此,Python Tensorflow:在同一操作中共享两个不同变量的值,python,tensorflow,Python,Tensorflow,我最近一直在试验TensorFlow(TF),我遇到了这个问题:假设我想计算函数的值和梯度 其中x的索引不同,但都指向相同的向量,J是随机常数(在物理学中,这是一个自旋玻璃模型)。然后简单地计算梯度wrt 因此,f对N^3项求和,gradf对N^2项求和N次。我已经实现了f,方法是将总和的所有项生成为秩3张量,并对所有条目进行总和缩减。然后我申请 tf.梯度(f,xk)[0] 其中f是损失函数,xk是变量。这是一个MWE,假设所有的J都是1 将numpy导入为np 导入tensorflow
f
对N^3项求和,gradf
对N^2项求和N次。我已经实现了f
,方法是将总和的所有项生成为秩3张量,并对所有条目进行总和缩减。然后我申请
tf.梯度(f,xk)[0]
其中f是损失函数,xk是变量。这是一个MWE,假设所有的J都是1
将numpy导入为np
导入tensorflow作为tf
#首先我定义变量
n=10#x的大小
x1=tf.变量(tf.零([n],dtype='float64'))
x2=tf.placeholder(tf.float64,shape=[n])
#这里我定义了成本函数
f_张量=tf.mul(tf.mul(tf.reformate(x1,[n]),
tf.重塑(x2,[n,1]),
tf.重塑(x2[n,1,1]))
f=tf.约化和(f\u张量)
session=tf.session()
初始化所有变量()
会话运行(init)
#在测试阵列上运行
xtest=np.one(n)
res=session.run([f,tf.gradients(f,x1)[0]],
feed_dict={x1:xtest,
x2:xtest})
断言res[0]==1000
assert all(res[1]==np.array([100表示xrange(n)])
我需要多次单独调用run
,并且我希望将变量赋值的数量减少到一个,因为x1,x2引用相同的向量
对n=200
(在GeForce GTX 650上)的相关示例进行的一些分析表明
- cuMemcpyDtoHAsync占用63%的时间
- CUMEMCPYHTOASYNC 18%和
- cuEventRecord 18%李>
n
,开销会变得更大,因此部分抵消了使用GPU的好处
关于如何通过只传输一次x来减少开销,有什么建议吗
此外,对于如何减少任何其他开销的任何其他建议,我们将不胜感激
编辑
为了在行动中显示问题,我将遵循mrry的建议。
如果我用x1替换x2的所有实例,那么MWE将如下所示
#首先定义变量
n=10#x的大小
x1=tf.变量(tf.零([n],dtype='float64'))
#这里我定义了成本函数
f_张量=tf.mul(tf.mul(tf.reformate(x1,[n]),
tf.重塑(x1[n,1]),
tf.重塑(x1[n,1,1]))
f=tf.约化和(f\u张量)
session=tf.session()
初始化所有变量()
会话运行(init)
#在测试阵列上运行
xtest=np.one(n)
session.run(x1.assign(xtest))
res=session.run([f,tf.gradients(f,x1)[0]]))
断言res[0]==1000
对于在res[1]中的g:
断言g==100
第二个断言将失败,因为梯度的每个条目将是300而不是100,因为它应该是100。原因是,当席、XJ、XK都指相同的向量时,它们具有象征性的区别:用相同的变量替换所有x将导致X ^ 3的导数,这是3×x ^ 2,因此第二个MWE的结果是:< /P>
另外,为了清晰起见,我还明确指定了x1,实现预期结果的一种方法是使用op生成变量的有效副本,而不影响梯度:
import numpy as np
import tensorflow as tf
# First define the variable.
n = 10 # size of x
x1 = tf.Variable(tf.zeros([n], dtype=tf.float64))
x2 = tf.stop_gradient(x1)
# Now define the cost function
f_tensor = tf.mul(tf.mul(tf.reshape(x1, [n]),
tf.reshape(x2, [n,1])),
tf.reshape(x2, [n,1,1]))
f = tf.reduce_sum(f_tensor)
session = tf.Session()
init = tf.initialize_all_variables()
session.run(init)
# Run on test array
xtest = np.ones(n)
res = session.run([f, tf.gradients(f, x1)[0]],
feed_dict={x1 : xtest})
assert res[0] == 1000
for g in res[1]:
assert g == 100
我无法在上面发表评论(声誉不够),但请注意,分析梯度应该是
$$
\frac{\partial f}{\partial x_k}=\sum{ij}J{ijk}x_i x_J+\sum{ij}J{ikj}x_i x_J+\sum{ij}J{kij}x_J。
$$如果总是为
x1
和x2
提供相同的向量,是否需要定义两个单独的张量?例如,如果您删除了x2
的定义,并将对x2
的所有引用替换为x1
,我认为您的程序将具有相同的语义。如果您尝试,您将看到第二个断言失败。这是因为在这种情况下,导数是不正确的,原因是tf会认为它取x^3的导数。这个代码似乎对我有用:。也许这里的代码与您正在运行的实际代码之间存在一些差异?mwe可以工作,我的观点是,我希望避免执行feed_dict={x1:xtest,x2:xtest},并用si替换它