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

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()

http://www.xdnf.cn/news/10519.html

相关文章:

  • Python 详细分析死锁原因及对应解决方案
  • 摩尔投票算法原理实现一文剖析
  • 基于 51 单片机的智能饮水机控制系统设计与实现
  • 低能硼注入的粒子控制 Axcelis Purion高电流离子注入机近晶圆环境中的石墨衬垫
  • BUUCTF[极客大挑战 2019]Secret File 1题解
  • 基于 Alpine 定制单功能用途(kiosk)电脑
  • 高效视频倍速播放插件推荐
  • 青少年编程与数学 02-020 C#程序设计基础 17课题、WEB与移动开发
  • C++中实现随机数(超详细!​​​​​)
  • 【Doris基础】Apache Doris中的Coordinator节点作用详解
  • 【MATLAB代码】制导——平行接近法,三维,目标是运动的,订阅专栏后可直接查看MATLAB源代码
  • C#项目07-二维数组的随机创建
  • Kotlin 中 companion object 扩展函数和普通函数区别
  • Qt OpenGL 3D 编程入门
  • Grafana对接Prometheus数据源
  • JAVA学习-练习试用Java实现“使用JavaFX绘制散点图 :可视化数据集”
  • 【2025年B卷】华为OD-100分-字符串重新排列、字符串重新排序
  • 解锁 AI 大语言模型的“知识宝藏”:知识库的奥秘与优化之道
  • TDengine 的 AI 应用实战——电力需求预测
  • 秋招Day12 - 计算机网络 - UDP
  • 阿里云国际站,如何通过代理商邀请的链接注册账号
  • 多维度健康护理:为进行性核上性麻痹患者护航
  • Python基础入门:开启编程之旅
  • 数据资产评估进阶:精读资产评估专家指引第9号——数据资产评估指导【附全文阅读】
  • CppCon 2014 学习:Gamgee: A C++14 library for genomic data processing and analysis
  • 服务器间文件传输
  • Linux_T(Sticky Bit)粘滞位详解
  • Spring Boot中的WebSocket技术实现
  • Linux 权限管理入门:从基础到实践
  • 123网盘SDK-npm包已发布