1

我有一个在 keras 中构建的 CNN 模型,它在最后一层使用了 SVM。我通过将输入输入到 CNN 模型中,提取相关特征,然后将这些特征放入我的 SVM 以获得输出预测,从而得到这个 SVM 的预测。这整个过程我在下面的代码中命名为 predict_DNR_tensor。这工作正常,我能够得到正确的预测。我现在正试图从我的 SVM wrt 到原始输入中获​​得这个预测的平方铰链损失的梯度,请参阅代码。但是,当在这里使用渐变胶带时,它似乎不起作用,该函数只返回无。当我将它与仅 CNN 模型(没有 SVM)的输出预测一起使用时,它很好并且给了我一个梯度。为什么?

import tensorflow as tf
import tensorflow.keras.losses as losses


x = np.expand_dims(X_train[0,:,:,:],axis=0)
x = tf.convert_to_tensor(x)

with tf.GradientTape() as tape:
  tape.watch(x)

  ##
  y_pred = predict_DNR_tensor(x)/2 # dividing by 2 to normalise back into [0,1 range]
  y_pred = tf.convert_to_tensor(y_pred, dtype="float32")
  ##

  y_pred2 = CNN_model(x)

  y_true = np.expand_dims(y_train[0,:],axis=0)
  loss = losses.squared_hinge(y_true,y_pred)
  loss2 = losses.squared_hinge(y_true,y_pred2)

gradient = tape.gradient(loss,x)

使用的变量如下:

y_true = array([[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.]], dtype=float32)  

y_pred = <tf.Tensor: id=84063, shape=(1, 10), dtype=float32, numpy=
array([[-0.51142603, -0.51385206, -0.5131374 , -0.52496594, -0.51574653,
         0.54295117, -0.5148362 , -0.51094234, -0.52781606, -0.53384954]],
      dtype=float32)>  

y_pred2 = <tf.Tensor: id=84105, shape=(1, 10), dtype=float32, numpy=
array([[9.1292924e-05, 6.4014189e-06, 1.2363887e-05, 2.6787011e-02,
        2.7567458e-07, 9.7225791e-01, 2.2164610e-04, 1.3467512e-06,
        5.6831568e-04, 5.3546366e-05]], dtype=float32)>


loss = <tf.Tensor: id=84125, shape=(1,), dtype=float32, numpy=array([0.22959474], dtype=float32)>

loss2 = <tf.Tensor: id=84384, shape=(1,), dtype=float32, numpy=array([0.9056972], dtype=float32)>

当我使用损失计算梯度时,我返回无。当我使用 loss2 计算梯度时,我得到了预期的值数组。loss 和 loss2 之间的唯一区别是 y_pred 和 y_pred2。y_pred2 据我了解,它只是 keras 中构建的 cnn 模型的输出预测。(注意:我的损失对于这个函数并不正确,我只是想看看如果我使用这个模型的输出它是否会抛出一个梯度。)

y_pred 然而,我实际上感兴趣的是调用用作 cnn 模型最后一层的 SVM 的输出。IE。它为此输入图像获取 cnn 模型的特征,然后将这些特征放入单独的 svm 模型中以获得这些输出。

y_pred 和 y_pred2 在它们的数据类型和形状上看起来很相似,不管有不同的值。为什么 y_pred 然后无法得到渐变?有没有办法解决它?

4

0 回答 0