卷积神经网络构建,新图片预测与类激活图

您所在的位置:网站首页 文章插图怎么画 卷积神经网络构建,新图片预测与类激活图

卷积神经网络构建,新图片预测与类激活图

2023-03-31 17:59| 来源: 网络整理| 查看: 265

卷积神经网络构建,新图片预测与类激活图——提高CNN模型的可解释性

文章目录 卷积神经网络构建,新图片预测与类激活图——提高CNN模型的可解释性前言一、卷积神经网络CNN与VGG16 介绍二、搭建CNN模型1.输入数据与图片增强2.搭建CNN模型与编译3.训练模型并保存4.输出训练结果 四、批量新图片的分类及类激活图1.导入模型和要分类的图片2.实现分类并输出结果3.绘制类映射图 结论

前言

卷积神经网络(CNN)作为最基础的图像分类与识别的深度学习模型,在很多领域都有着应用,例如人脸识别,医学图像分类等。本文从CNN出发,介绍基本CNN模型的构建,逐渐深入到复杂CNN变体VGG16的搭建。同时为了提高CNN这类模型的可解释性,使用已保存的CNN和VGG16模型预测批量的新图片,借助类激活图(CAM, class activation map) 对分类结果进行解释。最后绘制受试者工作特性曲线(ROC),对整体预测结果进行分析。

一、卷积神经网络CNN与VGG16 介绍

这部分只做卷积神经网络(CNN)和VGG16的简单介绍,使读者有个基本的了解,具体详细原理及参数请参考其他资料。CNN模型主要结构包括输入层、卷积层、池化层、全连接层和输出层。其中卷积层和池化层是CNN模型关键的功能层。卷积层的作用是对图片进行卷积,从中提取特征。卷积层由不同卷积核组成,常用3 * 3大小卷积核,不同卷积层提取不同特征,例如有的提取边界线条、有的提取整个色块。形象的说,卷积核就像扫描仪,对图片各部分进行扫描,但是这个扫描仪只对它感兴趣的形状重视,不重视的形状重视程度降低。而池化层则是为了降低卷积层提取的特征维度,常见池化的方式包括最大池化和平均池化,池化常用的窗口大小为2 * 2,移动步幅为2。全连接层则是为了将得到的特征展平,方便使用激活函数进行分类。VGG16则是一个16层的卷积神经网络(不包括最大池化层与softmax层),是牛津大学视觉几何团队开发的,目前也常被用于图像分类的任务中。

二、搭建CNN模型

本次代码在python3.7版本的tensroflow框架下搭建,使用了Jupyter notebook来运行。主要任务是对实现猫、狗、兔图片进行多分类,其中训练集数据各有200张,验证集各50张左右,测试集新图片各10张。需要说明的是,本文只是为了说明模型搭建和结果分析,固未使用更多数据,也没有进行更多的调优。读者可根据实际情况进行数据量的扩充和模型的调优。

1.输入数据与图片增强

代码如下():

import os #输入数据 from glob import glob train_dir = 'D:/AM Learning/data/kaggle/3categories/train' #训练集的保存路径 test_dir = 'D:/AM Learning/data/kaggle/3categories/validation' #验证集的保存路径 nb_train_samples = 600 #训练集的图片总数量 nb_validation_samples = 161 验证集的图片数量 epochs = 25 batch_size = 20 from keras.preprocessing.image import ImageDataGenerator #对图片进行处理 #(通过数据增强对图片进行变换) train_datagen = ImageDataGenerator(rescale=1./255,rotation_range =40, #(训练集图片增强) width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2,zoom_range=0.2,horizontal_flip=True) test_datagen = ImageDataGenerator(rescale=1./255) #(验证集图片像素标准化) train_generator = train_datagen.flow_from_directory(train_dir, target_size=(150, 150), #(图片大小) batch_size=batch_size, class_mode='categorical') #(分类类别,二分类对应binary,多分类对应categorical) validation_generator = test_datagen.flow_from_directory(test_dir, target_size=(150, 150), batch_size=batch_size, class_mode='categorical') 2.搭建CNN模型与编译

其中模型的卷积层层数、卷积核数等可根据读者需求调整,代码如下:

from keras import models from keras import layers from keras import optimizers model = models.Sequential() model.add(layers.Conv2D(16,(3,3),activation='relu',input_shape=(150,150,3)))#16个卷积核,每个卷积核大小为3*3 model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(32, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(128, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Flatten()) #model.add(layers.Dropout(0.5)) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(3, activation='softmax')) #数字3表示图片的类别,用于分类的激活函数二分类使用sigmoid,多分类单标签使用softmax #编译模型 model.compile(optimizer=optimizers.RMSprop(lr=1e-5), #设置激活函数和学习率,可以根据实际需要调整 loss='categorical_crossentropy', #误差,二分类对应binary_crossentorpy metrics=['acc']) #查看模型结构及内部参数量 model.summary() #打印不同类别对应的标签 print(train_generator.class_indices) 3.训练模型并保存 #训练模型 history = model.fit_generator(train_generator, #利用批量生成器拟合模型 steps_per_epoch=nb_train_samples/batch_size, epochs=25, validation_data=validation_generator, validation_steps=nb_validation_samples/batch_size) #以“3categories”的名字保存模型 model.save('3categories.h5') 4.输出训练结果 #打印训练集结果与验证集结果 import matplotlib.pyplot as plt acc = history.history['acc'] val_acc = history.history['val_acc'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs = range(1, len(acc)+1) plt.plot(epochs, acc, 'bo', label = 'Training acc') plt.plot(epochs, val_acc, 'b', label = 'Validation acc') plt.title('Training and validation accuracy') plt.legend() plt.figure() plt.plot(epochs, loss, 'ro', label = 'Training loss') plt.plot(epochs, val_loss, 'r', label = 'Validation loss') plt.title('Training and validation loss') plt.legend() plt.show()

训练集和验证及结果如图:

四、批量新图片的分类及类激活图

在训练好CNN模型之后,需要在新的图片上验证其泛化能力,即新数据上分类或预测的准确率。本次还借助类激活图对CNN模型的结果进行了分析。类激活图是指对输入图像生成类激活的热力图,具体方法是对输入图像的一层卷积层提取的特征图,用类别相对于通道的梯度对这个特征图中的每个通道进行加权。直观来说,就是用“每个通道对类别的重要程度”对“输入图像对不同的通道的激活强度”的空间进行加权,从而得到了“输入图像对类别的激活强度”的空间图。

1.导入模型和要分类的图片 import keras from tensorflow.keras.applications import VGG16 #导入已保存地CNN模型 model = keras.models.load_model('3categories.h5') # 导入新图片(使用目标图像的本地路径) img_path = 'D:/AM Learning/data/kaggle/3categories/test/1/dog.19.jpg' 2.实现分类并输出结果 from tensorflow.keras.preprocessing import image from keras.preprocessing.image import img_to_array from keras.applications.vgg16 import preprocess_input import numpy as np import cv2 # (大小为 150×150 的Python图像库(PIL,Python imaging library)图像) img = cv2.imread(img_path) # x形 状 为 (150, 150, 3) 的float32 格式的 Numpy 数组 ,保持和训练时用的图片尺寸大小相同 img_arr = cv2.resize(img,(150,150)) ima_arr = img_to_array(img_arr)/255.0 img_arr = np.expand_dims(img_arr,axis=0) img_arr=preprocess_input(img_arr) #预测目标分类 preds = model.predict(img_arr) proba = np.max(preds) print('Predicted:',preds) #不同类别的可能性 print('prob:',proba) #最终预测的图片类别对应的可能性大小 3.绘制类映射图 from keras import backend as K index=np.argmax(preds[0]) cat_output = model.output[:, index] # conv2d_4层的输出特征图,它是模型的最后一个卷积层,读者根据本身实际情况调整卷积层的名字 last_conv_layer = model.get_layer('conv2d_4') # “图片”类别相对于 conv2d_4输出特征图的梯度 grads = K.gradients(cat_output, last_conv_layer.output)[0] # 形状为 (512,) 的向量,每个元素是特定特征图通道的梯度平均大小 pooled_grads = K.mean(grads, axis=(0, 1, 2)) # 访问刚刚定义的量:对于给定的样本图像,pooled_grads 和 block5_conv3 层的输出特征图 iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]]) # 对于样本图像, 这两个量都是 Numpy 数组 pooled_grads_value, conv_layer_output_value = iterate([img_arr]) # 将特征图数组的每个通道乘以“这个通道 对类别的重要程度” for i in range(conv_layer_output_value.shape[-1]): conv_layer_output_value[:, :, i] *= pooled_grads_value[i] # 得到的特征图的逐通道平均值即为类激活的热力图 heatmap = np.mean(conv_layer_output_value, axis=-1) import matplotlib.pyplot as plt max_heat = np.max(heatmap) if max_heat == 0: max_heat = 1e-10 heatmap /= max_heat plt.matshow(heatmap) plt.show()

选择了两张新图片测试,结果如下图。可以看见“狗”这个类别分类时更关注“黑色”和和“嘴”这两个特征,而兔子更关注”身体“和“白色”这两个特征。当然不同的训练模型会有不同的结果,这里只说原理,不详细讨论结果。具体问题具体分析。 在这里插入图片描述

结论

本文阐述了卷积神经网络CNN的搭建过程,并对新的图片进行预测。同时还阐述了类激活图的搭建预分析。但是还存在以下问题:(1)进行新图片预测时,只能单张的预测,效率较低,应该考虑批量图片的预测;(2)图片数据量较少时,预测准确率较低,应考虑较复杂的模型。以上这两个问题将会在后面进行讨论。 本文参考了《python深度学习》与部分网友的思路,若侵权请联系本人。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3