上一篇博客中介紹了如何使用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(); %關閉所有的網絡