gpt4 book ai didi

python - 只能使用 TensorFlow 中处理梯度的代码示例来实现类似优化器的梯度下降吗?

转载 作者:太空狗 更新时间:2023-10-29 21:45:21 27 4
gpt4 key购买 nike

我正在查看 TensorFlow 具有的用于处理梯度的示例代码:

# Create an optimizer.
opt = GradientDescentOptimizer(learning_rate=0.1)

# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss, <list of variables>)

# grads_and_vars is a list of tuples (gradient, variable). Do whatever you
# need to the 'gradient' part, for example cap them, etc.
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]

# Ask the optimizer to apply the capped gradients.
opt.apply_gradients(capped_grads_and_vars)

但是,我注意到 apply_gradients 函数派生自 GradientDescentOptimizer。这是否意味着使用上面的示例代码,只能实现梯度下降规则(注意我们可以更改 opt = GradientDescentOptimizerAdam 或任何其他优化器)?特别是,apply_gradients 做了什么?我明确检查了 tf github page 中的代码但它是一堆与数学表达式无关的 python,因此很难说出它在做什么以及它如何从优化器变为优化器。

例如,如果我想实现我自己的自定义优化器,它可能会使用梯度(或者可能不会,例如直接用一些规则改变权重,也许更符合生物学规律),上面的示例代码不可能吗?


特别是我想实现一个人为限制在紧凑域中的梯度下降版本。特别是我想实现以下等式:

w := (w - mu*grad + eps) mod B

在 tensorflow 中。我意识到以下内容是正确的:

w := w mod B - mu*grad mod B + eps mod B

所以我认为我可以通过以下方式实现它:

def Process_grads(g,mu_noise,stddev_noise,B):
return (g+tf.random_normal(tf.shape(g),mean=mu_noise,stddev=stddev_noise) ) % B

然后就是:

processed_grads_and_vars = [(Process_grads(gv[0]), gv[1]) for gv in grads_and_vars]
# Ask the optimizer to apply the processed gradients.
opt.apply_gradients(processed_grads_and_vars)

但是,我意识到这还不够好,因为我实际上无法访问 w,所以我无法实现:

w mod B

至少不是我尝试过的方式。有没有办法做到这一点?即实际直接更改更新规则?至少是我尝试过的方式?

我知道它是一种骇人听闻的更新规则,但我的观点更多的是改变更新方程式,而不是真正关心该更新规则(所以如果它有点奇怪,请不要挂断它)。


我想出了 super hacky 的解决方案:

def manual_update_GDL(arg,learning_rate,g,mu_noise,stddev_noise):
with tf.variable_scope(arg.mdl_scope_name,reuse=True):
W_var = tf.get_variable(name='W')
eps = tf.random_normal(tf.shape(g),mean=mu_noise,stddev=stddev_noise)
#
W_new = tf.mod( W_var - learning_rate*g + eps , 20)
sess.run( W_var.assign(W_new) )

def manual_GDL(arg,loss,learning_rate,mu_noise,stddev_noise,compact,B):
# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss)
# process gradients
processed_grads_and_vars = [(manual_update_GDL(arg,learning_rate,g,mu_noise,stddev_noise), v) for g,v in grads_and_vars]

不确定它是否有效,但类似的东西通常应该有效。我们的想法是只写下想要使用(在 TensorFlow 中)的学习率方程,然后使用 session 手动更新权重。

不幸的是,这样的解决方案意味着我们必须处理退火(手动衰减学习率,这看起来很烦人)。该解决方案可能还有许多其他问题,请随时指出(如果可以,请给出解决方案)。


对于这个非常简单的问题,我意识到可以只执行正常的优化器更新规则,然后只取权重的模并将它们重新分配给它们的值:

sess.run(fetches=train_step)
if arg.compact:
# apply w := ( w - mu*g + eps ) mod B
W_val = W_var.eval()
W_new = tf.mod(W_var,arg.B).eval()
W_var.assign(W_new).eval()

但在这种情况下,存在这样一个简单的解决方案是巧合(不幸的是,绕过了我的问题的全部要点)。

实际上,这种解决方案大大降低了代码速度。目前是我所拥有的最好的。


作为引用,我看到了这个问题:How to create an optimizer in Tensorflow , 但没有发现它直接回答了我的问题。

最佳答案

您的解决方案会降低代码速度,因为您在创建“train_step”期间使用了 sess.run.eval() 代码。相反,您应该仅使用内部 tensorflow 函数创建 train_step 图(不使用 sess.run.eval())。此后,您只需在循环中评估 train_step。

如果您不想使用任何标准优化器,您可以编写自己的“应用梯度”图表。这是一个可能的解决方案:

learning_rate = tf.Variable(tf.constant(0.1))
mu_noise = 0.
stddev_noise = 0.01

#add all your W variables here when you have more than one:
train_w_vars_list = [W]
grad = tf.gradients(some_loss, train_w_vars_list)

assign_list = []
for g, v in zip(grad, train_w_vars_list):
eps = tf.random_normal(tf.shape(g), mean=mu_noise, stddev=stddev_noise)
assign_list.append(v.assign(tf.mod(v - learning_rate*g + eps, 20)))

#also update the learning rate here if you want to:
assign_list.append(learning_rate.assign(learning_rate - 0.001))

train_step = tf.group(*assign_list)

您还可以使用标准优化器之一来创建 grads_and_vars 列表(然后使用它代替 zip(grad, train_w_vars_list))。

这是一个带有损失的 MNIST 的简单示例:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from tensorflow.examples.tutorials.mnist import input_data

import tensorflow as tf

# Import data
mnist = input_data.read_data_sets('PATH TO MNIST_data', one_hot=True)

# Create the model
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
y = tf.matmul(x, W)


# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, 10])

cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))

learning_rate = tf.Variable(tf.constant(0.1))
mu_noise = 0.
stddev_noise = 0.01

#add all your W variables here when you have more than one:
train_w_vars_list = [W]
grad = tf.gradients(cross_entropy, train_w_vars_list)

assign_list = []
for g, v in zip(grad, train_w_vars_list):
eps = tf.random_normal(tf.shape(g), mean=mu_noise, stddev=stddev_noise)
assign_list.append(v.assign(tf.mod(v - learning_rate*g + eps, 20)))

#also update the learning rate here if you want to:
assign_list.append(learning_rate.assign(learning_rate - 0.001))

train_step = tf.group(*assign_list)


sess = tf.InteractiveSession()
tf.global_variables_initializer().run()


# Train
for _ in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})


# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
y_: mnist.test.labels}))

关于python - 只能使用 TensorFlow 中处理梯度的代码示例来实现类似优化器的梯度下降吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42870727/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com