Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Tensorflow:在同一操作中共享两个不同变量的值_Python_Tensorflow - Fatal编程技术网

Python Tensorflow:在同一操作中共享两个不同变量的值

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

我最近一直在试验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作为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%
(该mwe的结果类似)

因此,在GPU上执行计算时,分配是最昂贵的操作。显然,增加
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替换它