imagenet-vgg-verydeep-19.mat 格式解析

imagenet-vgg-verydeep-19.mat 格式解析

知乎的文章排版真是......(欲哭無淚),因此文章就先發在博客啦~粘貼在這裡以供預覽:

VGG pretrained模型地址:

vlfeat.org/matconvnet/p

下載地址:

vlfeat.org/matconvnet/m

不過我用的這個beta版本的不太一樣,地址

vlfeat.org/matconvnet/m

但是分析過程是一樣的

今天在玩Stanford CS20SI公開課里的一個神經網路style_transfer小模型的時候,用到了vgg pretrained模型,然而,代碼里獲取weight和bias是這麼寫的:

W = vgg_layers[0][layer][0][0][2][0][0]

b = vgg_layers[0][layer][0][0][2][0][1]

摔!這也沒注釋,完全看不懂啊!

雖然可以查到vgg的模型信息(下面有個layer configuration的SVG圖),可是對應不上這些索引啊!

於是把模型下載下來,在ipython里一步一步解析:

首先,導入scipy.io包:

import scipy.io

然後,用loadmat載入模型(載入matlab文件格式的方法):

vgg = scipy.io.loadmat(imagenet-vgg-verydeep-19.mat)

接下來就是探索格式了:

首先,看一下導入後的模型類型:

type(vgg)

嗯,不出所料,是個dict,scipy.io.loadmat的官方文檔也有說明,返回類型是個dict.

然後就是看一下有哪些key啦:

vgg.keys()

輸出有

dict_keys([__header__, __version__, __globals__, layers, classes, normalization])

嗯,看來前三項是meta信息,後面的三樣東西是我們需要的,看名字應該分別是層參數,分類信息,正則化參數(像素平均值)

那麼,先看看layers層:

layers = vgg[layers]

輸出有一大坨,不過看頭部足以分析:

array([[ array([[ (array([[ array([[[[ 0.39416704, -0.08419707, -0.03631314, ...

頂級array有兩個[[所以是兩維,每一個維數的元素是array,array內部還有維數,因此可以看出,想要索引出元素確實需要很多index,那麼看一下shape:

layers.shape

輸出是

(1, 43)

說明雖然有兩維,但是第一維是」虛的」,也就是只有一個元素,我們index進去:

layers = layers[0]

根據模型可以知道,這43個元素其實就是對應模型的43層信息(conv1_1,relu,conv1_2…),那麼看一層就足以,而且我們現在得到了一個有用的index,那就是layer

layers[layer]

其中layer是layer參數,範圍0-42,我們選0看看:

layer = layers[0]

從輸出可以看出尾部有dtype信息,這個比較重要,記錄了元素的標籤:

dtype=[(weights, O), (pad, O), (type, O), (name, O), (stride, O)]

可以看出頂層的array有5個元素,分別是weight(含有bias), pad(填充元素,無用), type, name, stride信息,然後繼續看一下shape信息,

layer.shape

輸出是:

(1, 1)

說明雖然有兩維,但是這兩維都是」虛的」,也就是只有一個元素,我們直接兩次index進去,應該會得到一個包含5中信息的array

layer = layer[0][0]

現在layer已經是」裸」的了,直接看看len

len(layer)

輸出是

5

果然不出所料,那麼已經很清楚了,對應上面的dtype說明,很容易得到weight,bias之類信息,比如layer的name,是第4個(從0開始索引),那麼:

name = layer[3]

輸出是

array([conv1_1],

dtype=<U7)

果然拿到了name信息,但是這是一個array,想拿到字元串還要再index進去:

name = name[0]

這次輸出就是一個字元串元素了,』conv1_1′,看來解析已經成功了,其他如法炮製,例如weight(含有bias)

weight = layer[0]

看一下weight的shape:

weight.shape

輸出是:

(1, 2)

再次說明第一維是」虛的」,index進去:

weight = weight[0]

注意,這裡的weight是廣義的weight,也就是包含通常我們說的weight和bias,所以,分別拿到這兩個元素還要再解開一次:

weight, bias = weight

至此,已經完成了第0層的name, weight, bias解析,那麼其他層也一樣,改變layer的index即可,但是要注意的是,這是conv層的解析,relu層,fc層有所不同,不過原理一樣,在ipython里探索即可.

所以,根據上面總結出layer的name的index順序

name = vgg[layers(字典key)][0(去掉"虛"的維,相當於np.squeeze)][layer(層索引)][0][0(連續兩次去掉虛的維度)][3(weigh,pad,type,name,stride5類信息的索引,從0開始)][0(去掉"虛"的維,相當於np.squeeze)]

weight, bias的index順序

weight, bias = vgg[layers(字典key)][0(去掉"虛"的維,相當於np.squeeze)][layer(層索引)][0][0(連續兩次去掉虛的維度)][0(weigh, pad, type, name, stride5類信息的索引,從0開始)][0(去掉"虛"的維,相當於np.squeeze)]

p.s. 感覺探索用了很多笨方法,但是整套下來基本思路倒是學到不少東西~

推薦閱讀:

TAG:TensorFlow | 深度學習DeepLearning |