美文网首页
CNN层探索

CNN层探索

作者: 钢笔先生 | 来源:发表于2019-08-02 23:40 被阅读0次

    Time: 2019-08-02
    视频链接:https://youtu.be/stWU37L91Yc?list=PLZbbT5o_s2xrfNyHZsM6ufI0iZENK9xgG

    卷积层的参数

    • kernel_size: filter的大小,一般filter都是正方形,所以指定一个值即可。注意kernelfilter是等价的意思。
    • out_channels: filters的个数,一个filter输出一个channel.

    全连接层的参数

    • out_features: 设置输出张量的大小,也表示该层神经元的个数

    CNN权重

    class Network():
      def __init__(self):
    #     super(Network, self).__init__()
        # 将层定义为属性
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)
        
        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)
        self.fc2 = nn.Linear(in_features=120, out_features=60)
        self.out = nn.Linear(in_features=60, out_features=10)
        
      # 实现forward函数,即组装网络的过程
      def forward(self, t):
        # pass
        return t
    

    不继承nn.Module的类,实例化后:

    # 实例化网络
    network = Network()
    network
    # <__main__.Network at 0x7febde19b668>
    

    就是一个平平无奇的对象。

    继承后:

    class Network(nn.Module):
      def __init__(self):
        super(Network, self).__init__()
        # 将层定义为属性
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)
        
        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)
        self.fc2 = nn.Linear(in_features=120, out_features=60)
        self.out = nn.Linear(in_features=60, out_features=10)
        
      # 实现forward函数,即组装网络的过程
      def forward(self, t):
        # pass
        return t
    

    实例化后:

    network
    '''
    Network(
      (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
      (conv2): Conv2d(6, 12, kernel_size=(5, 5), stride=(1, 1))
      (fc1): Linear(in_features=192, out_features=120, bias=True)
      (fc2): Linear(in_features=120, out_features=60, bias=True)
      (out): Linear(in_features=60, out_features=10, bias=True)
    )
    '''
    

    刚好今天复习到__repr__函数的实现,显然在nn.Module中实现了__repr__函数,这个可打印出关于对象的信息。

    关于卷积层的权重问题思考

    network.conv1.weight.shape
    # torch.Size([6, 1, 5, 5])
    

    就以这层作为例子好了,可以反映出卷积操作的全部问题。

    鼓励的思考卷积操作,我们可以想到几个关键词:

    • 权重共享
    • 稀疏连接

    但我个人觉得在思考CNN问题时,最重要的起点是:想到卷积核是3D张量,每一层的卷积核有多个,所以整体权重是个4D张量。每个卷积核对应着提取一种特征的权重。

    卷积层的权重就是卷积核的权重。

    另外不要混淆了卷积核输出的特征图的大小。

    卷积操作是立体的,是和输入张量形状所匹配的。

    这里,在定义卷积操作时,输入通道个数在前,输出通道个数在后,也即该层的卷积核的个数大小。

    该层的权重的形状中,第一个轴的大小是本层的输出通道个数,这样方便我们取得单个卷积核的大小。

    [6, 1, 5, 5]可以看作是6个卷积核,每个卷积核的形状是[1, 5, 5]。因为输入层就一层,所以这是个平面卷积核。

    全连接层就是密集的矩阵乘法,是二维平面。

    权重是个平面矩阵。

    查看网络的参数

    nn.Module中,网络中有个默认函数实现,parameters(),可以按照如下的方式调用:

    # 获取所有参数
    for param in network.parameters():
      print(param.shape)
    
    '''
    torch.Size([6, 1, 5, 5])
    torch.Size([6])
    torch.Size([12, 6, 5, 5])
    torch.Size([12])
    torch.Size([120, 192])
    torch.Size([120])
    torch.Size([60, 120])
    torch.Size([60])
    torch.Size([10, 60])
    torch.Size([10])
    '''
    

    另外还可以获取命名参数:

    for name, param in network.named_parameters():
      print(name, '\t\t', param.shape)
    
    '''
    conv1.weight         torch.Size([6, 1, 5, 5])
    conv1.bias       torch.Size([6])
    conv2.weight         torch.Size([12, 6, 5, 5])
    conv2.bias       torch.Size([12])
    fc1.weight       torch.Size([120, 192])
    fc1.bias         torch.Size([120])
    fc2.weight       torch.Size([60, 120])
    fc2.bias         torch.Size([60])
    out.weight       torch.Size([10, 60])
    out.bias         torch.Size([10])
    '''
    

    这些都是可学习参数。

    END.

    相关文章

      网友评论

          本文标题:CNN层探索

          本文链接:https://www.haomeiwen.com/subject/tkxkdctx.html