Caffe官方教程翻译(10):Editing model parameters
前言
最近打算重新跟著官方教程學習一下caffe,順便也自己翻譯了一下官方的文檔。自己也做了一些標注,都用斜體標記出來了。中間可能額外還加了自己遇到的問題或是運行結果之類的。歡迎交流指正,拒絕噴子!
官方教程的原文鏈接:
http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/net_surgery.ipynb
Net Surgery
通過編輯模型參數,可以將caffe網絡轉換成符合你特定需求的網絡。在pycaffe中,模型的數據、差值以及參數都是公開的。
開干吧!
Designer Filters
為了說明如何加載,操作和保存參數,我們把自己的濾波器設計為一個簡單的網絡,其只有一個卷積層。這個網絡有兩個blob,輸入數據層data和卷積輸出層conv。以及一個參數,表示卷積層上權重和偏置參數的conv。
# Load the net, list its data and params, and filter an example image. caffe.set_mode_cpu() net = caffe.Net('net_surgery/conv.prototxt', caffe.TEST) print("blobs {}\nparams {}".format(net.blobs.keys(), net.params.keys()))# load image and prepare as a single input batch for Caffe im = np.array(caffe.io.load_image('images/cat_gray.jpg', color=False)).squeeze() plt.title('original image') plt.imshow(im) plt.axis('off')im_input = im[np.newaxis, np.newaxis, :, :] net.blobs['data'].reshape(*im_input.shape) net.blobs['data'].data[...] = im_input blobs ['data', 'conv'] params ['conv']卷積層的權重都是由高斯噪聲初始化而來,而偏置則直接初始化為0.這些隨機濾波器給出的結果有點類似邊緣檢測的效果。
# helper show filter outputs def show_filters(net):net.forward()plt.figure()filt_min, filt_max = net.blobs['conv'].data.min(), net.blobs['conv'].data.max()for i in range(3):plt.subplot(1,4,i+2)plt.title("filter #{} output".format(i))plt.imshow(net.blobs['conv'].data[0, i], vmin=filt_min, vmax=filt_max)plt.tight_layout()plt.axis('off')# filter the image with initial show_filters(net)增加濾波器的權重也會相應地增加其輸出。
# pick first filter output conv0 = net.blobs['conv'].data[0, 0] print("pre-surgery output mean {:.2f}".format(conv0.mean())) net.params['conv'][1].data[0] = 1. net.forward() print("post-surgery output mean {:.2f}".format(conv0.mean())) pre-surgery output mean -0.02 post-surgery output mean 0.98改變濾波器的權重更令人興奮,因為我們可以分配任意的卷積核,比如高斯模糊、Sobel邊緣檢測算子,等等。一下操作將第0個濾波器的內核變為了高斯模糊,第1和第2個濾波器的內核變為了Sobel水平和垂直邊緣檢測算子。
看看第0個濾波器的輸出如何模糊處理的,第1個如何提取水平邊緣,第2個如何提取垂直邊緣。
通過調整網絡,我們可以跨網絡移植參數,通過自定義的每個對參數的操作進行規范化,并根據自己的方案進行轉換。
Casting a Classifier into a Fully Convolutional Network
我們使用caffe中的ImageNet模型——“CaffeNet”進行實驗,并將其轉換為一個完全的卷積網絡,以便對較大的輸入數據進行高效、密集的推理。這個模型生成的分類圖譜包含了給定的輸入尺寸,而不是單個分類的結果。特別是輸入為451××451,8××8的分類圖譜只需要3倍的時間就可以把輸出提高64倍。這里,我們通過撤銷重疊感受區域的計算,提升了卷積神經網絡本身的高效性。
為此,我們將CaffeNet的InnerProduct矩陣內積層換成了卷積層。這是唯一的改變:其他層的類型都與空間大小無關。卷積層是平移不變的,激活層是對每個元素的點積,等等。當通過fc6-conv卷積層進行計算之后,fc6內積層(全連接層)變為在pool5上的步長為1的6××6的卷積核。回到圖像空間,這里給出了對區域為227××227的圖像,對應每個像素步長為32的分類結果。請記住輸出/接收區域大小的計算公式,output = (input - kernel_size) / stride + 1,并通過下面的注釋理解。
這個兩個網絡的結構的唯一差異就是:將全連接層(內積層)換成卷積核(濾波器)尺寸為6××6的卷積層,因為參考分類器模型將pool5的36個元素作為輸入,并且以步長為1進行分類。請注意,由于被修改的部分層被重命名了,所以在加載預訓練模型時,caffe不會盲目地加載舊參數。
# Load the original network and extract the fully connected layers' parameters. net = caffe.Net('../models/bvlc_reference_caffenet/deploy.prototxt', '../models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel', caffe.TEST) params = ['fc6', 'fc7', 'fc8'] # fc_params = {name: (weights, biases)} fc_params = {pr: (net.params[pr][0].data, net.params[pr][1].data) for pr in params}for fc in params:print '{} weights are {} dimensional and biases are {} dimensional'.format(fc, fc_params[fc][0].shape, fc_params[fc][1].shape) fc6 weights are (4096, 9216) dimensional and biases are (4096,) dimensional fc7 weights are (4096, 4096) dimensional and biases are (4096,) dimensional fc8 weights are (1000, 4096) dimensional and biases are (1000,) dimensional考慮到內積參數的形狀。權重參數的尺寸為輸入尺寸××輸出尺寸,而偏置參數的尺寸是輸出的尺寸。
# Load the fully convolutional network to transplant the parameters. net_full_conv = caffe.Net('net_surgery/bvlc_caffenet_full_conv.prototxt', '../models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel',caffe.TEST) params_full_conv = ['fc6-conv', 'fc7-conv', 'fc8-conv'] # conv_params = {name: (weights, biases)} conv_params = {pr: (net_full_conv.params[pr][0].data, net_full_conv.params[pr][1].data) for pr in params_full_conv}for conv in params_full_conv:print '{} weights are {} dimensional and biases are {} dimensional'.format(conv, conv_params[conv][0].shape, conv_params[conv][1].shape) fc6-conv weights are (4096, 256, 6, 6) dimensional and biases are (4096,) dimensional fc7-conv weights are (4096, 4096, 1, 1) dimensional and biases are (4096,) dimensional fc8-conv weights are (1000, 4096, 1, 1) dimensional and biases are (1000,) dimensional卷積層的權重參數排列在output ×× input ×× height ×× width維度中。為了將內積的權重參數映射到卷積核上,我們可以將內積權重向量展開,放到channel ×× height ×× width的濾波器矩陣當中,單實際上這些矩陣在內存中(作為行主要陣列)是相同的,因此我們可以直接分配它們。
卷積層的偏差值依然與原來內積層的偏差值相同。
接下來開始移植!
接下來,保存新的模型權重。
net_full_conv.save('net_surgery/bvlc_caffenet_full_conv.caffemodel')最后,讓我們用前面示例的貓圖片來制作分類圖,并將“tiger cat”這一類的置信率可視化為概率熱圖。這里在451 ×× 451的輸入圖片的重疊區域上給出8-by-8的預測結果。
import numpy as np import matplotlib.pyplot as plt %matplotlib inline# load input and configure preprocessing im = caffe.io.load_image('images/cat.jpg') transformer = caffe.io.Transformer({'data': net_full_conv.blobs['data'].data.shape}) transformer.set_mean('data', np.load('../python/caffe/imagenet/ilsvrc_2012_mean.npy').mean(1).mean(1)) transformer.set_transpose('data', (2,0,1)) transformer.set_channel_swap('data', (2,1,0)) transformer.set_raw_scale('data', 255.0)# make classification map by forward and print prediction indices at each location out = net_full_conv.forward_all(data=np.asarray([transformer.preprocess('data', im)])) print out['prob'][0].argmax(axis=0) # show net input and confidence map (probability of the top prediction at each location) plt.subplot(1, 2, 1) plt.imshow(transformer.deprocess('data', net_full_conv.blobs['data'].data[0])) plt.subplot(1, 2, 2) plt.imshow(out['prob'][0,281]) [[282 282 281 281 281 281 277 282][281 283 283 281 281 281 281 282][283 283 283 283 283 283 287 282][283 283 283 281 283 283 283 259][283 283 283 283 283 283 283 259][283 283 283 283 283 283 259 259][283 283 283 283 259 259 259 277][335 335 283 259 263 263 263 277]] <matplotlib.image.AxesImage at 0x7f163dc96d10>這個分類預測結果給出了多種不同結果:比如282對應“tiger cat”,281對應“tabby”,283對應“persian”,等等,其他結果還對應了其他一些哺乳類動物。
通過這種方式,全連接層可以被提取為圖像上的密集特征(詳情查看net_full_conv.blobs['fc6'].data),也許這甚至比分類圖本身更有用。
注意,這個模型不是完全適合與華東窗口檢測法,因為它是針對整幅圖像的分類而訓練的。盡管如此,它依然可以工作得很棒。滑動窗口法訓練和微調都可以通過定義滑動窗口的ground truth和loss來完成,從而為每個位置制作loss圖譜,并像往常一樣解決。(這是給讀者的練習)
總結
以上是生活随笔為你收集整理的Caffe官方教程翻译(10):Editing model parameters的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用神经网络拟合曲线(MATLAB/Py
- 下一篇: 自适应中值滤波及实现