Градиенты отсутствуют при попытке реализовать GradCam

#python #tensorflow #machine-learning #keras #deep-learning

Вопрос:

Я пытаюсь реализовать GradCam, как в этом уроке Keras GradCam.

Я сделал уменьшенную версию этого ниже. Что бы я ни делал, мои градиенты таковы None .

 import tensorflow as tf
from tensorflow import keras as K
import numpy as np

inputs = tf.keras.Input(shape=(224, 224, 12))
x = K.applications.MobileNetV2(input_shape=(224, 224, 12),
                               include_top=False,
                               weights=None)(inputs)
x = K.layers.GlobalAveragePooling2D()(x)
x = K.layers.Dropout(0.25)(x)
x = K.layers.Dense(16, activation='relu')(x)
x = K.layers.Dropout(0.25)(x)
x = K.layers.Dense(1, activation='sigmoid')(x)
model = tf.keras.Model(inputs, x)

img_array = np.random.rand(1, 224, 224, 12).astype(np.float32)

grad_model = tf.keras.models.Model(
    [model.inputs], [model.layers[0].output, model.output]
)

image = np.random.rand(1, 224, 224, 12).astype(np.float32)

with tf.GradientTape() as tape:
    (convOutputs, predictions) = grad_model(image)

    loss = predictions[:, tf.argmax(predictions[0])]

grads = tape.gradient(loss, convOutputs)

print(grads)
 
 None
 

Ответ №1:

Причина получения None значения заключается в том, что вы вычисляете градиент в слое. input Вот одно упрощенное решение вышеперечисленных случаев:

 inputs = tf.keras.Input(shape=(224, 224, 12))
x = K.applications.MobileNetV2(input_tensor=inputs,
                               include_top=False,
                               weights=None)
x = K.layers.GlobalAveragePooling2D()(x.output)
x = K.layers.Dropout(0.25)(x)
x = K.layers.Dense(16, activation='relu')(x)
x = K.layers.Dropout(0.25)(x)
x = K.layers.Dense(1, activation='sigmoid')(x)
model = tf.keras.Model(inputs, x)

img_array = np.random.rand(1, 224, 224, 12).astype(np.float32)

grad_model = tf.keras.models.Model(
    [model.inputs], [model.layers[1].output, model.output]
)

model.layers[0].output, model.layers[1].output
(<KerasTensor: shape=(None, 224, 224, 12) dtype=float32 (created by layer 'input_63')>,
 <KerasTensor: shape=(None, 112, 112, 32) dtype=float32 (created by layer 'Conv1')>)
 

Вот, мы используем layer[1] . Теперь можно получить градиенты входных данных без этого.

 image = np.random.rand(1, 224, 224, 12).astype(np.float32) 

with tf.GradientTape() as tape:
    (convOutputs, predictions) = grad_model(tf.cast(image, tf.float32))
    loss = predictions[:, tf.argmax(predictions[0])]

grads = tape.gradient(loss, convOutputs)
print(grads) 

tf.Tensor(
[[[[ 0.0000000e 00 -1.4619777e-16 -5.2771450e-17 ... -0.0000000e 00
     0.0000000e 00  0.0000000e 00]
   [-7.5641491e-17  0.0000000e 00 -0.0000000e 00 ... -0.0000000e 00
    -1.1224229e-16  0.0000000e 00]
   [-5.8784695e-17  1.0889748e-18  1.9431665e-16 ...  0.0000000e 00
     0.0000000e 00  0.0000000e 00]
   ...