如何获取输出 w.r.t 神经网络参数的"数学"梯度并计算两个此类梯度之间的余弦



i具有神经网络out = f(s),其中s是带有Shape [None, dim_s]的输入的一批输入,而OUT是Scaleer,f只是MLP。使用tf.gradient(out, tf.trainable_variables()),我可以获得out W.R.T的梯度f的神经网络参数,这是梯度的列表。

现在,我有两批ss1s2,然后我们可以获得两个不同的渐变G1G2

例如:

import tensorflow as tf
import numpy as np
batch_1=np.random.normal(0,1, [2, 3])
batch_2=np.random.normal(0,1, [2, 3])
x = tf.placeholder(tf.float32, shape=(None, 3))
out = tf.layers.dense(x, 2, tf.tanh,
                              kernel_initializer=tf.random_normal_initializer(
                                  stddev=np.sqrt(1 / 100)))
predictions = tf.layers.dense(out, 1, tf.tanh,
                              kernel_initializer=tf.random_normal_initializer(
                                  stddev=np.sqrt(1 / 100)))
opt = tf.train.GradientDescentOptimizer(learning_rate=0.01)
gradient_step = opt.compute_gradients(predictions, tf.trainable_variables())
sess=tf.Session()
sess.run(tf.global_variables_initializer())
gradients_1 = sess.run(gradient_step, feed_dict={x: batch_1})
gradients_2 = sess.run(gradient_step, feed_dict={x: batch_2})

如果可以在G1G2之间计算余弦?我需要首先将两个梯度弄平吗?G1G2是否是数学的通常梯度?

re natematical:据我所知,"数学"的含义,tensorflow中的梯度是"数学"。例如,如果您的ff(x) = x^3,则在x=5上运行它,并获取它的tf.gradients,您将获得75 = 3*5^2

re cesine:是的,您可以做到这一点,但是需要更深入地了解TensorFlow梯度计算。要计算梯度,您需要记住前向通行证的值。在上面的示例中,要计算75,您需要记住5。通常,这可能是f中所有操作计算的所有张量。默认情况下,TensorFlow仅在计算梯度之前记住这些值。然后,将值丢弃。

如果您想使用两组梯度,最简单的方法是两次实例化模型。这通常称为有两个"塔"。这些塔将共享变量,它们的结构将是相同的,但是每个塔将具有自己的操作集(Tensorflow图中的节点)。然后,将s1作为输入输入第一个塔,将s2作为输入到第二座塔中(在同一会话中。run()呼叫)。

如果您有数百万的操作和实例化两个塔非常昂贵,则可以创建一个张量的功能(此实验性API)。

另一个可能更容易的选择是使用最近发布的急切执行,在该执行中,立即执行操作(没有图形,没有session.run()),并且您可以轻松控制使用渐变图像的梯度计算。您可以在此处找到其用法的示例。急切的执行在目前处于α前状态,仅在TF-of-nightly构建中可用。请参阅此处的"夜间建造"。

响应评论3:据我所知,您的示例清楚地表明梯度是在批处理上求和的。密集层中的变量具有形状3x11x1

print tf.trainable_variables()
    [<tf.Variable 'dense/kernel:0' shape=(3, 1) dtype=float32_ref>,
     <tf.Variable 'dense/bias:0' shape=(1,) dtype=float32_ref>]

第一个梯度(对于3x1变量)是:

print gradients_1[0][0]
    array([[-0.098351  ],
           [-0.6422075 ],
           [ 0.09750339]], dtype=float32)

因此,即使batch_1对于每个标量变量具有2个标量,每个标量变量都有一个标量。

我已经写了如何使用"塔"来与来自不同输入的两个渐变一起工作。这是基于您的代码段的示例。我认为"余弦"是指"余弦相似性"

import tensorflow as tf
import numpy as np
x1 = tf.placeholder(tf.float32, shape=(None, 3))
x2 = tf.placeholder(tf.float32, shape=(None, 3))
predictions1 = tf.layers.dense(x1, 1, tf.tanh,
                               kernel_initializer=tf.random_normal_initializer(
                                   stddev=np.sqrt(1 / 100)),
                               reuse=None)
predictions2 = tf.layers.dense(x2, 1, tf.tanh,
                               kernel_initializer=tf.random_normal_initializer(
                                   stddev=np.sqrt(1 / 100)),
                               reuse=True)
weights = tf.trainable_variables()[0]   # the 3x1 weight variable
g1 = tf.reshape(tf.gradients(predictions1, weights), [-1])   # 3x1 gradient tensor
g2 = tf.reshape(tf.gradients(predictions2, weights), [-1])   # 3x1 gradient tensor
cos_similarity = 1 - tf.losses.cosine_distance(tf.nn.l2_normalize(g1, 0),
                                               tf.nn.l2_normalize(g2, 0),
                                               dim=0)
sess=tf.Session()
sess.run(tf.global_variables_initializer())
print sess.run([g1, g2, cos_similarity], feed_dict={
    x1: [[1,2,3], [2,4,6]],
    x2: [[1,2,3], [2,4,7]]
    })
# prints
# [array([ 3.,  6.,  9. ], dtype=float32),
#  array([ 3.,  6.,  10.], dtype=float32),
#  0.99876773]