CNN的輸入輸出運算過程及其Pytorch實現

0. 卷積神經網絡的結構

在這裏插入圖片描述如上圖所示,一個卷積神經網絡由若干卷積層、池化層、全連接層組成。我們可以通過對其中要素的重組來構成不同的卷積神經網絡。構成不同卷積神經網絡的公式爲:
INPUT>[[CONV]N>POOL?]M>[FC]KINPUT -> [[CONV]*N -> POOL?]*M -> [FC]*K
以上圖爲例,其結構爲:
INPUT>[[CONV]1>POOL]2>[FC]1INPUT -> [[CONV]*1 -> POOL]*2 -> [FC]*1

1. 卷積神經網絡的工作原理

卷積神經網絡用於圖像處理比較多,但在處理圖像的時候也是將其放在數字張量中進行處理,所以CNN也可直接用於處理數據。關於圖像的處理過程可以參考零基礎入門深度學習(4) - 卷積神經網絡,更加直觀的可以參考李宏毅深度學習筆記(十一)CNN(卷積神經網絡)

我們着重說一下對數據的處理,拿使用CNN實現C-MAPSS數據集裏面的剩餘壽命預測(Pytorch)這篇博文中的數據集來舉例,它有25個特徵,我們取它的第一條訓練軌跡(長度爲192)構成的一個張量(192,25),然後用一個大小爲50的滑動窗口進行取值操作,最後這個張量變成了(142,50,25),可以看作142張大小爲(50,25)的單通道圖片。如果設計一個卷積神經網絡結構爲:
INPUT>CONV>POOL>FCINPUT -> CONV->POOL->FC
且其中:

				in_channels=1,  # 輸入卷積層的圖片通道數
                out_channels=20,  # 輸出的通道數
                kernelSize=3,  # 卷積核的大小,長寬相等,3*3
                stride=1,  # 滑動步長爲1
                padding=2  # 在輸入張量周圍補的邊
                poolKernelSize=2 # 池化層的filters的大小2*2

在給CNN輸入的時候要將(142,50,25)一個一個輸入,即每次輸入(1,50,25),輸入142次,如果在Pytorch裏面選用Conv2d就得先將(142,50,25)變爲(142,1,50,25),這裏的1代表它是單通道,然後在一個一個輸入(1,1,50,25),經過如上所設計的CNN之後就會變成(1,1,26,13)。計算方法如下:
W0W_0H0H_0代表輸入的寬度和高度,W1W_1H1H_1代表輸出的寬度和高度,則
W1=((W0kernelSize+2padding)/stride+1)/poolKernelSizeW_1=((W_0-kernelSize+2*padding)/stride+1)/poolKernelSize
=((503+22)/1+1)/2=26=((50-3+2*2)/1+1)/2=26

H1=((H0kernelSize+2padding)/stride+1)/poolKernelSizeH_1=((H_0-kernelSize+2*padding)/stride+1)/poolKernelSize
=((253+22)/1+1)/2=13=((25-3+2*2)/1+1)/2=13
即輸入(1,1,50,25),輸出(1,20,26,13),其中1—>20是通道數的變化。

但是不管是要進行分類任務還是迴歸任務,我們需要的輸出都不會是這種四維的形式(1,20,26,13),所以要加一個全連接層,使得輸出爲我們想要的形式,在全連接層之前還要進行flatten操作,將(1,20,26,13)轉化成(202613,1),這樣全連接層的輸入爲(202613,1),輸出爲(1,1),當然也可以設爲其他形式。

2.Pytorch實現

還是拿使用CNN實現C-MAPSS數據集裏面的剩餘壽命預測(Pytorch)來說:

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(
            torch.nn.Conv2d(  # 輸入conv1的形狀(50, 1, 50, 25)-->輸出conv1的形狀(50, 20, 26, 13)
                in_channels=1,  # 輸入卷積層的圖片通道數
                out_channels=20,  # 輸出的通道數
                kernel_size=3,  # 卷積核的大小,長寬相等
                stride=1,  # 滑動步長爲1
                padding=2  # 給輸入矩陣周圍添兩圈0,這樣的話在卷積核爲3*3時能將輸入矩陣的所有元素考慮進去
            ),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
        )
        self.fc = nn.Linear(20*26*13, 1)  # 將conv1的輸出flatten後爲(50, 20*26*13)-->經過全連接變爲(50, 1)

    def forward(self, x):
        x = self.conv1(x)
        x = x.view(x.size(0), -1)  # 將conv1的輸出flatten
        # x, _ = self.lstm2(x)
        x = self.fc(x)
        return x

在將數據進行預處理之後變成(142,1,50,25),再一個一個投入上面的CNN中,輸出就會變成一維的。

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