Caffe學習1-圖像識別與數據可視化

本文采用深度學習庫caffe做圖像的識別與分類,所用模型爲caffemodel。
具體參考caffe官網:http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb

#用caffe來進行圖像的識別和各層可視化
# 加載各個模塊,比如python,numpy和matploblib
import numpy as np
import matplotlib.pyplot as plt
# 在notebook裏面顯示圖像
%matplotlib inline

# set display defaults
plt.rcParams['figure.figsize'] = (10, 10)        # 顯示圖像的最大範圍
plt.rcParams['image.interpolation'] = 'nearest'  # 差值方式
plt.rcParams['image.cmap'] = 'gray'  # 灰度空間
#第二步,用來加載caffe
import sys
caffe_root='../../'    #我的路徑是在caffe/example/test路徑下,根據你的情況將caffe_root路徑進行定義
sys.path.insert(0,caffe_root+'python')

import caffe
#如果沒有事先下載了已經訓練好了的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

CaffeNet found

#第三步,設置用CPU來加載Caffe並且加載網絡
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'   #加載了caffe的預訓練模型

#定義網絡
net =  caffe.Net(model_def,model_weights,caffe.TEST)       #用caffe的測試模式,即只是提取特徵,不訓練
#定義轉換也即是預處理函數
#caffe中用的圖像是BGR空間,但是matplotlib用的是RGB空間;再比如caffe的數值空間是[0,255]但是matplotlib的空間是[0,1]。這些都需要轉換過來
#載入imagenet的均值,實際圖像要減去這個均值,從而減少噪聲的影響
mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy')
mu = mu.mean(1).mean(1)  #計算像素的平均值
print 'mean-subtracted values:', zip('BGR', mu)     #打印B、G、R的平均像素值

# 定義轉換輸入的data數值的函數
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})

transformer.set_transpose('data', (2,0,1))  # 分離圖像的RGB三通道
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空間

mean-subtracted values: [(‘B’, 104.0069879317889), (‘G’, 116.66876761696767), (‘R’, 122.6789143406786)]

#第四步,用CPU來進行圖像的分類
#首先,可以resize圖像的大小
net.blobs['data'].reshape(50,3,227,227)   #batchsize=50,三通道,圖像大小是227*227
#第五步,加載圖像
image = caffe.io.load_image(caffe_root + 'examples/00-classification-test/dog.jpg')
traformed_image = transformer.preprocess('data',image)
plt.imshow(image)

dog

#將圖像數據拷貝到內存中並分配給網絡net
net.blobs['data'].data[...] = traformed_image

#分類,這裏用的是caffemodel,這是在imagenet上的預訓練模型,有1000類
output = net.forward()

output_prob = output['prob'][0]                                      #這裏是輸出softmax迴歸向量
print 'predicted class is:', output_prob.argmax()           #找出這個向量裏面值最大的那個標號

predicted class is: 253

#第五步,加載imagenet裏面1000類的標籤
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: n02110806 basenji

#輸出概率較大的前五個物體
top_inds = output_prob.argsort()[::-1][:5]

print 'probailities and labels:'
zip(output_prob[top_inds],labels[top_inds])             #根據概率,輸出排名前五個

probailities and labels:

[(0.81211644, ‘n02110806 basenji’),
(0.098898478, ‘n02087046 toy terrier’),
(0.030348787, ‘n02113023 Pembroke, Pembroke Welsh corgi’),
(0.022625968, ‘n02091032 Italian greyhound’),
(0.015911266, ‘n02113186 Cardigan, Cardigan Welsh corgi’)]

#採用cpu查看一次正向傳播時間
%timeit net.forward()

1 loop, best of 3: 521 ms per loop

#採用gpu查看一次正向的時間
caffe.set_device(0)  # 假如有多塊gpu,選擇第一塊gpu
caffe.set_mode_gpu()
net.forward()  
%timeit net.forward()

10 loops, best of 3: 61.6 ms per loop

#顯示各個層的參數和輸出類型,輸出分別是(batchsize,通道數或者feature map數目,輸出image高,輸出image寬)
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)

#查看參數,存放參數的數據結構是輸出的feature-map數量,輸入的feature-map數量,卷積核大小
#這裏conv3和conv4分開了,分別是192,則192*2=384
#後面只有一個參數的表示偏置b數量
for layer_name,param in net.params.iteritems():
    print layer_name + '\t' + str(param[0].data.shape),str(param[1].data.shape)

conv1 (96, 3, 11, 11) (96,)
conv2 (256, 48, 5, 5) (256,)
conv3 (384, 256, 3, 3) (384,)
conv4 (384, 192, 3, 3) (384,)
conv5 (256, 192, 3, 3) (256,)
fc6 (4096, 9216) (4096,)
fc7 (4096, 4096) (4096,)
fc8 (1000, 4096) (1000,)

#第六步,定義卷積核可視化函數
def vis_square(data):
    """
    將數列(通道數,高度,寬度)可視化爲(高度,寬度),即卷積核可視化。
    """
    #標準化數據normalize
    data = (data-data.min())/(data.max()-data.min())
    #強制濾波器/卷積核數量爲偶數
    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)

#給卷積核命名
    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')         #關閉座標軸
#查看各個層的參數(params)
filters = net.params['conv1'][0].data
vis_square(filters.transpose(0,2,3,1))

convolutional kernals

#可視化數據卷積層的效果圖
feat = net.blobs['data'].data[0,:3]
vis_square(feat)

data layer,B,G,R three channls

#顯示/統計全連接層和prob層
feat = net.blobs['fc7'].data[0]
plt.subplot(2,1,1)         #兩行一列第一個
plt.plot(feat.flat)
plt.subplot(2,1,2)        #兩行一列第二個圖像
a= plt.hist(feat.flat[feat.flat > 0], bins=100)     #統計直方圖

fc7 layer and its histgram

#第七步,統計屬於哪一類的概率,記住imagenet有1000類
feat = net.blobs['prob'].data[0]
plt.figure(figsize=(15,3))
plt.plot(feat.flat)

probability

#第八步,載入網上任意的圖像,統計其特性
#輸入圖像的URL地址
my_image_url ="https://upload.wikimedia.org/wikipedia/commons/b/be/Orang_Utan%2C_Semenggok_Forest_Reserve%2C_Sarawak%2C_Borneo%2C_Malaysia.JPG"

!wget -O image.jpg $my_image_url
#轉換數據
image = caffe.io.load_image("image.jpg")
net.blobs['data'].data[...] = transformer.preprocess('data',image)

net.forward()

out_prob = net.blobs['prob'].data[0]
top_inds = output_prob.argsort()[::-1][:5]

plt.imshow(image)

print 'probabilites and labels:'

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

–2016-05-04 20:57:11– https://upload.wikimedia.org/wikipedia/commons/b/be/Orang_Utan%2C_Semenggok_Forest_Reserve%2C_Sarawak%2C_Borneo%2C_Malaysia.JPG
正在解析主機 upload.wikimedia.org (upload.wikimedia.org)… 198.35.26.112, 2620:0:863:ed1a::2:b
正在連接 upload.wikimedia.org (upload.wikimedia.org)|198.35.26.112|:443… 已連接。
已發出 HTTP 請求,正在等待迴應… 200 OK
長度: 1443340 (1.4M) [image/jpeg]
正在保存至: “image.jpg”

100%[======================================>] 1,443,340 25.8KB/s 用時 80s

2016-05-04 20:58:35 (17.6 KB/s) - 已保存 “image.jpg” [1443340/1443340])

probabilites and labels:

[(0.96807837, ‘n02480495 orangutan, orang, orangutang, Pongo pygmaeus’),
(0.030588904, ‘n02492660 howler monkey, howler’),
(0.00085891597, ‘n02493509 titi, titi monkey’),
(0.00015429019, ‘n02493793 spider monkey, Ateles geoffroyi’),
(7.2596624e-05, ‘n02488291 langur’)]
orang

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章