Keras+VGG16特征图可视化

  • 一、VGG16结构理解
    • 1. 可视化结构图
    • 2. VGGNet各级别网络结构图
    • 3. VGG16网络结构图
  • 二、Keras实现VGG16
    • 代码实现
  • 三、VGG16特征图可视化
    • 代码实现

一、VGG16结构理解

1. 可视化结构图

2. VGGNet各级别网络结构图

3. VGG16网络结构图


总结:三种不同的形式,方便大家对VGG16架构有更为直观的认识。

二、Keras实现VGG16

代码实现

# -*- coding: utf-8 -*-
"""
Created on Tue Apr  7 09:15:36 2020@author: wuzhendong
"""
import keras
#cifar10数据集:60000张彩色图像,这些图像是32*32,分为10个类,每类6000张图
from keras.datasets import cifar10
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, BatchNormalization
from keras.optimizers import SGD
from keras import regularizers
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report#该数据集需要自动下载,大小约为163M,若下载失败可手动下载
#下载链接:https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
(x_train, y_train), (x_test, y_test) = cifar10.load_data()x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)#训练集和验证集7/3分
x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size = 0.3)#用于正则化时权重降低的速度
weight_decay = 0.0005 #权重衰减(L2正则化),作用是避免过拟合
nb_epoch=50 #50轮
batch_size=32 #每轮32张图#layer1 32*32*3
model = Sequential()
#第一层 卷积层 的卷积核的数目是32 ,卷积核的大小是3*3,keras卷积层stride默认是1*1
#对于stride=1*1,padding ='same',这种情况卷积后的图像shape与卷积前相同,本层后shape还是32*32
model.add(Conv2D(64, (3, 3), padding='same',strides=(1, 1),
input_shape=(32,32,3),kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))
#进行一次归一化
model.add(BatchNormalization())
model.add(Dropout(0.3))#layer2 32*32*64
model.add(Conv2D(64, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
#keras 池化层 stride默认是2*2, padding默认是valid,输出的shape是16*16*64
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2),padding='same'))#layer3 16*16*64
model.add(Conv2D(128, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.4))#layer4 16*16*128
model.add(Conv2D(128, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))#layer5 8*8*128
model.add(Conv2D(256, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.4))#layer6 8*8*256
model.add(Conv2D(256, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.4))#layer7 8*8*256
model.add(Conv2D(256, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))#layer8 4*4*256
model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.4))#layer9 4*4*512
model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.4))#layer10 4*4*512
model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))#layer11 2*2*512
model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.4))#layer12 2*2*512
model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.4))#layer13 2*2*512
model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))#layer14 1*1*512
model.add(Flatten())
model.add(Dense(512,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())#layer15 512
model.add(Dense(512,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation('relu'))
model.add(BatchNormalization())#layer16 512
model.add(Dropout(0.5))
model.add(Dense(10))
model.add(Activation('softmax'))# 10
model.summary()
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd,metrics=['accuracy'])#训练
model.fit(x_train, y_train, epochs=nb_epoch, batch_size=batch_size,validation_split=0.1, verbose=1)#验证 loss值和 准确率
loss, acc = model.evaluate(x_val, y_val, batch_size=batch_size, verbose=1, sample_weight=None)
print("accuracy:",acc)
print("loss",loss)#推理
y_pred = model.predict_classes(x_test, batch_size=32, verbose=0)
y_pred = keras.utils.to_categorical(y_pred, 10)
#测试集的准确率
print("accuracy score:", accuracy_score(y_test, y_pred))
#分类报告
print(classification_report(y_test, y_pred))
#保存模型
#官方文档不推荐使用pickle或cPickle来保存Keras模型
model.save('keras_vgg16_cifar10.h5')
#.h5文件是 HDF5文件,改文件包含:模型结构、权重、训练配置(损失函数、优化器等)、优化器状态
#使用keras.models.load_model(filepath)来重新实例化你的模型#只保存模型结构
# save as JSON
json_string = model.to_json()
# save as YAML
yaml_string = model.to_yaml()#保存模型权重
model.save_weights('my_model_weights.h5')

! ! ! 加 载 c i f a r 10 数 据 集 失 败 的 解 决 办 法 \color{#FF0000} { !!!加载cifar10数据集失败 的解决办法 } !!!加载cifar10数据集失败的解决办法

由于网络不稳定,在执行 (x_train, y_train), (x_test, y_test) = cifar10.load_data() 自动加载数据集时可能会失败,解决办法如下:

  1. 迅雷下载:http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
  2. 更改文件名为:cifar-10-batches-py.tar.gz
  3. 移动该压缩文件至 ~/.keras/datasets/
  4. 解压

下次再执行 (x_train, y_train), (x_test, y_test) = cifar10.load_data() 则会自动加载下载好的数据集。

三、VGG16特征图可视化

代码实现

# -*- coding: utf-8 -*-
"""
Created on Tue Apr  7 11:57:10 2020@author: wuzhendong
"""from keras.models  import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, BatchNormalization
import cv2
import os
import shutil
import numpy as np
import matplotlib.pyplot as plt
from keras import regularizers#网络模型
def create_model():#用于正则化时权重降低的速度weight_decay = 0.0005 #权重衰减(L2正则化),作用是避免过拟合    #layer1 32*32*3model = Sequential()#第一层 卷积层 的卷积核的数目是32 ,卷积核的大小是3*3,keras卷积层stride默认是1*1#对于stride=1*1,padding ='same',这种情况卷积后的图像shape与卷积前相同,本层后shape还是32*32model.add(Conv2D(64, (3, 3), padding='same',strides=(1, 1),input_shape=(32,32,3),kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))#进行一次归一化model.add(BatchNormalization())model.add(Dropout(0.3))#layer2 32*32*64model.add(Conv2D(64, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())#keras 池化层 stride默认是2*2, padding默认是valid,输出的shape是16*16*64model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2),padding='same'))#layer3 16*16*64model.add(Conv2D(128, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(Dropout(0.4))#layer4 16*16*128model.add(Conv2D(128, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(MaxPooling2D(pool_size=(2, 2)))#layer5 8*8*128model.add(Conv2D(256, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(Dropout(0.4))#layer6 8*8*256model.add(Conv2D(256, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(Dropout(0.4))#layer7 8*8*256model.add(Conv2D(256, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(MaxPooling2D(pool_size=(2, 2)))#layer8 4*4*256model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(Dropout(0.4))#layer9 4*4*512model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(Dropout(0.4))#layer10 4*4*512model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(MaxPooling2D(pool_size=(2, 2)))#layer11 2*2*512model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(Dropout(0.4))#layer12 2*2*512model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(Dropout(0.4))#layer13 2*2*512model.add(Conv2D(512, (3, 3), padding='same',kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Dropout(0.5))#layer14 1*1*512model.add(Flatten())model.add(Dense(512,kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())#layer15 512model.add(Dense(512,kernel_regularizer=regularizers.l2(weight_decay)))model.add(Activation('relu'))model.add(BatchNormalization())#layer16 512model.add(Dropout(0.5))model.add(Dense(10))model.add(Activation('softmax'))return model#保存特征图
def save_conv_img(conv_img):feature_maps = np.squeeze(conv_img,axis=0)img_num = feature_maps.shape[2]#卷积核个数对应特征图个数all_feature_maps = []for i in range(0,img_num):single_feature_map = feature_maps[:,:,i]all_feature_maps.append(single_feature_map)plt.imshow(single_feature_map)plt.savefig('./feature_map/'+'feature_{}'.format(i))sum_feature_map = sum(feature_map for feature_map in all_feature_maps)plt.imshow(sum_feature_map)plt.savefig("./feature_map/feature_map_sum.png")def create_dir():if not os.path.exists('./feature_map'):os.mkdir('./feature_map')else:shutil.rmtree('./feature_map')os.mkdir('./feature_map')if __name__ =='__main__':img = cv2.imread('cat_1.jpg')print(img.shape)create_dir()model = create_model()img_batch = np.expand_dims(img,axis=0)conv_img = model.predict(img_batch) #predict()的参数是需要四维的save_conv_img(conv_img)

需要展示哪一层的特征图,就代码注释掉后面的哪几层。举个例子,你想观察第7层,就将Layer 7 后面的代码注释掉。

create_model() 函数跟上一章节VGG16代码实现是完全相同的。

注意:第一层的 input_shape=(32, 32, 3) 代表你输入的图像必须是32×32大小,这里需要和你的输入图片大小完全一致。假如你输入一张640(W:宽)× 480(H:高)的图片,则需要改为 input_shape=(480, 640, 3)。

举例:输入图片 640(W:宽)× 480(H:高)

原图
第七层第3个卷积核产生的特征图
第七层第49个卷积核产生的特征图

第七层第256个卷积核产生的特征图原图第七层第3个卷积核产生的特征图
第七层第256个卷积核产生的特征图
第十三层第3个卷积核产生的特征图
第十三层第256个卷积核产生的特征图

【总结】Keras+VGG16特征图可视化,帮助你深入理解VGG16相关推荐

  1. 深度学习网络和特征图可视化的工具介绍

    1.深度学习网络结构画图工具: 网络结构画图工具https://cbovar.github.io/ConvNetDraw/ 输入:层信息 输出:网络结构图 网络结构图实例 2.caffe可视化工具 输 ...

  2. 收藏 | PyTorch模型训练特征图可视化(TensorboardX)

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:作者丨Pa ...

  3. caffe之特征图可视化及特征提取

    上一篇博客,介绍了怎么对训练好的model的各层权重可视化,这篇博客,我们介绍测试图片输入网络后产生的特征图的可视化 记得上篇中,我们是写了一个新的文件test.cpp,然后编译运行那个文件的,这是因 ...

  4. CNN神经网络猫狗分类经典案例,深度学习过程中间层激活特征图可视化

    AI:CNN神经网络猫狗分类经典案例,深度学习过程中间层激活特征图可视化 基于前文 https://zhangphil.blog.csdn.net/article/details/103581736 ...

  5. CNN可视化技术总结(一)--特征图可视化

    导言: 在CV很多方向所谓改进模型,改进网络,都是在按照人的主观思想在改进,常常在说CNN的本质是提取特征,但并不知道它提取了什么特征,哪些区域对于识别真正起作用,也不知道网络是根据什么得出了分类结果 ...

  6. caffe for windows的matlab接口(四):权重和特征图可视化的一个例子

    模型读取 参照三,想实现一个自己图像的可视化过程: 首先我发现自己训练出的model没有deploy文件.查阅了下:"如果要把训练好的模型拿来测试新的图片,那必须得要一个deploy.pro ...

  7. yolov5特征图可视化

    文章目录 前言 一.效果图 二.使用步骤 1.使用方法 2.注意事项 总结 参考 前言 最近写论文需要观察中间特征层的特征图,使用的是yolov5的代码仓库,但是苦于找不到很好的轮子,于是参考了很多, ...

  8. 卷积神经网络特征图可视化热图可视化

    文章目录 前言 一.可视化特征图 二.热力图可视化(图像分类) 总结 前言 使用pytorch中的钩子将特征图和梯度勾出来,从而达到可视化特征图(featuremap)和可视化热图(heatmap)的 ...

  9. 卷积神经网络特征图可视化及其意义

    文章目录 特征图可视化方法 1. tensor->numpy->plt.save 2. register_forward_pre_hook函数实现特征图获取 3. 反卷积可视化 特征图可视 ...

最新文章

  1. 先来先服务调度算法(FCFS)
  2. largest number java_LeetCode算法题-Largest Number At Least Twice of Others(Java实现)
  3. 远场语音识别,性能提升 30%,百度怎么做到的?
  4. java日志学习笔记
  5. Linux系统学习笔记:文件描述符标志
  6. python基础代码事例-python基础代码大全
  7. Teams bot的调用限制
  8. linux下使用pidcat找bug
  9. python开发商城实战_python框架Django实战商城项目之工程搭建
  10. AI 的下一个重大挑战:理解语言的细微差别
  11. 十三、栅栏CyclicBarrier
  12. 加密软件漏洞评测系统_【E周道】Elasticsearch泄露12亿用户数据 开源VNC存在37个漏洞...
  13. 天天唠叨的MySQL优化,到底该怎么玩?
  14. SQL:postgresql点geom转换为经纬度、POINT
  15. DEDECMS v5.7 实现导航条下拉二级菜单
  16. linebreak_经典MT4指标3LineBreak
  17. android 网页取词,有道词典屏幕取词怎么用?,你知道吗?在浏览网页
  18. FreeRTOS快速入门-初探FreeRTOS
  19. java使用RXTX的详细总结
  20. 投影仪如何选择?怎样选购家用投影仪

热门文章

  1. 实验五:MSI时序逻辑部件应用(彩灯流水电路的设计)
  2. osCommerce安装指南
  3. 怎样判断漂亮女孩是不是单身的?
  4. Java 后端开发常考面试题有哪些?
  5. 可扩展性强且经济高效?RealMedia HD低延时直播方案为你支招
  6. 对称加密与非对称加密的优缺点及非对称加密的使用前提
  7. 虚拟机centos 7网络配置
  8. OpenStack GlanceCinder Havana版本的新变化 (by quqi99)
  9. Http与Https区别,加密,证书
  10. nom总结与实习经历