tf.GradientTape 为梯度

我正在使用 tf.GradientTape().gradient() 来计算 representer point,它可用于计算给定训练示例对给定测试示例的“影响”。给定测试示例 x_t 和训练示例 x_i 的表示点计算为其特征表示 f_tf_i 的点积乘以权重 {{ 1}}。

注意:这种方法的细节对于理解问题不是必需的,因为主要问题是让梯度胶带起作用。话虽如此,我已经为感兴趣的任何人提供了以下一些细节的屏幕截图。

计算 alpha_i 需要微分,因为它表示如下:

tf.GradientTape 为梯度

在上面的等式中,L 是标准损失函数(多类分类的分类交叉熵),phi 是 pre-softmax 激活输出(所以它的长度是类的数量)。此外,alpha_i 可以进一步分解为 alpha_i,它是针对特定类 alpha_ij 计算的。因此,我们只得到测试样例的预测类别(最终预测最高的类别)对应的pre-softmax输出j

我使用 MNIST 创建了一个简单的设置并实现了以下内容:

phi_j

现在假设模型已经过训练,我想计算给定训练示例对给定测试示例预测的影响,可能是为了模型理解/调试目的。

def simple_mnist_cnn(input_shape = (28,28,1)):
  input = Input(shape=input_shape)
  x = layers.Conv2D(32,kernel_size=(3,3),activation="relu")(input)
  x = layers.MaxPooling2D(pool_size=(2,2))(x)
  x = layers.Conv2D(64,activation="relu")(x)
  x = layers.MaxPooling2D(pool_size=(2,2))(x)
  x = layers.flatten()(x) # feature representation 
  output = layers.Dense(num_classes,activation=None)(x) # presoftmax activation output 
  activation = layers.activation(activation='softmax')(output) # final output with activation 
  model = tf.keras.Model(input,[x,output,activation],name="mnist_model")
  return model

上面的代码给出了以下错误,因为 alpha_ij 是 None:with tf.GradientTape() as t1: f_t,_,pred_t = model(x_t) # get features for misclassified example f_i,presoftmax_i,pred_i = model(x_i) # compute dot product of feature representations for x_t and x_i dotps = tf.reduce_sum( tf.multiply(f_t,f_i)) # get presoftmax output corresponding to highest predicted class of x_t phi_ij = presoftmax_i[:,np.argmax(pred_t)] # y_i is actual label for x_i cl_loss_i = tf.keras.losses.categorical_crossentropy(pred_i,y_i) alpha_ij = t1.gradient(cl_loss_i,phi_ij) # note: alpha_ij returns None currently k_ij = tf.reduce_sum(tf.multiply(alpha_i,dotps)) 。但是,如果我更改 ValueError: Attempt to convert a value (None) with an unsupported type (<class 'NoneType'>) to a Tensor. -> t1.gradient(cl_loss_i,phi_ij),它不再返回 None。不知道为什么会这样?在切片张量上计算梯度有问题吗? “观察”太多变量是否有问题?我很少使用渐变胶带,所以我不确定修复是什么,但希望得到帮助。

对于任何感兴趣的人,这里有更多详细信息:

tf.GradientTape 为梯度

haoyun1126 回答:tf.GradientTape 为梯度

我从未见过你watch任何张量。请注意,磁带默认仅跟踪 tf.Variable。这是您的代码中缺少的吗?否则我看不到 t1.gradient(cl_loss_i,presoftmax_i) 是如何工作的。

不管怎样,我认为解决它的最简单方法是做

all_gradients = t1.gradient(cl_loss_i,presoftmax_i)
desired_gradients = all_gradients[[:,np.argmax(pred_t)]]

所以只需在渐变之后进行索引即可。请注意,这可能很浪费(如果有很多类),因为您计算的梯度比您需要的要多。

为什么(我相信)您的版本不起作用的解释最容易在绘图中显示,但让我尝试解释:想象一下有向图中的计算。我们有

presoftmax_i -> pred_i -> cl_loss_i

将损失反向传播到 presoftmax 很容易。但是后来你又设立了一个分支,

presoftmax_i -> presoftmax_ij

现在,当您尝试计算关于 presoftmax_ij 的损失梯度时,实际上没有反向传播路径(我们只能向后跟随箭头)。另一种思考方式:在计算损失之后计算 presoftmax_ij 。那么损失怎么可能取决于它?

本文链接:https://www.f2er.com/331.html

大家都在问