深度學習Caffe實戰筆記(10)Windows Caffe使用MATLAB介面提取和視覺化特徵
上一篇部落格中介紹瞭如何使用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(); %關閉所有的網路