Grad-CAM 迁移学习错误:尝试将具有不支持类型(<类 “nonetype”>)的值(无)转换为张量

发布于 2025-01-18 00:58:12 字数 6409 浏览 1 评论 0原文

在使用转移学习技术训练机器学习模型之后,我正在尝试运行Grad-CAM,以对某些图像进行分类。 我使用的模型是Mobilenetv2。我在其中添加了一个分类器部分。我同时完成了模型培训和微调零件,并且该模型本身效果很好。

但是,当我尝试运行Grad-CAM以生成热图时,它给了我一个错误消息,如下所示:

valueError:尝试使用不支持的类型(&lt;类'nontype'&gt;类型转换值(无); )张量。

这是模型摘要:

Model: "model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 200, 320, 3)]     0         
                                                                 
 mobilenetv2_1.00_224 (Funct  (None, 7, 10, 1280)      2257984   
 ional)                                                          
                                                                 
 flatten (Flatten)           (None, 89600)             0         
                                                                 
 dense (Dense)               (None, 6)                 537606    
                                                                 
=================================================================
Total params: 2,795,590
Trainable params: 537,606
Non-trainable params: 2,257,984
_________________________________________________________________
None

我使用以下代码查看MobilenetV2的层,并在Grad-Cam函数中需要提及最后一个卷积层的名称:

model.get_layer('mobilenetv2_1.00_224').summary()
def make_gradcam_heatmap(img_array, model, base_model_name,last_conv_layer_name):
    # First, we create a model that maps the input image to the activations
    # of the last conv layer as well as the output predictions
    grad_model = tf.keras.models.Model(
        [model.inputs], [model.get_layer(base_model_name).get_layer(last_conv_layer_name).output, model.output]
    )

    # Then, we compute the gradient of the top predicted class for our input image
    # with respect to the activations of the last conv layer
    with tf.GradientTape() as tape:
        last_conv_layer_output, preds = grad_model(img_array)
        class_channel = preds[:, 0]
    #print('preds: ',preds)    
    #print('last conv layer output:\n',last_conv_layer_output)
    #print('class channel:\n',class_channel)
    
    # This is the gradient of the output neuron (top predicted or chosen)
    # with regard to the output feature map of the last conv layer
    grads = tape.gradient(class_channel, last_conv_layer_output)
    #print('grads:\n',grads)

    # This is a vector where each entry is the mean intensity of the gradient
    # over a specific feature map channel
    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))

    # We multiply each channel in the feature map array
    # by "how important this channel is" with regard to the top predicted class
    # then sum all the channels to obtain the heatmap class activation
    last_conv_layer_output = last_conv_layer_output[0]
    heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
    heatmap = tf.squeeze(heatmap)

    # For visualization purpose, we will also normalize the heatmap between 0 & 1
    heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap)
    heatmap = heatmap.numpy()
    heatmap_resized = resize(heatmap,(200, 320))
    return heatmap_resized
model.layers[-1].activation = None


plt.figure(figsize = (6,12),dpi = 450)

for ii in range(6):
    # Generate class activation heatmap
    heatmap = make_gradcam_heatmap(X_test_pp[ii][np.newaxis,:,:], model, "mobilenetv2_1.00_224","Conv_1")
    plt.subplot(6,4,ii+1)
    plt.imshow(X_test_pp[ii])
    plt.title('Label: '+class_names[Y_test[ii]]+'| Pred: '+class_names[np.argmax(Y_pred,axis=1)[ii]],fontdict = {'fontsize' : 4})
    plt.imshow(heatmap, alpha = 0.35, cmap = "inferno")
    #plt.colorbar()
    plt.axis("off")
plt.show()

详细信息错误消息:

ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_5016/4168142392.py in <module>
      8 for ii in range(6):
      9     # Generate class activation heatmap
---> 10     heatmap = make_gradcam_heatmap(X_test_pp[ii][np.newaxis,:,:], model, "mobilenetv2_1.00_224","Conv_1")
     11     plt.subplot(6,4,ii+1)
     12     plt.imshow(X_test_pp[ii])

~\AppData\Local\Temp/ipykernel_5016/3660858513.py in make_gradcam_heatmap(img_array, model, base_model_name, last_conv_layer_name)
     22     # This is a vector where each entry is the mean intensity of the gradient
     23     # over a specific feature map channel
---> 24     pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
     25 
     26     # We multiply each channel in the feature map array

C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\util\traceback_utils.py in error_handler(*args, **kwargs)
    151     except Exception as e:
    152       filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153       raise e.with_traceback(filtered_tb) from None
    154     finally:
    155       del filtered_tb

C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\framework\constant_op.py in convert_to_eager_tensor(value, ctx, dtype)
    100       dtype = dtypes.as_dtype(dtype).as_datatype_enum
    101   ctx.ensure_initialized()
--> 102   return ops.EagerTensor(value, ctx.device_name, dtype)
    103 
    104 

ValueError: Attempt to convert a value (None) with an unsupported type (<class 'NoneType'>) to a Tensor.

<Figure size 2700x5400 with 0 Axes>

这是我的问题, 首先,我给Grad-CAM的最后一个卷积层的名称正确吗?如果没有,那应该是什么? 此错误消息的原因是什么,因为当我自己定义整个模型结构时,它正在工作?

到目前为止,我已经做过的事情:

我尝试调试代码,以查看此错误消息背后的原因是什么。 我意识到以下行返回“无”作为梯度,但是我不确定为什么呢?以及我如何解决这个问题。

grads = tape.gradient(class_channel,last_conv_layer_output)

我还尝试了最后一个卷积层的不同层名称,但它也不起作用。

我稍微读到了一些有关此问题的信息,并注意到有些人提到所有库中都需要直接从Tensorflow导入。这是我进口的内容:

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.model_selection import train_test_split
import tensorflow_datasets as tfds 
import glob
from skimage import transform
import cv2
import seaborn as sns
from skimage.transform import resize
from sklearn.metrics import confusion_matrix
from tensorflow.keras import backend as K

谢谢大家。

i am trying to run Grad-CAM after training a machine learning model using the Transfer learning technique to classify some images.
the model i am using is MobilenetV2. and I am adding a classifier section to it. i have done both the model training and fine-tuning parts and the model itself works quite well.

however, when I try to run the Grad-CAM to generate the heatmaps it gives me an error message as follows:

ValueError: Attempt to convert a value (None) with an unsupported type (<class 'NoneType'>) to a Tensor.

Here is the model summary:

Model: "model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 200, 320, 3)]     0         
                                                                 
 mobilenetv2_1.00_224 (Funct  (None, 7, 10, 1280)      2257984   
 ional)                                                          
                                                                 
 flatten (Flatten)           (None, 89600)             0         
                                                                 
 dense (Dense)               (None, 6)                 537606    
                                                                 
=================================================================
Total params: 2,795,590
Trainable params: 537,606
Non-trainable params: 2,257,984
_________________________________________________________________
None

i am using the following code to see the layer of MobileNetV2 and to get the name of the last convolutional layer that i need to mention in my Grad-CAM function:

model.get_layer('mobilenetv2_1.00_224').summary()
def make_gradcam_heatmap(img_array, model, base_model_name,last_conv_layer_name):
    # First, we create a model that maps the input image to the activations
    # of the last conv layer as well as the output predictions
    grad_model = tf.keras.models.Model(
        [model.inputs], [model.get_layer(base_model_name).get_layer(last_conv_layer_name).output, model.output]
    )

    # Then, we compute the gradient of the top predicted class for our input image
    # with respect to the activations of the last conv layer
    with tf.GradientTape() as tape:
        last_conv_layer_output, preds = grad_model(img_array)
        class_channel = preds[:, 0]
    #print('preds: ',preds)    
    #print('last conv layer output:\n',last_conv_layer_output)
    #print('class channel:\n',class_channel)
    
    # This is the gradient of the output neuron (top predicted or chosen)
    # with regard to the output feature map of the last conv layer
    grads = tape.gradient(class_channel, last_conv_layer_output)
    #print('grads:\n',grads)

    # This is a vector where each entry is the mean intensity of the gradient
    # over a specific feature map channel
    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))

    # We multiply each channel in the feature map array
    # by "how important this channel is" with regard to the top predicted class
    # then sum all the channels to obtain the heatmap class activation
    last_conv_layer_output = last_conv_layer_output[0]
    heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
    heatmap = tf.squeeze(heatmap)

    # For visualization purpose, we will also normalize the heatmap between 0 & 1
    heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap)
    heatmap = heatmap.numpy()
    heatmap_resized = resize(heatmap,(200, 320))
    return heatmap_resized
model.layers[-1].activation = None


plt.figure(figsize = (6,12),dpi = 450)

for ii in range(6):
    # Generate class activation heatmap
    heatmap = make_gradcam_heatmap(X_test_pp[ii][np.newaxis,:,:], model, "mobilenetv2_1.00_224","Conv_1")
    plt.subplot(6,4,ii+1)
    plt.imshow(X_test_pp[ii])
    plt.title('Label: '+class_names[Y_test[ii]]+'| Pred: '+class_names[np.argmax(Y_pred,axis=1)[ii]],fontdict = {'fontsize' : 4})
    plt.imshow(heatmap, alpha = 0.35, cmap = "inferno")
    #plt.colorbar()
    plt.axis("off")
plt.show()

details of the error message:

ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_5016/4168142392.py in <module>
      8 for ii in range(6):
      9     # Generate class activation heatmap
---> 10     heatmap = make_gradcam_heatmap(X_test_pp[ii][np.newaxis,:,:], model, "mobilenetv2_1.00_224","Conv_1")
     11     plt.subplot(6,4,ii+1)
     12     plt.imshow(X_test_pp[ii])

~\AppData\Local\Temp/ipykernel_5016/3660858513.py in make_gradcam_heatmap(img_array, model, base_model_name, last_conv_layer_name)
     22     # This is a vector where each entry is the mean intensity of the gradient
     23     # over a specific feature map channel
---> 24     pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
     25 
     26     # We multiply each channel in the feature map array

C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\util\traceback_utils.py in error_handler(*args, **kwargs)
    151     except Exception as e:
    152       filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153       raise e.with_traceback(filtered_tb) from None
    154     finally:
    155       del filtered_tb

C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\framework\constant_op.py in convert_to_eager_tensor(value, ctx, dtype)
    100       dtype = dtypes.as_dtype(dtype).as_datatype_enum
    101   ctx.ensure_initialized()
--> 102   return ops.EagerTensor(value, ctx.device_name, dtype)
    103 
    104 

ValueError: Attempt to convert a value (None) with an unsupported type (<class 'NoneType'>) to a Tensor.

<Figure size 2700x5400 with 0 Axes>

so here is my questions,
first, is the name of the last convolutional layer that i have given to Grad-CAM correct? if Not, what should it be?
what is the reason for this error message, as it is working when i define the whole model structure myself?

what i have done so far:

I have tried debugging the code to see what is the reason behind this error message.
i realized that the following line returns "none" as a gradient, but I am not sure why? and how i can solve this.

grads = tape.gradient(class_channel, last_conv_layer_output)

i have also tried different layer names for the last convolutional layer but it did not work as well.

I read about this issue a bit and noticed that some people mentioned that all the librarie need to be imported from tensorflow not keras directly. here is what i am importing :

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.model_selection import train_test_split
import tensorflow_datasets as tfds 
import glob
from skimage import transform
import cv2
import seaborn as sns
from skimage.transform import resize
from sklearn.metrics import confusion_matrix
from tensorflow.keras import backend as K

thank you all in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

留蓝 2025-01-25 00:58:12

您的整个CNN型号保存在一层中。 mobilenetv2_1.00_224 - CNN模型

model = model.layers[1]

在加载模型时指定输入形状,以避免将模型保存在单层中,例如这样。

input = Input(shape=(640, 640, 3))
model = VGG16(include_top=False,input_tensor=input)

your entire cnn model is saved in one layer. mobilenetv2_1.00_224 - cnn model

model = model.layers[1]

while loading a model specify the input shape to avoid saving your model in a single layer,like this.

input = Input(shape=(640, 640, 3))
model = VGG16(include_top=False,input_tensor=input)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文