第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个GPUtf.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 = 100train_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.AUTOTUNEdef 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, LearningRateSchedulerNO_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-CAMwith 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 # 防止除以0heatmap /= 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)
输出如下:

然后,用哪一层呢?
其实吧,选择哪一层用于Grad-CAM的计算并没有一条明确的规则,这完全取决于你的模型结构以及你的具体需求。
一般来说,Convolutional Neural Networks(CNN,卷积神经网络)的前面几层往往捕捉到的是图像的低级特征,比如边缘、色彩和纹理等,而后面的层则可以捕捉到更为高级的特征,比如物体的部分或者整体。所以,如果你想要看到模型在判断图像时,主要关注了图像中的哪些部分或者物体,你可能需要选择离输出层更近一些的卷积层。
但是这也不是绝对的。在实际应用中,你可能需要尝试不同的层,看看哪一层生成的Grad-CAM热力图最能满足你的需求。
比如我试了试:'block_1_project':

'block_7_project':

'block_10_project':

'block_2_add':

综上,似乎一切随缘,太抽象了!!!
三、写在最后
略~
四、数据
链接:https://pan.baidu.com/s/15vSVhz1rQBtqNkNp2GQyVw?pwd=x3jf
提取码:x3jf
相关文章:
第56步 深度学习图像识别:CNN梯度权重类激活映射(TensorFlow)
基于WIN10的64位系统演示 一、写在前面 类激活映射(Class Activation Mapping,CAM)和梯度权重类激活映射(Gradient-weighted Class Activation Mapping,Grad-CAM)是两种可视化深度学习模型决策过程的技术…...
云道资本:2023中国氢能源产业-氢制备深度研究报告(附下载)
关于报告的所有内容,公众【营销人星球】获取下载查看 核心观点 中国可再生能源消纳能力提升远远滞后于发电占比的提升。大规模的可再生能源发电是实现碳中和的关键一步,但风电、光伏发电间歌性、波动性强,电网消纳压力较大,且电…...
java文件
一.File类 二.扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件 我的代码: import java.io.File; import java.io.IOException; import java.util.Scanner;public class Tes…...
pyqt5 如何终止正在执行的线程?
在 PyQt5 中终止正在执行的线程,可以通过一些协调的方法来实现。一般情况下,直接强行终止线程是不安全的,可能会导致资源泄漏或者程序异常。相反,我们可以使用一种协作的方式,通知线程在合适的时候自行退出。 以下是一…...
力扣第357场周赛补题
6925. 故障键盘 - 力扣(LeetCode) 思路:模拟 class Solution { public:string finalString(string s) {string res;for(auto c : s){if(c i) reverse(res.begin(), res.end());else res c;}return res;} }; 6953. 判断是否能拆分数组 - 力…...
Keras指定model.fit()的输出
model.fit()当verbose1的时候会打印出所有指标和loss, 在多输出的情况下更是一团乱麻. 下面是一个可以指定每个epoch训练完的输入指标的方法: from keras.callbacks import Callback# Custom callback to display loss only at the end of each epoch class LossCallback(Call…...
替换开源LDAP,某科技企业用宁盾目录统一身份,为业务敏捷提供支撑
客户介绍 某高科技企业成立于2015年,是一家深耕于大物流领域的人工智能公司,迄今为止已为全球16个国家和地区,120余家客户打造智能化升级体验,场景覆盖海陆空铁、工厂等货运物流领域。 该公司使用开源LDAP面临的挑战 挑战1 开源…...
解决log4j.xml的url没有注册问题
在对log4j.xml配置文件配置时出现http//jakarta.apache.org/log4j/爆红,IDEA提示uri is not registered。源代码如下 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j"http://jakarta.apache.org/lo…...
深度思考操作系统面经
1 堆和栈的区别:(如果记的不太清楚,可以类比jvm中的堆和栈的区别,大差不差) 存储位置:堆是在计算机内存中动态分配的区域,而栈是在计算机内存中由操作系统自动分配和管理的区域。管理方式&…...
智慧工地源码:数字孪生智慧工地可视化解决方案
一、智慧工地建设背景 我国经济发展正从传统粗放式的高速增长阶段,进入高效率、低成本、可持续的中高速增长阶段。随着现代建筑的复杂度和体量等不断增加,施工现场管理的内容越来越多,管理的技术难度和要求在不断提高。传统的施工现场管理模…...
解决rockchip平台Android13系统以太网设置静态IP保存不了问题
前言 rk平台平Android13系统测试以太网,发现设置静态IP保存不了问题,即设置静态IP以后重启系统,IP又变成动态的了。 分析 抓取log发现保存静态IP的时候会打印如下log: 08-07 06:22:28.377 626 749 D EthernetNetworkFactory: updateInterface, iface: eth0, ipConfi…...
SQLAlchemy与标准SQL相比有哪些优点?
让我来给你讲讲SQLAlchemy和标准SQL相比有哪些优点吧! 首先,我们要知道,SQLAlchemy是一个Python的SQL工具包和对象关系映射(ORM)系统,它把Python的面向对象编程(OOP)的理念带入了数…...
Zookeeper与Kafka
Zookeeper与Kafka 一、Zookeeper 概述1.Zookeeper 定义2.Zookeeper 工作机制3.Zookeeper 特点4.Zookeeper 数据结构5.Zookeeper 应用场景6.Zookeeper 选举机制 二、部署 Zookeeper 集群1.准备 3 台服务器做 Zookeeper 集群2.安装 Zookeeper3.拷贝配置好的 Zookeeper 配置文件到…...
MySQL—— 基础语法大全
MySQL—— 基础 一、MySQL概述1.1 、数据库相关概念1.2 、MySQL 客户端连接1.3 、数据模型 二、SQL2.1、SQL通用语法2.2、SQL分类2.3、DDL2.4、DML2.5、DQL2.6、DCL 三、函数四、约束五、多表查询六、事务 一、MySQL概述 1.1 、数据库相关概念 数据库、数据库管理系统、SQL&a…...
css小练习:案例6.炫彩加载
一.效果浏览图 二.实现思路 html部分 HTML 写了一个加载动画效果,使用了一个包含多个 <span> 元素的 <div> 元素,并为每个 <span> 元素设置了一个自定义属性 --i。 这段代码创建了一个简单的动态加载动画,由20个垂直排列的…...
使用正则表达式替换文本中的html标签
文章目录 使用正则表达式替换文本中的html标签原文本:使用正则表达式进行替换替换后:展示 html 文本 使用正则表达式替换文本中的html标签 我们存储 markdown 文章时,如果存储转换后的 html 页面,那么在查出来的时候,…...
当向数据库导入大量数据时,mysql主键唯一键重复插入,如何丝滑操作并不导入重复数据呢
解决办法: 答案来源:...
【go-zero】docker镜像直接部署go-zero的API与RPC服务 如何实现注册发现?docker network 实现 go-zero 注册发现
一、场景&问题 使用docker直接部署go-zero微服务会发现API无法找到RPC服务 1、API无法发现RPC服务 用docker直接部署 我们会发现API无法注册发现RPC服务 原因是我们缺少了docker的network网桥 2、系统内查看 RPC服务运行正常API服务启动,通过docker logs 查看日志还是未…...
微信小程序读取本地json
首先在项目录下新建【server】文件夹,新建data.js文件,并定义好json数据格式。如下: pages/index/index.ts导入data.js并请求json pages/index/index.wxml页面展示数据...
Stephen Wolfram:ChatGPT 的训练
The Training of ChatGPT ChatGPT 的训练 OK, so we’ve now given an outline of how ChatGPT works once it’s set up. But how did it get set up? How were all those 175 billion weights in its neural net determined? Basically they’re the result of very large…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
