膨脹卷積-空洞卷積-Dilated Convolution


膨脹卷積,也叫空洞卷積,Dilated Convolution,也有叫 擴張卷積;

空洞卷積 是 2016在ICLR(International Conference on Learning Representation)上被提出的,本身用在圖像分割領域,被deepmind拿來應用到語音(WaveNet)和NLP領域,它在物體檢測也發揮了重要的作用,對於小物體的檢測十分重要

 

普通卷積 

先來看看 普通卷積 

卷積后需進行池化 pooling,池化除了 降維、提升局部位移魯棒性 等作用外,還有 增大感受野 的作用,

但是在 pooling 時,會丟失一部分信息,特別是一些 細節信息 和 小目標信息,對任務造成一定的影響:

1.在圖像識別任務中,丟失細節可能降低准確率

2.在目標檢測任務中,小目標檢測 受影響較大

3.在語義分割任務中,下采樣后的上采樣無法還原這些信息

 

如果沒有 pooling,感受野 太小,

不利於 在圖像需要全局信息、語音文本需要較長的 sequence 信息依賴 等問題

 

感受野

卷積模塊 輸出結果中 一個元素 對應 輸入層的 區域大小,代表 卷積核 在 圖像上看到的區域大小,感受野 越大,包含的 上下文關系 越多,【通俗理解就是 視野更廣闊了,看問題更全面了 等等】

 

空洞卷積

為了避免 pooling 的影響,提出了 空洞卷積

VS 普通卷積

空洞卷積其實 就是在 普通卷積核中間 插 0,看起來像中間有洞,故稱空洞;

空洞卷積與 普通卷積 參數量 相同;

空洞卷積與 普通卷積 輸出的 feature map 大小相同;

 

膨脹率 

空洞卷積中引入 膨脹率 dilation_rate 的概念,也叫 擴張率,空洞數,

膨脹率 代表 將 原來的一個 元素 擴展到 多少倍,擴展后的 卷積核尺寸 dilation_rate*(kernel_size - 1)+1,

如下圖

a為 普通卷積核為 3x3,感受野 9;

b 膨脹率為 2,原先1個元素變成2個,5x5,感受野 25;

c 膨脹率為 3,原先1個元素變成3個,7x7,感受野 49;

 

保持數據結構不變

pooling 操作一般會改變 數據尺寸,在 圖像分割 領域,下采樣后需上采樣,數據尺寸會發生變化,而空洞卷積只有卷積,沒有池化,可以保持數據結構不變

 

空洞卷積的問題與優化 

柵格效應 Gridding Effect

 

 

這張圖代表了3層空洞卷積,每層在 原始輸入 上 參與計算的 像素個數,可忽略,直接看下面的圖 

 

多個相同膨脹率的空洞卷積堆疊

左側從下往上看,相當於一個卷積網絡,每次卷積采用 膨脹率為 2 的空洞卷積,

右側是卷積后的統計分析,整個圖代表 原始輸入,每個格子代表一個像素,格子里的值代表 3次卷積后,該像素被 計算的次數,

可以看到有些 像素 是沒有參與計算的,造成了大量的信息丟失,影響最終效果,

論文中稱 卷積核 不連續

 

多個不同膨脹率的空洞卷積堆疊

左側膨脹率分別為 1 2 3,右側所有像素都參與計算了,信息利用率大大增強,

同時感受野 等於 上個圖,大於 下個圖(普通卷積)

 

多個普通卷積堆疊

感受野明顯小很多 

 

Hybrid Dilated Convolution(HDC) 

混合膨脹卷積,

空洞卷積會產生 柵格效應,需要 設計 膨脹率 使得卷積核能夠覆蓋所有像素,HDC 用於解決這一問題。

HDC 要求 膨脹率 滿足如下要求

1.滿足公式和約束

Mi 表示 第 i 層 最大 可使用 的 膨脹率,ri 表示 第 i 層的膨脹率, n 表示 膨脹卷積核  的 個數,

下面分別表示 膨脹系數 為 [1 2 5] 和 [1 2 9]

 

2.鋸齒結構

dilated rate設計成了鋸齒狀結構,例如[1, 2, 5, 1, 2, 5]這樣的循環結構 

鋸齒狀本身的性質就比較好的來同時滿足小物體大物體的分割要求(小 dilation rate 來關心近距離信息,大 dilation rate 來關心遠距離信息)。

這樣卷積依然是連續的,依然能滿足VGG組觀察的結論,大卷積是由小卷積的 regularisation 的 疊加。

3.公約數不能大於 1

疊加的膨脹卷積的膨脹率dilated rate不能有大於1的公約數(比如[2, 4, 8]),不然會產生柵格效應

 

下面代碼用於 畫 上面的圖

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap


def dilated_conv_one_pixel(center: (int, int),
                           feature_map: np.ndarray,
                           k: int = 3,
                           r: int = 1,
                           v: int = 1):
    """
    膨脹卷積核中心在指定坐標center處時,統計哪些像素被利用到,
    並在利用到的像素位置處加上增量v
    Args:
        center: 膨脹卷積核中心的坐標
        feature_map: 記錄每個像素使用次數的特征圖
        k: 膨脹卷積核的kernel大小
        r: 膨脹卷積的dilation rate
        v: 使用次數增量
    """
    assert divmod(3, 2)[1] == 1

    # left-top: (x, y)
    left_top = (center[0] - ((k - 1) // 2) * r, center[1] - ((k - 1) // 2) * r)
    for i in range(k):
        for j in range(k):
            feature_map[left_top[1] + i * r][left_top[0] + j * r] += v


def dilated_conv_all_map(dilated_map: np.ndarray,
                         k: int = 3,
                         r: int = 1):
    """
    根據輸出特征矩陣中哪些像素被使用以及使用次數,
    配合膨脹卷積k和r計算輸入特征矩陣哪些像素被使用以及使用次數
    Args:
        dilated_map: 記錄輸出特征矩陣中每個像素被使用次數的特征圖
        k: 膨脹卷積核的kernel大小
        r: 膨脹卷積的dilation rate
    """
    new_map = np.zeros_like(dilated_map)
    for i in range(dilated_map.shape[0]):
        for j in range(dilated_map.shape[1]):
            if dilated_map[i][j] > 0:
                dilated_conv_one_pixel((j, i), new_map, k=k, r=r, v=dilated_map[i][j])

    return new_map


def plot_map(matrix: np.ndarray):
    plt.figure()

    c_list = ['white', 'blue', 'red']
    new_cmp = LinearSegmentedColormap.from_list('chaos', c_list)
    plt.imshow(matrix, cmap=new_cmp)

    ax = plt.gca()
    ax.set_xticks(np.arange(-0.5, matrix.shape[1], 1), minor=True)
    ax.set_yticks(np.arange(-0.5, matrix.shape[0], 1), minor=True)

    # 顯示color bar
    plt.colorbar()

    # 在圖中標注數量
    thresh = 5
    for x in range(matrix.shape[1]):
        for y in range(matrix.shape[0]):
            # 注意這里的matrix[y, x]不是matrix[x, y]
            info = int(matrix[y, x])
            ax.text(x, y, info,
                    verticalalignment='center',
                    horizontalalignment='center',
                    color="white" if info > thresh else "black")
    ax.grid(which='minor', color='black', linestyle='-', linewidth=1.5)
    plt.show()
    plt.close()

def main():
    # bottom to top
    dilated_rates = [1, 2, 3]
    # init feature map
    size = 31
    m = np.zeros(shape=(size, size), dtype=np.int32)
    center = size // 2
    m[center][center] = 1
    # print(m)
    # plot_map(m)

    for index, dilated_r in enumerate(dilated_rates[::-1]):
        new_map = dilated_conv_all_map(m, r=dilated_r)
        m = new_map
    print(m)
    plot_map(m)

if __name__ == '__main__':
    main()

 

 

 

 

 

 

參考資料:

https://www.cnblogs.com/pinking/p/9192546.html  膨脹卷積與IDCNN                      言簡意賅,有圖 有代碼,適合入門

https://www.bilibili.com/video/BV1Bf4y1g7j8?spm_id_from=333.337.search-card.all.click     b站視頻,講得很清楚,特別是 gridding effect 問題 及 HDC 策略

https://blog.51cto.com/u_15072927/4308099                        基本和 上個視頻對應,建議先看視頻再看該文章

 

 

https://blog.csdn.net/qq_27586341/article/details/103131674  膨脹卷積(Dilated convolution)

 

https://blog.csdn.net/qq_35495233/article/details/86638098  NLP進階之(七)膨脹卷積神經網絡

https://zhuanlan.zhihu.com/p/113285797  吃透空洞卷積(Dilated Convolutions)

https://www.zhihu.com/question/54149221/answer/1683243773  如何理解空洞卷積(dilated convolution)?

https://zhuanlan.zhihu.com/p/89425228  空洞(擴張)卷積(Dilated/Atrous Convolution)

 


免責聲明!

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



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