Caffe_Windows学习笔记(四)逐层可视化图像特征

这篇博客记录了使用Caffe在Windows环境下进行深度学习模型的图像特征逐层可视化的步骤,包括加载网络、预处理输入、GPU分类及中间层特征、直方图的可视化,并展示了不同阶段的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0、参考文献

[1]官网 http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb

[2]薛开宇《读书笔记 5 逐层可视化图像特征》

[3]Jesse_Mx http://blog.youkuaiyun.com/jesse_mx/article/details/58605385

1、准备工作

#设置Python环境
import numpy as np 
import matplotlib.pyplot as plt

#设置显示默认值,rcParams是一个包含各种参数的字典结构,含有多个key-value,可修改其中部分值
plt.rcParams['figure.figsize']=(10,10) #图像显示大小,单位是英寸
plt.rcParams['image.interpolation']='nearest' #最近邻差值,像素为正方形
plt.rcParams['image.cmap']='gray' #使用灰度输出而不是彩色输出

#加载caffe
import sys
caffe_root = 'D:/caffe_test/caffe-master/'
sys.path.insert(0,caffe_root + 'python')

import caffe
#如果你的“No module named _caffe”,要么你没有建立pycaffe,要么你有错误的路径。
#我将Build/x64/Release/pycaffe下的caffe文件夹替换了python下的caffe

'''
#我已下载过bvlc_reference_caffenet.caffemodel,故以下步骤不做
import os
if os.path.isfile(caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'):
    print 'CaffeNet found.'
else:
    print 'Downloading pre-trained CaffeNet model...'
    !../scripts/download_model_binary.py ../models/bvlc_reference_caffenet
'''

2、加载网络以及输入预处理

#设置gpu模式以及从硬盘加载网络
caffe.set_mode_gpu()

model_def = caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt'
model_weights = caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'

net=caffe.Net(model_def, #定义模型结构
              model_weights, #包含模型训练权重
              caffe.TEST) #使用测试模式(训练中不能执行dropout)

#图像预处理
#加载ImageNet训练集的图像均值,预处理需要减去均值
#ilsvrc_2012_mean.npy文件是numpy格式,其数据维度是(3L, 256L, 256L)
mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy') #加载均值文件
mu = mu.mean(1).mean(1) #对所有像素值取平均以此获取BGR的均值像素值
print 'mean-subtracted values:',zip('BGR',mu)

#对输入数据进行变换
#caffe.io.transformer是一个类,实体化的时候构造函数__init__(self, inputs)给一个初值
#其中net.blobs本身是一个字典,每一个key对应每一层的名字
transformer = caffe.io.Transformer({'data':net.blobs['data'].data.shape})

#以下都是caffe.io.transformer类的函数方法,caffe.io.transformer的类定义放在io.py文件中
transformer.set_transpose('data',(2,0,1)) #将图像通道数设置为outermost的维数
transformer.set_mean('data',mu) #每个通道减去均值
transformer.set_raw_scale('data',255) #像素值从[0,1]变换为[0,255]
transformer.set_channel_swap('data',(2,1,0)) #交换通道,RGB->BGR

3、运行GPU分类程序

#载入图片
#设置输入图像大小
net.blobs['data'].reshape(50, #尽管只检测一张图片,batch size仍为50
                          3,  #3通道
                          227,227) #图片尺寸227x227
         
#加载图片,函数声明为load_image(filename, color=True)
image = caffe.io.load_image(caffe_root+'examples/images/cat.jpg')
#按照之前设置进行预处理
transformed_image = transformer.preprocess('data',image)
plt.imshow(image) #显示图片

结果:

#进行分类,获取结果
#将图像数据拷贝到为net分配的内存中
net.blobs['data'].data[...]=transformed_image

#前向传播,进行分类
#前向传播,跑一遍网络,默认结果为最后一层的blob(也可以指定某一中间层),赋给output
output = net.forward()

#output['prob']矩阵的维度是(50, 1000)
output_prob = output['prob'][0] #取batch中第一张图像的概率值

# 打印概率最大的类别代号,argmax()函数是求取矩阵中最大元素的索引
print 'predicted class is:',output_prob.argmax()

结果:

predicted class is: 281
网络输出是一个概率向量,最可能的类别是第281个类别。但是结果是否正确呢,需要查看一下ImageNet的标签。
#加载ImageNet标签
labels_file = caffe_root +'data/ilsvrc12/synset_words.txt'

#读取纯文本数据,三个参数分别是文件地址、数据类型和数据分隔符,保存为字典格式 
labels = np.loadtxt(labels_file,str,delimiter='\t')

print 'output label:',labels[output_prob.argmax()]

结果:

output label: n02123045 tabby, tabby cat
#从softmax output可查看置信度最高的五个结果
top_inds = output_prob.argsort()[::-1][:5] #逆序排列,取前五个最大值

print 'probabilities and labels:'
zip(output_prob[top_inds],labels[top_inds])

结果:

4、测试中间输出结果

1)中间层的可视化

卷积神经网络不单单是一个黑盒子。我们接下来看看该模型的一些参数和一些中间输出。首先,我们来看下如何读取网络的结构(每层的名字以及相应层的参数)。
#net.blob对应网络每一层数据,对于每一层,都是四个维度:(batch_size, channel_dim, height, width)
#循环打印每一层名字和相应维度
for layer_name, blob in net.blobs.iteritems():
    print layer_name+'\t'+ str(blob.data.shape)

结果:

#net.params对应网络中的参数(卷积核参数,全连接层参数等),有两个字典值
#net.params[0]是权值(weights),net.params[1]是偏移量(biases)
#权值参数的维度表示是(output_channels, input_channels, filter_height, filter_width)
#偏移量参数的维度表示(output_channels)
#循环打印参数名称,权值参数和偏移量参数的维度
for layer_name, param in net.params.iteritems():
    print layer_name+'\t'+ str(param[0].data.shape),str(param[1].data.shape)

结果:


#这里要将四维数据进行特征可视化,需要一个定义辅助函数    
def vis_square(data):
    
    #数据正则化
    data=(data-data.min())/(data.max()-data.min())
    
    #此处目的是将一个个滤波器按照正方形的样子排列
    #先对shape[0]也就是滤波器数量取平方根,然后取大于等于该结果的正整数
    #比如40个卷积核,则需要7*7的正方形格子(虽然填不满)
    n=int(np.ceil(np.sqrt(data.shape[0])))
    padding=(((0,n**2-data.shape[0]),
              (0,1),(0,1)) #在相邻的卷积核之间加入空白
              +((0,0),)*(data.ndim-3)) #不填充最后一维
    #pad函数声明:pad(array, pad_width, mode, **kwargs),作用是把list在原维度上进行扩展;
    #pad_width是扩充参数,例如参数((3,2),(2,3));
    #(3,2)为水平方向上,上面加3行,下面加2行;
    #(2,3)为垂直方向上,上面加2行,下面加3行;
    #constant是常数填充的意思。
    data=np.pad(data,padding,mode='constant',constant_values=1) #每张小图片向周围扩展一个白色像素
    
    #将卷积核平铺成图片
    data=data.reshape((n,n)+data.shape[1:]).transpose((0,2,1,3)+tuple(range(4,data.ndim+1)))
    data=data.reshape((n*data.shape[1],n*data.shape[3])+data.shape[4:])
    
    plt.imshow(data);plt.axis('off')
filters=net.params['conv1'][0].data #选取conv1的卷积核权值参数
vis_square(filters.transpose(0,2,3,1)) #调用函数显示

结果:


feat = net.blobs['conv1'].data[0,:36] #选取‘conv1’的blob数据,只选择前面36张图片
vis_square(feat)

结果:

feat = net.blobs['pool5'].data[0] #选取pool5的第一个输出结果
vis_square(feat)

结果:


2)直方图显示

feat = net.blobs['fc6'].data[0] #选取fc6的输出数据,这是一个4096维的向量
plt.subplot(2,1,1) #创建2行1列的子图,现在是第1个子图
plt.plot(feat.flat) #平铺向量,图像显示其每一个值
plt.subplot(2,1,2) #现在是第2个子图
_=plt.hist(feat.flat[feat.flat>0],bins=100) #做直方图,总共100根条形

结果:

feat = net.blobs['prob'].data[0] #选取最后一层的输出结果
plt.figure(figsize=(15,3)) #设置图像大小为(15,3),单位是英寸
plt.plot(feat.flat) #平铺向量,图像显示其每一个值

结果:

Out[12]: [<matplotlib.lines.Line2D at 0x331e1438>]

3)测试自己的图片

图片来源: 点击打开链接
#变换图像并将其拷贝到网络
image = caffe.io.load_image(caffe_root+'examples/images/xing.jpg')
net.blobs['data'].data[...]=transformer.preprocess('data',image)

#预测分类结果
net.forward()

#获取输出概率值
output_prob=net.blobs['prob'].data[0]

#将softmax的输出结果按照从大到小排序,并取前5名
top_inds = output_prob.argsort()[::-1][:5]

plt.imshow(image)

print 'probabilities and labels:'
zip(output_prob[top_inds],labels[top_inds]) #zip函数依次取值,然后组合

结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值