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中,输出就会变成一维的。

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