Python Tensorflow仅针对变量的某些元素最小化

Python Tensorflow仅针对变量的某些元素最小化,python,tensorflow,machine-learning,Python,Tensorflow,Machine Learning,是否可以通过仅改变变量的某些元素来最小化损失函数?换句话说,如果我有一个长度为2的变量X,如何通过更改X[0]并保持X[1]恒定来最小化损失函数 希望我尝试的这段代码能够描述我的问题: import tensorflow as tf import tensorflow.contrib.opt as opt X = tf.Variable([1.0, 2.0]) X0 = tf.Variable([3.0]) Y = tf.constant([2.0, -3.0]) scatter = tf

是否可以通过仅改变变量的某些元素来最小化损失函数?换句话说,如果我有一个长度为2的变量
X
,如何通过更改
X[0]
并保持
X[1]
恒定来最小化损失函数

希望我尝试的这段代码能够描述我的问题:

import tensorflow as tf
import tensorflow.contrib.opt as opt

X = tf.Variable([1.0, 2.0])
X0 = tf.Variable([3.0])

Y = tf.constant([2.0, -3.0])

scatter = tf.scatter_update(X, [0], X0)

with tf.control_dependencies([scatter]):
    loss = tf.reduce_sum(tf.squared_difference(X, Y))

opt = opt.ScipyOptimizerInterface(loss, [X0])

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    opt.minimize(sess)

    print("X: {}".format(X.eval()))
    print("X0: {}".format(X0.eval()))
哪些产出:

INFO:tensorflow:Optimization terminated with:
  Message: b'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
  Objective function value: 26.000000
  Number of iterations: 0
  Number of functions evaluations: 1
X: [3. 2.]
X0: [3.]
INFO:tensorflow:优化终止于:

消息:b'CONVERGENCE:NORM_OF_PROJECTED_GRADIENT_这应该很容易通过使用
minimize
函数的
var_列表
参数来实现

trainable_var = X[0]
train_op = tf.train.GradientDescentOptimizer(learning_rate=1e-3).minimize(loss, var_list=[trainable_var])
您应该注意,按照惯例,所有可培训变量都会添加到tensorflow默认集合
GraphKeys.trainable_variables
,因此您可以使用以下方法获得所有可培训变量的列表:

all_trainable_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES)
这只是一个变量列表,您可以根据需要对其进行操作,并将其用作
var\u list
参数

与您的问题相切的是,如果您想进一步定制优化过程,您还可以使用
grads=tf手动计算梯度。梯度(损失,变量列表)
根据您的需要操纵梯度,然后调用
tf.train.GradientDescentOptimizer(…)。应用梯度(grads和vars作为元组列表)
。在引擎盖下,minimize只为您执行这两个步骤


还请注意,您可以完全自由地为不同的变量集合创建不同的优化器。您可以为某些变量创建一个学习率为1e-4的SGD优化器,为另一组变量创建另一个学习率为1e-2的Adam优化器。这并不是说有任何特定的用例,我只是指出fle您现在拥有的灵活性。

我不确定是否可以使用SciPy optimizer接口,但使用一个常规子类,您可以先调用,然后屏蔽渐变,然后调用, 而不是打电话(正如文档所说,基本上是打以前的电话)

输出:

Step 0: X = [ 2.79999995  2.        ]
Step 1: X = [ 2.63999987  2.        ]
Step 2: X = [ 2.51199985  2.        ]
Step 3: X = [ 2.40959978  2.        ]
Step 4: X = [ 2.32767987  2.        ]
Step 5: X = [ 2.26214385  2.        ]
Step 6: X = [ 2.20971513  2.        ]
Step 7: X = [ 2.16777205  2.        ]
Step 8: X = [ 2.13421774  2.        ]
Step 9: X = [ 2.10737419  2.        ]
Final X = [ 2.10737419  2.        ]

可以使用此技巧将渐变计算限制为一个索引:

import tensorflow as tf
import tensorflow.contrib.opt as opt

X = tf.Variable([1.0, 2.0])

part_X = tf.scatter_nd([[0]], [X[0]], [2])

X_2 = part_X + tf.stop_gradient(-part_X + X)

Y = tf.constant([2.0, -3.0])

loss = tf.reduce_sum(tf.squared_difference(X_2, Y))

opt = opt.ScipyOptimizerInterface(loss, [X])

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    opt.minimize(sess)

    print("X: {}".format(X.eval()))

part_X
成为要在与X形状相同的一个热向量中更改的值。
part_X+tf.stop_渐变(-part_X+X)
在向前传球中与X相同,因为
part_X-part_X
为0。但是在向后传球中,tf.stop_gradient
阻止所有不必要的梯度计算。

下面第二个链接中Oren的答案调用函数(在第一个链接中定义)这需要参数的布尔热矩阵和参数的张量进行优化,它使用stop_梯度,就像我开发的神经网络的魅力一样


这里解决了?是的,我看到了,但不幸的是,对于我想要做的事情,没有一个解决方案(据我所知)。
var\u list
参数需要一个对象列表,但是
X[0]
是对
X
应用切片操作后产生的张量。您无法对此进行优化,因为常规张量无法更新(而且在任何情况下都不会更新原始变量,因为它是不同的张量).我承认我没有尝试过使用slice,但我希望它仍然可以工作。如果它不尝试
tf.identity(X[0])
作为为其创建单独变量名的一种方法。我可能仍然错了,但我已经在tensorflow中编写了一个优化器,这样做的界面非常简单。优化器只需获得一个变量列表及其梯度,以生成更新。如果分配
可训练变量=X[0]
不起作用,我会有点惊讶,如果
tf.identity
不起作用,我会更惊讶。我希望它能起作用,因为你可以在切片上取梯度。好吧,试试看,但我担心切片和
tf.identity
都不会创建变量,它们是产生张量作为输出的运算,所以我会执行ally真的很惊讶它是否有效。如果所有这些都失败了,另一种选择是从2个变量开始,并将它们连接起来进行计算。是的,连接是另一种很好的选择,尽管我不知道这对于OP来说是否足够,或者他们需要能够动态选择更新的参数…这看起来不错-谢谢!IIUC,不幸的是,它需要计算
X
中所有元素的梯度(在我的实际问题中,我的
X
很大,我只想指出其中的几个元素,我的缺点是在问题中没有具体说明)使用SciPy优化器是不可能的,但这是迄今为止我所拥有的最好的,所以我会在悬赏结束之前接受它,除非找到更好的解决方案。@Jeff是的,这是正确的,至少需要计算所有的梯度(我对SciPy优化器了解不多,所以我不能肯定这一点)。如另一个答案的评论中所述,如果您需要更新的参数集是固定的(例如,始终是数组的第一个元素),而不是动态的(例如,根据某个值决定更新哪些权重,或在训练期间更改),你可以只将你知道需要更新的元素定义为变量,并连接其余的权重来组成网络,我不知道这是否对你有用。
import tensorflow as tf
import tensorflow.contrib.opt as opt

X = tf.Variable([1.0, 2.0])

part_X = tf.scatter_nd([[0]], [X[0]], [2])

X_2 = part_X + tf.stop_gradient(-part_X + X)

Y = tf.constant([2.0, -3.0])

loss = tf.reduce_sum(tf.squared_difference(X_2, Y))

opt = opt.ScipyOptimizerInterface(loss, [X])

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    opt.minimize(sess)

    print("X: {}".format(X.eval()))