第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow)

这篇具有很好参考价值的文章主要介绍了第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于WIN10的64位系统演示

一、写在前面

类激活映射(Class Activation Mapping,CAM)和梯度权重类激活映射(Gradient-weighted Class Activation Mapping,Grad-CAM)是两种可视化深度学习模型决策过程的技术。他们都是为了理解模型的决策过程,特别是对于图像分类任务,它们可以生成一种热力图,这种图可以突出显示模型在做出预测时关注的图像区域。

CAM:CAM是一种可视化卷积神经网络(Convolutional Neural Networks, CNN)决策依据的技术。对于图像分类任务,它可以生成一种热力图,突出显示模型在做出预测时关注的图像区域。CAM需要模型在全局平均池化(Global Average Pooling, GAP)层和最终的全连接层(Fully Connected, FC)之间没有其他隐藏层,这是其使用的限制。

Grad-CAM:Grad-CAM是为了克服CAM的限制而提出的一种方法,它使用的是类别得分关于特定层输出的梯度信息。这种方法不仅可以应用于卷积层,还可以应用于任何层的输出。因此,Grad-CAM可以用于多种类型的深度学习模型,包括图像分类、图像生成、强化学习等各种模型。这使得Grad-CAM在可视化模型决策过程方面更加灵活和强大。

这一期主要介绍Grad-CAM,用的模型是Mobilenet_v2,以为够快!!

二、Grad-CAM可视化实战

继续使用胸片的数据集:肺结核病人和健康人的胸片的识别。其中,肺结核病人700张,健康人900张,分别存入单独的文件夹中。

(a)Mobilenet_v2建模

######################################导入包###################################
from tensorflow import keras
import tensorflow as tf
from tensorflow.python.keras.layers import Dense, Flatten, Conv2D, MaxPool2D, Dropout, Activation, Reshape, Softmax, GlobalAveragePooling2D, BatchNormalization
from tensorflow.python.keras.layers.convolutional import Convolution2D, MaxPooling2D
from tensorflow.python.keras import Sequential
from tensorflow.python.keras import Model
from tensorflow.python.keras.optimizers import adam_v2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator, image_dataset_from_directory
from tensorflow.python.keras.layers.preprocessing.image_preprocessing import RandomFlip, RandomRotation, RandomContrast, RandomZoom, RandomTranslation
import os,PIL,pathlib
import warnings
#设置GPU
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")
    
warnings.filterwarnings("ignore")             #忽略警告信息
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

################################导入数据集#####################################
#1.导入数据
data_dir = "./MTB"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:",image_count)

batch_size = 32
img_height = 100
img_width  = 100

train_ds = image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)

val_ds = image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)
print(train_ds)


#2.检查数据
for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break

#3.配置数据
AUTOTUNE = tf.data.AUTOTUNE

def train_preprocessing(image,label):
    return (image/255.0,label)

train_ds = (
    train_ds.cache()
    .shuffle(800)
    .map(train_preprocessing)    
    .prefetch(buffer_size=AUTOTUNE)
)

val_ds = (
    val_ds.cache()
    .map(train_preprocessing) 
    .prefetch(buffer_size=AUTOTUNE)
)

#4. 数据可视化
plt.figure(figsize=(10, 8))  # 图形的宽为10高为5
plt.suptitle("数据展示")

class_names = ["Tuberculosis","Normal"]

for images, labels in train_ds.take(1):
    for i in range(15):
        plt.subplot(4, 5, i + 1)
        plt.xticks([])
        plt.yticks([])
        plt.grid(False)

        # 显示图片
        plt.imshow(images[i])
        # 显示标签
        plt.xlabel(class_names[labels[i]-1])

plt.show()

######################################数据增强函数################################

data_augmentation = Sequential([
  RandomFlip("horizontal_and_vertical"),
  RandomRotation(0.2),
  RandomContrast(1.0),
  RandomZoom(0.5,0.2),
  RandomTranslation(0.3,0.5),
])

def prepare(ds):
    ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y), num_parallel_calls=AUTOTUNE)
    return ds
train_ds = prepare(train_ds)

################################导入mobilenet_v2################################
#获取预训练模型对输入的预处理方法
from tensorflow.python.keras.applications import mobilenet_v2
from tensorflow.python.keras import Input, regularizers
IMG_SIZE = (img_height, img_width, 3)

# 创建输入张量
inputs = Input(shape=IMG_SIZE)
# 定义基础模型,并将 inputs 传入
base_model = mobilenet_v2.MobileNetV2(input_tensor=inputs,
                                      include_top=False, 
                                      weights='imagenet')

#从基础模型中获取输出
x = base_model.output
#全局池化
x = GlobalAveragePooling2D()(x)
#BatchNormalization
x = BatchNormalization()(x)
#Dropout
x = Dropout(0.8)(x)
#Dense
x = Dense(128, kernel_regularizer=regularizers.l2(0.1))(x)  # 全连接层减少到128,添加 L2 正则化
#BatchNormalization
x = BatchNormalization()(x)
#激活函数
x = Activation('relu')(x)
#输出层
outputs = Dense(2, kernel_regularizer=regularizers.l2(0.1))(x)  # 添加 L2 正则化
#BatchNormalization
outputs = BatchNormalization()(outputs)
#激活函数
outputs = Activation('sigmoid')(outputs)
#整体封装
model = Model(inputs, outputs)
#打印模型结构
print(model.summary())

#############################编译模型#########################################
#定义优化器
from tensorflow.python.keras.optimizers import adam_v2, rmsprop_v2
optimizer = adam_v2.Adam()


#编译模型
model.compile(optimizer=optimizer,
                loss='sparse_categorical_crossentropy',
                metrics=['accuracy'])

#训练模型
from tensorflow.python.keras.callbacks import ModelCheckpoint, Callback, EarlyStopping, ReduceLROnPlateau, LearningRateScheduler

NO_EPOCHS = 50
PATIENCE  = 10
VERBOSE   = 1

# 设置动态学习率
annealer = LearningRateScheduler(lambda x: 1e-5 * 0.99 ** (x+NO_EPOCHS))

# 设置早停
earlystopper = EarlyStopping(monitor='loss', patience=PATIENCE, verbose=VERBOSE)

# 
checkpointer = ModelCheckpoint('mtb_jet_best_model_mobilenetv3samll.h5',
                                monitor='val_accuracy',
                                verbose=VERBOSE,
                                save_best_only=True,
                                save_weights_only=True)

train_model  = model.fit(train_ds,
                  epochs=NO_EPOCHS,
                  verbose=1,
                  validation_data=val_ds,
                  callbacks=[earlystopper, checkpointer, annealer])

#保存模型
model.save('mtb_jet_best_model_mobilenet.h5')
print("The trained model has been saved.")

(b)Grad-CAM

import numpy as np
from PIL import Image, ImageOps
from tensorflow.python.keras.preprocessing import image
from tensorflow.python.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.python.keras.models import load_model
import tensorflow as tf
from tensorflow.python.keras import Model
import matplotlib.pyplot as plt

# 你的模型路径
model_path = 'mtb_jet_best_model_mobilenet.h5'

# 你的图像路径
image_path = './MTB/Tuberculosis/Tuberculosis-666.png'

# 加载你的模型
model = load_model(model_path)

def grad_cam(img_path, cls, model, layer_name='block_7_project'):
    # 加载图像并预处理
    img = image.load_img(img_path, target_size=(100, 100))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)

    # 获取预测类别
    preds = model.predict(x)
    pred_class = np.argmax(preds[0])

    # 使用 GradientTape 计算 Grad-CAM
    with tf.GradientTape() as tape:
        last_conv_layer = model.get_layer(layer_name)
        iterate = Model([model.inputs], [model.output, last_conv_layer.output])
        model_out, last_conv_layer = iterate(x)
        class_out = model_out[:, pred_class]

    # 得到的梯度
    grads = tape.gradient(class_out, last_conv_layer)
    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))

    # 我们把梯度在每个特征图上进行平均
    heatmap = tf.reduce_mean(tf.multiply(pooled_grads, last_conv_layer), axis=-1)
    
    # 调整 heatmap 的形状和数值范围
    heatmap = tf.squeeze(heatmap)  # 去掉尺寸为1的维度
    heatmap = np.maximum(heatmap, 0)  # 去掉小于0的值
    max_heat = np.max(heatmap)
    if max_heat == 0:
        max_heat = 1e-10  # 防止除以0
    heatmap /= max_heat  # 归一化到0-1之间
    heatmap = np.uint8(255 * heatmap)  # 转换到0-255之间并转为uint8类型

    # 加载原始图像
    img = Image.open(img_path)

    # 将热力图转换为 PIL 图像并调整其尺寸
    heatmap = Image.fromarray(heatmap)
    heatmap = heatmap.resize((img.height, img.width))

    # 将单通道热力图转换为彩色(RGB)图像
    heatmap = ImageOps.colorize(heatmap, 'blue', 'red')

    # 将彩色热力图转换为带透明度的(RGBA)图像
    heatmap = heatmap.convert('RGBA')
    heatmap_with_alpha = Image.new('RGBA', heatmap.size)
    for x in range(heatmap.width):
        for y in range(heatmap.height):
            r, g, b, a = heatmap.getpixel((x, y))
            heatmap_with_alpha.putpixel((x, y), (r, g, b, int(a * 0.5)))

    # 将原始图像转换为 RGBA 图像
    img = img.convert('RGBA')

    # 叠加图像
    overlay = Image.alpha_composite(img, heatmap_with_alpha)

    # 将叠加后的图像转换为numpy数组
    overlay = np.array(overlay)

    # 使用matplotlib显示图像
    plt.imshow(overlay)
    plt.axis('off')  # 不显示坐标轴
    plt.show()
    
    print(pred_class)

# 绘制热力图
grad_cam(image_path, 0, model)

这个代码需要调整的参数就只有“layer_name”,也就是使用哪一层的信息来可视化。当然,首先我们得先知道每一层的名称:

#查看 Keras 模型每一层的名称
for layer in model.layers:
    print(layer.name)

输出如下:

第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow),《100 Steps to Get ML》—JET学习笔记,深度学习,cnn,tensorflow,图像识别

然后,用哪一层呢?

其实吧,选择哪一层用于Grad-CAM的计算并没有一条明确的规则,这完全取决于你的模型结构以及你的具体需求。

一般来说,Convolutional Neural Networks(CNN,卷积神经网络)的前面几层往往捕捉到的是图像的低级特征,比如边缘、色彩和纹理等,而后面的层则可以捕捉到更为高级的特征,比如物体的部分或者整体。所以,如果你想要看到模型在判断图像时,主要关注了图像中的哪些部分或者物体,你可能需要选择离输出层更近一些的卷积层。

但是这也不是绝对的。在实际应用中,你可能需要尝试不同的层,看看哪一层生成的Grad-CAM热力图最能满足你的需求。

比如我试了试:'block_1_project':

第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow),《100 Steps to Get ML》—JET学习笔记,深度学习,cnn,tensorflow,图像识别

 'block_7_project':

第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow),《100 Steps to Get ML》—JET学习笔记,深度学习,cnn,tensorflow,图像识别

 'block_10_project':

第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow),《100 Steps to Get ML》—JET学习笔记,深度学习,cnn,tensorflow,图像识别

 'block_2_add':

第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow),《100 Steps to Get ML》—JET学习笔记,深度学习,cnn,tensorflow,图像识别

 综上,似乎一切随缘,太抽象了!!!

三、写在最后

略~

四、数据

链接:https://pan.baidu.com/s/15vSVhz1rQBtqNkNp2GQyVw?pwd=x3jf

提取码:x3jf 文章来源地址https://www.toymoban.com/news/detail-637633.html

到了这里,关于第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 大数据深度学习:基于Tensorflow深度学习卷积神经网络CNN算法垃圾分类识别系统

    随着社会的发展和城市化进程的加速,垃圾分类已经成为了环境保护和可持续发展的重要课题。然而,传统的垃圾分类方法通常依赖于人工识别,效率低下且易出错。因此,本项目旨在利用大数据和深度学习技术,构建一个基于 TensorFlow 深度学习的神经网络 CNN(Convolutional

    2024年04月14日
    浏览(108)
  • 基于深度学习的车牌+车辆识别(YOLOv5和CNN)

    yolov5车牌识别+车辆识别 行人识别yolov5和v7对比 一、综述 二、车牌检测 本篇文章是面向的是小白,想要学习深度学习上的应用,本文中目前应用了YOLO v5和CNN来对车牌进行处理,最终形成一个完整的车牌信息记录,如果我写的有什么不对或者需要改进的地方࿰

    2024年02月04日
    浏览(49)
  • 车牌识别系统Python,基于深度学习CNN卷积神经网络算法

    车牌识别系统,基于Python实现,通过TensorFlow搭建CNN卷积神经网络模型,对车牌数据集图片进行训练最后得到模型,并基于Django框架搭建网页端平台,实现用户在网页端输入一张图片识别其结果,并基于Pyqt5搭建桌面端可视化界面。 在智能交通和车辆监控领域,车牌识别技术扮

    2024年02月07日
    浏览(73)
  • 深度学习:使用卷积神经网络CNN实现MNIST手写数字识别

    本项目基于pytorch构建了一个深度学习神经网络,网络包含卷积层、池化层、全连接层,通过此网络实现对MINST数据集手写数字的识别,通过本项目代码,从原理上理解手写数字识别的全过程,包括反向传播,梯度下降等。 卷积神经网络是一种多层、前馈型神经网络。从功能上

    2024年02月13日
    浏览(46)
  • 深度学习实战项目(一)-基于cnn和opencv的车牌号识别

    网上大部分是关于tensorflow,使用pytorch的比较少,本文也在之前大佬写的代码的基础上,进行了数据集的完善,和代码的优化,效果可比之前的pytorch版本好一点。 数据集来自github开源的字符数据集: 数据集有:0-9,26个字母减去I和O,还有中文字,这里可以看看几张图片:

    2024年02月06日
    浏览(59)
  • 竞赛保研 基于深度学习的植物识别算法 - cnn opencv python

    🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习的植物识别算法 ** 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:4分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng

    2024年01月25日
    浏览(61)
  • 挑战杯 基于深度学习的植物识别算法 - cnn opencv python

    🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习的植物识别算法 ** 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:4分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng

    2024年04月09日
    浏览(86)
  • 深度学习与图像识别:如何使用深度学习进行图像识别

    深度学习与图像识别:如何使用深度学习进行图像识别 深度学习是一种基于多层神经网络的机器学习方法,能够从大量的数据中自动提取特征和规律,从而实现复杂的任务,如图像识别。图像识别是指让计算机能够理解和分析图像中的内容,如物体、人脸、场景等。使用深度

    2024年02月05日
    浏览(45)
  • 【Python深度学习】Tensorflow+CNN进行人脸识别实战(附源码和数据集)

    需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 下面利用tensorflow平台进行人脸识别实战,使用的是Olivetti Faces人脸图像 部分数据集展示如下  程序训练过程如下  接下来训练CNN模型 可以看到训练进度和损失值变化 接下来展示人脸识别结果   程序会根据一张图片自动

    2024年02月09日
    浏览(44)
  • 计算机竞赛 基于深度学习的植物识别算法 - cnn opencv python

    🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习的植物识别算法 ** 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:4分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng

    2024年02月09日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包