上一篇博客中介绍了如何使用MATLAB训练和测试数据,这篇博客介绍如何从训练好的模型中提取图像特征,并介绍把卷积层特征可视化方法。
之前提取特征都是用python,尽管用python提取特征很方便,但是感觉MATLAB提取特征更方便,因为博主对MATLAB比较熟悉,对python不太熟悉,,,,,,可视化部分我参考了http://www.2cto.com/kf/201609/550879.html,特征提取是我自己总结的,这个博客里还介绍了权重的可视化,大家自己去拜读一下吧。
开始train(最近博客审核的好慢啊)
1、提取特征
当把图像数据forward之后,所有的数据都存在了blob当中,所以只需要从blob当中把数据提取出来即可,
names=net.blob_names; %网络每一层的名字
featuremap=net.blobs(names{mapnum}).get_data();%获取指定层的特征图,mapnum需要自己指定,既哪一层
把names输出得到结果
这是每一层的名字,featuremap=net.blobs(names{mapnum}).get_data();
featuremap就是指定层的特征图,计算一个featuremap的大小,发现这是一个4维数据:
[m_size,n_size,num,crop]=size(featuremap) %获取特征图大小,长*宽*卷积核个数*通道数
通道数就是上一篇博客里介绍的crop之后的10张图。m_size,n_size,num,crop分别代表feature map的长,宽,卷积核个数和通道数。
如果我们想要提取其中一张crop图的某一个featuremap,怎么办呢?
只需要 feature_map=featuremap(:,:,哪一个featuremap,哪一个crop)。这样就能完成特征提取,最后我会把特征提取的函数代码放在最后。
我们用Alexnet最常用的就是4096,那么怎么提取4096的特征呢,只需要:
featuremap=net.blobs(names{13}).get_data();%13层就是fc7层
结果如下:
一共有4096*10维的特征,其中10就是10张crop图,求平均或者max,或者只需要拿出一个4096就能得到4096维的特征。是不是挺简单的?
下面就是把特征图可视化出来,最后我会把可视化代码贴上去,这里可视化分为两部分,一个是部分可视化,指定哪一层,哪一个crop图可视化。第二个是全部可视化,只需要指定哪一层,把所有的featuremap可视化出来,效果图(指定第二层,第一张crop图,既卷积层的第一个crop的96个featuremap):
全部可视化效果:
知道为什么是960个featuremap吗?对,因为是96*10,96是卷积核数量,10是10个crop图,所以是960个featuremap。
代码如下:
function [ ] = feature_partvisual( net,mapnum,crop_num ) %三个参数分别代表网络结构,第几层特征图,第几张crop_num,部分可视化
names=net.blob_names;
featuremap=net.blobs(names{mapnum}).get_data();%获取指定层的特征图
[m_size,n_size,num,crop]=size(featuremap); %获取特征图大小,长*宽*卷积核个数*通道数
featuremap(:,:,1,crop_num); %第多少个卷积核,第几个crop_num的特征
row=ceil(sqrt(num));%行数
col=row;%列数
feature_map=zeros(m_size*row,n_size*col);
cout_map=1;
for i=0:row-1
for j=0:col-1
if cout_map<=num
feature_map(i*m_size+1:(i+1)*m_size,j*n_size+1:(j+1)*n_size)=(mapminmax(featuremap(:,:,cout_map,crop_num),0,1)*255)';
cout_map=cout_map+1;
end
end
end
imshow(uint8(feature_map));
str=strcat('feature map num:',num2str(cout_map-1));
title(str)
end
全部可视化:
function [ ] = feature_fullvisual( net,mapnum )
names=net.blob_names;
featuremap=net.blobs(names{mapnum}).get_data();%获取指定层的特征图
[m_size,n_size,num,crop]=size(featuremap) %获取特征图大小,长*宽*卷积核个数*图片个数
row=crop;%行数
col=num;%列数
feature_map=zeros(m_size*row,n_size*col);
for i=0:row-1
for j=0:col-1
feature_map(i*m_size+1:(i+1)*m_size,j*n_size+1:(j+1)*n_size)=(mapminmax(featuremap(:,:,j+1,i+1),0,1)*255)';
end
end
figure
imshow(uint8(feature_map))
str=strcat('feature map num:',num2str(row*col));
title(str)
end
主测试函数(包括了类别测试的代码)
clear;
clc;
addpath ../../../../matlab
net = init_net(); %初始化网络
%im_data = caffe.io.load_image('test0020.jpg');
im_data=imread('test0001.jpg'); %读入图像
%imshow(im_data);
input_data = {prepare_image(im_data)}; %准备数据,需要裁剪时裁剪数据
%不裁剪时使用reshape操作
% net.blobs('data').reshape([227 227 3 1]); % 当读进来一幅图像,不做裁剪操作时,这样使用
% net.reshape();
tic
res = net.forward(input_data); %前向传播结果
mapnum=2; %第几层
crop_num=1; %第几张crop_num
feature_partvisual( net,mapnum, crop_num ); %可视化部分feature map
feature_fullvisual(net,mapnum); %可视化全部的feature map
res=res{1};
res = mean(res, 2); % take average scores over 10 crops 求裁剪的10个batch平均值
toc
[~, idx]= max(res); %找到最大的一个概率值
disp(idx-1); %输出类别标签
caffe.reset_all(); %关闭所有的网络
参考博客:http://www.2cto.com/kf/201609/550879.html