Caffe學習筆記4圖像特征進行可視化


 

Caffe學習筆記4圖像特征進行可視化

本文為原創作品,未經本人同意,禁止轉載,禁止用於商業用途!本人對博客使用擁有最終解釋權

 

歡迎關注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing/

 

這篇文章主要參考的是http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb

可以算是對它的翻譯的總結吧,它可以算是學習筆記2的一個發展,2是介紹怎么提取特征,這是介紹怎么可視化特征

1、准備工作

首先安裝依賴項

pip install cython

pip install h5py

pip install ipython

pip install leveldb

pip install matplotlib

pip install networkx

pip install nose

pip install numpy

pip install pandas

pip install protobuf

pip install python-gflags

pip install scikit-image

pip install scikit-learn

pip install scipy

接下來的操作都是在ipython中執行的,在ipython中用!表示執行shell命令,用$表示將python的變量轉化為shell變量。通過這兩種符號便可以實現shell命令和ipython的交互。

Ipython可以在終端運行,但是為了方便我們使用的是ipython notebook,這個玩意的介紹網上有很多的資源,這里就不贅述了,所以還要在你的主機上面配置ipython notebook

2、開始

2.1初始化並加載caffe

在終端輸入

ipython notebook

新建一個文件

 

在終端輸入代碼,這里shift+enter表示運行代碼,接下來每一個代碼段輸入完成后,運行一下!

# set up Python environment: numpy for numerical routines, and #matplotlib for plotting

import numpy as np

import matplotlib.pyplot as plt

# display plots in this notebook

%matplotlib inline

調入numpy子程序和matplotlib.pyplot(用於畫圖) 子程序,並將它們分別命名為np和plt

# set display defaults

plt.rcParams['figure.figsize'] = (10, 10) # large images

plt.rcParams['image.interpolation'] = 'nearest' # don't interpolate: show #square pixels

plt.rcParams['image.cmap'] = 'gray' # use grayscale output rather than #a (potentially misleading) color heatmap

設置顯示圖片的一些默認參數大小最大,圖片插值原則為最近鄰插值,圖像為灰度圖

# The caffe module needs to be on the Python path;

# we'll add it here explicitly.

import sys

caffe_root = '/home/wangshuo/caffe/' # this file should be run from {caffe_root}/examples (otherwise change this line)

sys.path.insert(0, caffe_root + 'python')

 

import caffe

# If you get "No module named _caffe", either you have not built pycaffe #or you have the wrong path.

加載caffe,把caffe的路徑添加到當前的python路徑下面來,如果沒有添加路徑,則會在python的路徑下進行檢索,會報錯,caffe模塊不存在。

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

加載模型,這個模型在學習筆記1的時候已經下載過了,如果沒有下載該模型可以用命令行

./examples/imagenet/get_caffe_reference_imagenet_model.sh

這里注意該模型的大小有233M左右,聯網下載可能不全,注意查看,是個坑注意躲避!

2.2加載網絡模型

設置為cpu工作模式並加載網絡模型

caffe.set_mode_cpu()

 

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, # defines the structure of the model

model_weights, # contains the trained weights

caffe.TEST) # use test mode (e.g., don't perform dropout)

model_def:定義模型的結構文件

model_weights:訓練的權重

# load the mean ImageNet image (as distributed with Caffe) for subtraction

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)

 

# create transformer for the input called 'data'

transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})

 

transformer.set_transpose('data', (2,0,1)) # move image channels to outermost dimension

transformer.set_mean('data', mu) # 各個通道的像素值減去圖像均值

transformer.set_raw_scale('data', 255) # 設置灰度級為[0,255]而不是[0,1]

transformer.set_channel_swap('data', (2,1,0)) # 把RGB轉為BGR

這段是設置輸入的進行預處理,調用的是caffe.io.Transformer來進行預處理,這些預處理步驟是獨立於其他的caffe部分的,所以可以使用傳統的算法進行處理。

在caffe的默認設置中,使用的是BGR圖像格式進行處理。像素的級數為[0,255],然后對這些圖片進行預處理是減去均值,最后通道的信息會被轉到第一個維度上來。

但是在matplotlib中加載的圖片像素灰度級是[0,1]之間,且其通道數是在最里層的維度上的RGB格式故需要以上的轉換

2.3CPU分類

# set the size of the input (we can skip this if we're happy

# with the default; we can also change it later, e.g., for different batch sizes)

net.blobs['data'].reshape(50, # 批次大小

3, # 3-channel (BGR) images

227, 227) # image size is 227x227

加載一個圖片

image = caffe.io.load_image(caffe_root + 'examples/images/cat.jpg')

transformed_image = transformer.preprocess('data', image)

plt.imshow(image)

在這里運行完之后正常應該顯示一張圖片,然而並沒有,具體看問題1

現在開始分類

# copy the image data into the memory allocated for the net

net.blobs['data'].data[...] = transformed_image

 

### perform classification

output = net.forward()

 

output_prob = output['prob'][0] # the output probability vector for the first image in the batch

 

print 'predicted class is:', output_prob.argmax()#分類輸出最大概率的類別

輸出:predicted class is: 281 

第281類

但是我們需要更加准確地分類標簽,因此加載分類標簽

# load ImageNet labels

labels_file = caffe_root + 'data/ilsvrc12/synset_words.txt'

if not os.path.exists(labels_file):

!../data/ilsvrc12/get_ilsvrc_aux.sh

 

labels = np.loadtxt(labels_file, str, delimiter='\t')

 

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

輸出:output label: n02123045 tabby, tabby cat

判斷准確,再看看把它判斷成其他類別的輸出概率:

# sort top five predictions from softmax output

top_inds = output_prob.argsort()[::-1][:5] # reverse sort and take five largest items

 

print 'probabilities and labels:'

zip(output_prob[top_inds], labels[top_inds])

輸出:

probabilities and labels:

[(0.31243637, 'n02123045 tabby, tabby cat'),

(0.2379719, 'n02123159 tiger cat'),

(0.12387239, 'n02124075 Egyptian cat'),

(0.10075711, 'n02119022 red fox, Vulpes vulpes'),

(0.070957087, 'n02127052 lynx, catamount')]

可以看到最小的置信概率下輸出的標簽也比較明智

2.4切換到GPU模式

計算分類所用的時間,並把它和gpu模式比較

%timeit net.forward()

選擇GPU模式

caffe.set_device(0) # if we have multiple GPUs, pick the first one

caffe.set_mode_gpu()

net.forward() # run once before timing to set up memory

%timeit net.forward()

3查看中間的輸出

在每一層中我們主要關注的是激活的形狀,它的典型格式為,批次,第二個是特征數,第三個第四個是每個神經元中圖片的長寬

# for each layer, show the output shape

for layer_name, blob in net.blobs.iteritems():

print layer_name + '\t' + str(blob.data.shape)

查看每一層的輸出形狀

輸出:

data    (50, 3, 227, 227)

conv1    (50, 96, 55, 55)

pool1    (50, 96, 27, 27)

norm1    (50, 96, 27, 27)

conv2    (50, 256, 27, 27)

pool2    (50, 256, 13, 13)

norm2    (50, 256, 13, 13)

conv3    (50, 384, 13, 13)

conv4    (50, 384, 13, 13)

conv5    (50, 256, 13, 13)

pool5    (50, 256, 6, 6)

fc6    (50, 4096)

fc7    (50, 4096)

fc8    (50, 1000)

prob    (50, 1000)

再看看參數的結構,參數結構是被另外一個函數定義的選擇輸出的類型,0代表權重,1代表偏差,權重有4維特征(輸出的通道數,輸入通道數,濾波的高,濾波的寬),偏差有一維(輸出的通道)

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):

"""Take an array of shape (n, height, width) or (n, height, width, 3)

and visualize each (height, width) thing in a grid of size approx. sqrt(n) by sqrt(n)"""

 

# normalize data for display

data = (data - data.min()) / (data.max() - data.min())

 

# force the number of filters to be square

n = int(np.ceil(np.sqrt(data.shape[0])))

padding = (((0, n ** 2 - data.shape[0]),

(0, 1), (0, 1)) # add some space between filters

+ ((0, 0),) * (data.ndim - 3)) # don't pad the last dimension (if there is one)

data = np.pad(data, padding, mode='constant', constant_values=1) # pad with ones (white)

 

# tile the filters into an image

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:])

ipt.show()

plt.imshow(data); plt.axis('off')

顯示第一個卷積層的特征

# the parameters are a list of [weights, biases]

filters = net.params['conv1'][0].data

vis_square(filters.transpose(0, 2, 3, 1))

 

遇到問題

在運行plt.imshow(image)之后應該顯示相應的圖片,最后沒有顯示,這里有一個問題就是,需要在導入nump的時候也要導入pylab

import pylab as ipt

在顯示之前添上

ipt.show()

所以問題1的答案為

image = caffe.io.load_image(caffe_root + 'examples/images/cat.jpg')

transformed_image = transformer.preprocess('data', image)

ipt.show()

plt.imshow(image)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM