天天看點

詳解FCN模型中每一層的輸出及可視化操作

對于FCN模型的搭建以及訓練自己的資料集,其實并不是特别難。可以參考FCN訓練自己的資料集。可能更多的人想知道FCN每一層輸出的結果是什麼。這篇部落客要介紹的是對FCN每一層輸出進行可視化操作。

  1. 檢視FCN總體架構

    先打開工具netcope,如果打不開點選這個netscope然後打開fcn-master2\voc-fcn32s下的train.prototxt檔案,将train.prototxt檔案内容複制到網頁左側編輯框後,shift+enter,就可以直接顯示網絡結構。

    詳解FCN模型中每一層的輸出及可視化操作
  2. 檢視每一層輸出的結構

    打開fcn-master2\voc-fcn32s下infer.py檔案,在原代碼的最後寫上如下代碼。

for layer_name, blob in net.blobs.iteritems():
    print layer_name + '\t' + str(blob.data.shape)
           

運作程式,可以看到輸出的結果如下

data	(1L, 3L, 375L, 500L)                                       
data_input_0_split_0	(1L, 3L, 375L, 500L)
data_input_0_split_1	(1L, 3L, 375L, 500L)
conv1_1	(1L, 64L, 573L, 698L)                              
conv1_2	(1L, 64L, 573L, 698L)
pool1	(1L, 64L, 287L, 349L)
conv2_1	(1L, 128L, 287L, 349L)
conv2_2	(1L, 128L, 287L, 349L)
pool2	(1L, 128L, 144L, 175L)
conv3_1	(1L, 256L, 144L, 175L)
conv3_2	(1L, 256L, 144L, 175L)
conv3_3	(1L, 256L, 144L, 175L)
pool3	(1L, 256L, 72L, 88L)
conv4_1	(1L, 512L, 72L, 88L)
conv4_2	(1L, 512L, 72L, 88L)
conv4_3	(1L, 512L, 72L, 88L)
pool4	(1L, 512L, 36L, 44L)
conv5_1	(1L, 512L, 36L, 44L)
conv5_2	(1L, 512L, 36L, 44L)
conv5_3	(1L, 512L, 36L, 44L)
pool5	(1L, 512L, 18L, 22L)
fc6	(1L, 4096L, 12L, 16L)
fc7	(1L, 4096L, 12L, 16L)
score_fr	(1L, 5L, 12L, 16L)
upscore	(1L, 5L, 416L, 544L)
score	(1L, 5L, 375L, 500L)
           

從輸出結果可以看出輸入的是500 x 375 x 3的圖檔,第一層卷積後輸出的是698 x 573 x 64的特征圖。可能有很多人疑惑為什麼第一層卷積層分為conv1_1和conv1_2。因為FCN是基于VGG16的結構,VGG16總共是有16層,第一層分為conv1_1和conv1_2因為沒有改變圖像的大小以及卷積核數,是以兩個層合并稱為第一層。後面的層數是同樣的道理,具體的可以參考部落格詳解VGG16模型。

  1. 可視化資料函數

    在fcn-master2\voc-fcn32s下建立vis_square.py檔案,複制代碼

# -*- coding: utf-8 -*
####定義輔助函數來進行可視化中間層特征
import numpy as np
from PIL import Image
import scipy.misc
import pylab
import matplotlib.pyplot as plt
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
    # 此處目的是将一個個濾波器按照正方形的樣子排列
    # 先對shape[0]也就是濾波器數量取平方根,然後取大于等于該結果的正整數
    # 比如40個卷積核,則需要7*7的正方形格子(雖然填不滿)
    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進行padding
               + ((0, 0),) * (data.ndim - 3))
 # don't pad the last dimension (if there is one)   如果最後最後一維是1不進行擴充
    data = np.pad(data, padding, mode='constant', constant_values=1)
 # pad函數聲明:pad(array, pad_width, mode, **kwargs),作用是把list在原次元上進行擴充;
    # pad_width是擴充參數,例如參數((3,2),(2,3));
    # 其中(3,2)為水準方向上,上面加3行,下面加2行;
    # (2,3)為垂直方向上,上面加2行,下面加3行;
    # constant是常數填充的意思。# 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:])

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

           

儲存退出,這代碼的功能是用來顯示每一層輸出的圖像。

然後在infer.py檔案上添加子產品

import vis_square
import pylab
           
  1. 可視化第一層卷積核圖像

在代碼的最後寫上如下代碼

filters = net.params['conv1_1'][0].data
vis_square.vis_square(filters.transpose(0, 2, 3, 1))
           

輸出的是第一層卷積核模闆的圖像,這卷積核圖像是通過訓練模型得出來的。FCN的第一層共有64個卷積核,是以輸出的是64個卷積核圖像。

詳解FCN模型中每一層的輸出及可視化操作
  1. 可視化第一層圖像輸出

    先将第4步的代碼注釋,然後在寫上如下代碼

feat = net.blobs['conv1_1'].data[0, :]
vis_square.vis_square(feat)
           

輸出的結果為下圖所示。因為有64個卷積核,是以輸出的是64張特征圖。

詳解FCN模型中每一層的輸出及可視化操作
  1. 可視化第一層池化後的資料圖像

    同樣先注釋第5步的代碼,然後在寫上如下代碼。

feat = net.blobs['pool1'].data[0]
vis_square.vis_square(feat)
           
  1. 輸出第一層圖像的資料

    圖像就是一組資料組成的,如果想要得出第一層資料的話,可以下上如下代碼

print('conv1_1')
print net.blobs['conv1_1'].data[0]
           

輸出的結果為如下圖所示。

詳解FCN模型中每一層的輸出及可視化操作
  1. 總結

    以上介紹的是第一層圖像的可視化操作。如果想要其它層圖像可視化操作,隻需要修改net.blobs[‘ ’]中每層網絡結構的名稱即可。如檢視第5層資料。代碼為

feat = net.blobs['conv5_1'].data[0, :]
vis_square.vis_square(feat)
           

到此所有的可視化操作已經介紹完了,相信通過對每一層資料的可視化操作,能夠更加深刻的了解FCN模型。