1

假设我有两个矩阵 tf_t(形状:5x3)和 tf_b(形状:3x3)。y_tf = tf.matmul(tf_t, tf_b) 然后我使用 tf.gradient api 计算了 dy/dt

import tensorflow as tf

mat = [[0.8363, 0.4719, 0.9783],
        [0.3379, 0.6548, 0.3835],
        [0.7846, 0.9173, 0.2393],
        [0.5418, 0.3875, 0.4276],
        [0.0948, 0.2637, 0.8039]]

another_mat = [[ 0.43842274 ,-0.53439844, -0.07710262],
               [ 1.5658046,  -0.1012345 , -0.2744976 ],
               [ 1.4204658 ,  1.2609464,  -0.43640924]]

tf_t = tf.Variable(tf.convert_to_tensor(mat))
tf_b = tf.Variable(tf.convert_to_tensor(another_mat))

with tf.GradientTape() as tape:
  tape.watch(tf_t)
  y_tf = tf.matmul(tf_t, tf_b)
  y_t0 = y_tf[0,0]

# dy = 2x * dx
dy_dx = tape.gradient(y_tf, tf_t)
print(dy_dx)

我得到以下矩阵作为 dy/dx

tf.Tensor(
[[-0.17307831  1.1900724   2.245003  ]
 [-0.17307831  1.1900724   2.245003  ]
 [-0.17307831  1.1900724   2.245003  ]
 [-0.17307831  1.1900724   2.245003  ]
 [-0.17307831  1.1900724   2.245003  ]], shape=(5, 3), dtype=float32)

上面的矩阵看起来不正确。因为对于元素 y_tf[0,0]

注意:y_tf[0,0] = tf_t[0,0]*tf_b[0,0] + tf_t[0,1]*tf_b[1,0] + tf_t[0,2]*tf_b[2,0]

如果我表演

tape.gradient(y_t0, tf_t)

我得到这样的矩阵

tf.Tensor(
[[0.43842274 1.5658046  1.4204658 ]
 [0.         0.         0.        ]
 [0.         0.         0.        ]
 [0.         0.         0.        ]
 [0.         0.         0.        ]], shape=(5, 3), dtype=float32)

上面的第一行是矩阵的第一列,tf_b考虑到矩阵乘法的工作原理,如果我是,总而言之,这些数字将是3.424693但是,我得到的结果是dy_dx它的第一个元素dy_dx[0,0]-0.17307831它是总和第一排tf_b ( sum(tf_b[0,:])!!

那么任何人都可以解释如何将梯度tf_y[0,0] wrt tf_x减少到-0.17307831 而不是3.424693

这个问题可能看起来与类似,但我正在寻找的答案并没有用清晰的图片来解决。

4

1 回答 1

1

这里要理解的关键概念是tf.gradients计算输出之和相对于输入的梯度。即dy_dx表示所有元素的总和y_tf随着每个元素的tf_t变化而变化的比例。

因此,如果您取tf_t[0, 0],则该值用于计算和y_tf[0, 0],在每种情况下,系数和。因此,如果我增加1,则 的总和将增加,即 的值。继续相同的推理,每个值实际上都乘以 中的所有值,因此是 的行总和的重复。y_tf[0, 1]y_tf[0, 2]tf_b[0, 0]tf_b[0, 1]tf_b[0, 2]tf_t[0, 0]y_tftf_b[0, 0] + tf_b[0, 1] + tf_b[0, 2]dy_dx[0, 0]tf_t[i, j]tf_b[j, :]dy_dxtf_b

当您计算y_t0相对于的梯度时tf_t, 的变化tf_t[0, 0]将使结果的总和改变 一个因子tf_b[0, 0],因此这就是这种情况下的梯度值。

于 2020-11-16T12:32:51.277 回答