当前位置: 首页 > news >正文

DAY 43 复习日

作业:

kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化

进阶:并拆分成多个文件

import os
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers, models, applications
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau
from tensorflow.keras.models import load_model
import cv2# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]class DataLoader:def __init__(self, data_dir, img_size=(224, 224), batch_size=32):self.data_dir = data_dirself.img_size = img_sizeself.batch_size = batch_sizedef load_data(self):"""加载并预处理图像数据"""# 数据增强配置train_datagen = ImageDataGenerator(rescale=1./255,rotation_range=20,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,validation_split=0.2)test_datagen = ImageDataGenerator(rescale=1./255)# 生成训练集和验证集train_generator = train_datagen.flow_from_directory(os.path.join(self.data_dir, 'train'),target_size=self.img_size,batch_size=self.batch_size,class_mode='categorical',subset='training')val_generator = train_datagen.flow_from_directory(os.path.join(self.data_dir, 'train'),target_size=self.img_size,batch_size=self.batch_size,class_mode='categorical',subset='validation')# 生成测试集test_generator = test_datagen.flow_from_directory(os.path.join(self.data_dir, 'test'),target_size=self.img_size,batch_size=self.batch_size,class_mode='categorical')return train_generator, val_generator, test_generatorclass CNNModel:def __init__(self, input_shape, num_classes):self.input_shape = input_shapeself.num_classes = num_classesdef build_simple_cnn(self):"""构建简单的CNN模型"""model = models.Sequential([layers.Conv2D(32, (3, 3), activation='relu', input_shape=self.input_shape),layers.MaxPooling2D((2, 2)),layers.Conv2D(64, (3, 3), activation='relu'),layers.MaxPooling2D((2, 2)),layers.Conv2D(128, (3, 3), activation='relu'),layers.MaxPooling2D((2, 2)),layers.Flatten(),layers.Dense(128, activation='relu'),layers.Dropout(0.5),layers.Dense(self.num_classes, activation='softmax')])model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])return modeldef build_pretrained_model(self, model_name='vgg16'):"""构建基于预训练模型的CNN"""if model_name == 'vgg16':base_model = applications.VGG16(weights='imagenet',include_top=False,input_shape=self.input_shape)elif model_name == 'resnet50':base_model = applications.ResNet50(weights='imagenet',include_top=False,input_shape=self.input_shape)else:raise ValueError("不支持的预训练模型")# 冻结预训练层for layer in base_model.layers:layer.trainable = False# 添加自定义层x = base_model.outputx = layers.GlobalAveragePooling2D()(x)x = layers.Dense(256, activation='relu')(x)x = layers.Dropout(0.5)(x)predictions = layers.Dense(self.num_classes, activation='softmax')(x)model = models.Model(inputs=base_model.input, outputs=predictions)model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])return model, base_modelclass ModelTrainer:def __init__(self, model, model_path='best_model.h5'):self.model = modelself.model_path = model_pathdef train(self, train_generator, val_generator, epochs=10):"""训练模型"""callbacks = [EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True),ModelCheckpoint(self.model_path, monitor='val_accuracy', save_best_only=True),ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=2, min_lr=0.00001)]history = self.model.fit(train_generator,steps_per_epoch=train_generator.samples // train_generator.batch_size,validation_data=val_generator,validation_steps=val_generator.samples // val_generator.batch_size,epochs=epochs,callbacks=callbacks)return historyclass GradCAM:def __init__(self, model, class_names, layer_name=None):self.model = modelself.class_names = class_names# 如果没有指定层名,尝试自动找到最后一个卷积层if layer_name is None:layer_name = self._find_last_conv_layer()self.layer_name = layer_namedef _find_last_conv_layer(self):"""自动查找模型的最后一个卷积层"""for layer in reversed(self.model.layers):if 'conv' in layer.name:return layer.nameraise ValueError("模型中没有找到卷积层")def generate_heatmap(self, img_array, pred_index=None):"""生成Grad-CAM热力图"""# 创建一个用于获取输出的模型grad_model = tf.keras.models.Model([self.model.inputs], [self.model.get_layer(self.layer_name).output, self.model.output])# 计算梯度with tf.GradientTape() as tape:conv_outputs, predictions = grad_model(img_array)if pred_index is None:pred_index = tf.argmax(predictions[0])class_channel = predictions[:, pred_index]# 获取梯度grads = tape.gradient(class_channel, conv_outputs)# 平均梯度pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))# 权重激活映射conv_outputs = conv_outputs[0]heatmap = tf.reduce_mean(tf.multiply(pooled_grads, conv_outputs), axis=-1)# 归一化热力图heatmap = np.maximum(heatmap, 0) / np.max(heatmap)return heatmapdef overlay_heatmap(self, heatmap, img, alpha=0.4):"""将热力图叠加到原图上"""# 调整热力图大小以匹配原图heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))# 将热力图转换为RGBheatmap = np.uint8(255 * heatmap)heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)# 将热力图叠加到原图上superimposed_img = heatmap * alpha + imgsuperimposed_img = np.uint8(255 * superimposed_img / np.max(superimposed_img))return superimposed_imgdef visualize(self, img_path, img_size=(224, 224), alpha=0.4, top_n=3):"""可视化Grad-CAM结果"""# 加载和预处理图像img = tf.keras.preprocessing.image.load_img(img_path, target_size=img_size)img_array = tf.keras.preprocessing.image.img_to_array(img)img_array = np.expand_dims(img_array, axis=0)img_array = img_array / 255.0# 预测类别predictions = self.model.predict(img_array)top_indices = np.argsort(predictions[0])[::-1][:top_n]# 生成热力图heatmap = self.generate_heatmap(img_array)# 加载原图用于显示original_img = cv2.imread(img_path)original_img = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB)original_img = cv2.resize(original_img, img_size)# 叠加热力图superimposed_img = self.overlay_heatmap(heatmap, original_img, alpha)# 显示结果plt.figure(figsize=(15, 5))plt.subplot(131)plt.title('原始图像')plt.imshow(original_img)plt.axis('off')plt.subplot(132)plt.title('Grad-CAM热力图')plt.imshow(heatmap, cmap='jet')plt.axis('off')plt.subplot(133)plt.title('叠加结果')plt.imshow(superimposed_img)plt.axis('off')# 显示预测结果plt.figtext(0.5, 0.01, f"预测结果:\n" + "\n".join([f"{self.class_names[idx]}: {predictions[0][idx]:.2%}" for idx in top_indices]),ha="center", fontsize=12)plt.tight_layout()plt.show()def download_kaggle_dataset(api_command):"""使用Kaggle API下载数据集"""print(f"正在下载数据集: {api_command}")os.system(f"kaggle datasets download {api_command} -p ./data --unzip")print("数据集下载完成")def main():# 设置参数data_dir = './data/your_dataset'  # 数据集路径img_size = (224, 224)batch_size = 32epochs = 10model_path = 'best_model.h5'use_pretrained = True  # 是否使用预训练模型# 下载Kaggle数据集(取消注释并提供正确的API命令)# download_kaggle_dataset('username/dataset-name')# 加载数据data_loader = DataLoader(data_dir, img_size, batch_size)train_generator, val_generator, test_generator = data_loader.load_data()num_classes = len(train_generator.class_indices)class_names = list(train_generator.class_indices.keys())# 构建模型cnn_model = CNNModel(input_shape=(*img_size, 3), num_classes=num_classes)if use_pretrained:model, base_model = cnn_model.build_pretrained_model()last_conv_layer = base_model.get_layer('block5_conv3').name  # VGG16最后一个卷积层else:model = cnn_model.build_simple_cnn()last_conv_layer = None  # 自动查找最后一个卷积层# 训练模型trainer = ModelTrainer(model, model_path)history = trainer.train(train_generator, val_generator, epochs)# 评估模型test_loss, test_acc = model.evaluate(test_generator)print(f"测试准确率: {test_acc:.2%}")# 可视化训练历史plt.figure(figsize=(12, 4))plt.subplot(121)plt.plot(history.history['accuracy'])plt.plot(history.history['val_accuracy'])plt.title('模型准确率')plt.ylabel('准确率')plt.xlabel('训练轮次')plt.legend(['训练', '验证'], loc='upper left')plt.subplot(122)plt.plot(history.history['loss'])plt.plot(history.history['val_loss'])plt.title('模型损失')plt.ylabel('损失')plt.xlabel('训练轮次')plt.legend(['训练', '验证'], loc='upper left')plt.tight_layout()plt.show()# 加载最佳模型用于Grad-CAMbest_model = load_model(model_path)# 选择一个测试图像进行Grad-CAM可视化test_image_path = os.path.join(data_dir, 'test', class_names[0], os.listdir(os.path.join(data_dir, 'test', class_names[0]))[0])# 创建Grad-CAM对象并可视化grad_cam = GradCAM(best_model, class_names, last_conv_layer)grad_cam.visualize(test_image_path)if __name__ == "__main__":main()

相关文章:

  • 网络安全:网页密码防护与记住密码功能的安全
  • 常见ADB指令
  • CLion调试无法触发断点
  • CppCon 2014 学习:Gamgee: A C++14 library for genomic data processing and analysis
  • Spring Security入门:创建第一个安全REST端点项目
  • NodeJS全栈WEB3面试题——P5全栈集成与 DApp 构建
  • mysql分布式教程
  • CentOS8.3+Kubernetes1.32.5+Docker28.2.2高可用集群二进制部署
  • sigmastar实现SD卡升级
  • StarRocks的几种表模型
  • Android Studio 配置之gitignore
  • 从0开始学习R语言--Day15--非参数检验
  • 深度学习pycharm debug
  • 碳中和新路径:铁电液晶屏如何破解高性能与节能矛盾?
  • C++.cstring string
  • 渗透测试之信息搜集
  • 第1篇:数据库中间件概述:架构演进、典型方案与应用场景
  • React 组件异常捕获机制详解
  • Linux --TCP协议实现简单的网络通信(中英翻译)
  • vite构建工具
  • 网站建设地址北京昌平/常州网站制作维护
  • 做翻页电子书的网站/深圳网站seo优化公司
  • apache多个网站/seo长尾关键词排名
  • 南通做公司网站/排超联赛积分榜
  • 怎样做单页微信网站连接/邢台市seo服务
  • 给政府做网站怎么报价/seo常用的工具