当前位置 博文首页 > 斯人若彩虹,遇上方知有!:Pytorch-池化、线性、激活函数层

    斯人若彩虹,遇上方知有!:Pytorch-池化、线性、激活函数层

    作者:[db:作者] 时间:2021-08-25 21:50

    1. 池化层——Pooling layer
    2. 线性层——Linear layer
    3. 激活函数层——Activation layer

    1、池化层——Pooling layer

    池化运算:对信号进行 “收集”并 “总结”,类似水池收集水资源,因而得名池化层
    “收集”:多变少 “总结”:最大值/平均值

    最大值池化:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    import os
    import torch
    import random
    from PIL import Image
    import numpy as np
    import matplotlib.pyplot as plt
    import torchvision
    from torchvision import transforms
    import torch.nn as nn
    path_tools = os.path.join("tools","common_tools.py")
    from tools.common_tools import transform_invert,set_seed
    set_seed(1)
    
    img = Image.open('lena.png').convert('RGB')
    plt.imshow(img)
    
    <matplotlib.image.AxesImage at 0x2524a16f208>
    

    在这里插入图片描述

    # 转换为向量
    img_transform = transforms.Compose([transforms.ToTensor()])
    img_tensor = img_transform(img)
    img_tensor.unsqueeze_(dim=0) # C*H*W to B*C*H*W
    
    tensor([[[[0.8824, 0.8824, 0.8824,  ..., 0.8941, 0.8549, 0.7961],
              [0.8784, 0.8824, 0.8784,  ..., 0.9059, 0.8588, 0.7922],
              [0.8824, 0.8784, 0.8784,  ..., 0.9137, 0.8667, 0.7765],
              ...,
              [0.3216, 0.3098, 0.3686,  ..., 0.6863, 0.6824, 0.6824],
              [0.3216, 0.3137, 0.3843,  ..., 0.7059, 0.7137, 0.7059],
              [0.3255, 0.3176, 0.3882,  ..., 0.7020, 0.7216, 0.7216]],
    
             [[0.5412, 0.5333, 0.5333,  ..., 0.5843, 0.5176, 0.3922],
              [0.5333, 0.5333, 0.5333,  ..., 0.5882, 0.5216, 0.3922],
              [0.5373, 0.5373, 0.5373,  ..., 0.5765, 0.5098, 0.3804],
              ...,
              [0.0863, 0.0706, 0.1176,  ..., 0.2706, 0.2588, 0.2588],
              [0.0863, 0.0745, 0.1333,  ..., 0.2745, 0.2824, 0.2863],
              [0.0902, 0.0784, 0.1373,  ..., 0.2667, 0.2941, 0.2941]],
    
             [[0.4745, 0.5020, 0.5176,  ..., 0.4627, 0.4196, 0.3333],
              [0.4784, 0.5020, 0.5176,  ..., 0.4745, 0.4314, 0.3451],
              [0.4902, 0.5020, 0.5098,  ..., 0.4706, 0.4392, 0.3490],
              ...,
              [0.2196, 0.2039, 0.2549,  ..., 0.3255, 0.3098, 0.3098],
              [0.2196, 0.2078, 0.2706,  ..., 0.3176, 0.3255, 0.3255],
              [0.2235, 0.2118, 0.2745,  ..., 0.2941, 0.3176, 0.3176]]]])
    
    # 最大池化操作
    flag = 0
    if flag:
        maxpool_layer = nn.MaxPool2d((2,2),stride=(2,2)) # input:(i, o, size) weights:(o, i , h, w)
        img_pool = maxpool_layer(img_tensor)
    
    # 平均池化操作
    flag = 1
    if flag:
        avgpool_layer = nn.AvgPool2d((2,2),stride=(2,2)) # input:(i, o, size) weights:(o, i , h, w)
        img_pool = avgpool_layer(img_tensor)
        
    # 可视化
    print("池化前尺寸:{}\n池化后尺寸:{}".format(img_tensor.shape,img_pool.shape))
    img_pool = transform_invert(img_pool[0,0:3,...],img_transform)
    img_raw = transform_invert(img_tensor.squeeze(),img_transform)
    plt.subplot(122).imshow(img_pool)
    # plt.title("池化后")
    plt.subplot(121).imshow(img_raw)
    # plt.title("原图")
    plt.show()
    
    池化前尺寸:torch.Size([1, 3, 512, 512])
    池化后尺寸:torch.Size([1, 3, 256, 256])
    

    在这里插入图片描述

    # 平均池化-设置divisor_override
    # 这个参数可以指定平均的个数,比如原本是2*2的卷积核,平均池化需要除以4,这里设置
    # 其他参数如:divisor_override=3,就表示除以3,而不是原来的4
    img_tensor = torch.ones((1, 1, 4, 4))
    # 未使用divisor_override
    avgpool_layer1 = nn.AvgPool2d((2,2),stride=(2,2))
    img_pool1 = avgpool_layer1(img_tensor)
    # divisor_override=3
    avgpool_layer = nn.AvgPool2d((2, 2), stride=(2, 2), divisor_override=3)
    img_pool = avgpool_layer(img_tensor)
    print("img_pool1:\n{}".format(img_pool1))
    print("raw_img:\n{}\npooling_img:\n{}".format(img_tensor, img_pool))
    
    img_pool1:
    tensor([[[[1., 1.],
              [1., 1.]]]])
    raw_img:
    tensor([[[[1., 1., 1., 1.],
              [1., 1., 1., 1.],
              [1., 1., 1., 1.],
              [1., 1., 1., 1.]]]])
    pooling_img:
    tensor([[[[1.3333, 1.3333],
              [1.3333, 1.3333]]]])
    
    #最大池化上采样:对二维信号(图像)进行最大值池化上采样
    # nn.MaxUnpool2d
    
    # 池化操作
    img_tensor = torch.randint(high=5,size=(1,1,4,4),dtype=torch.float)
    # print(img_tensor)
    maxpool_layer = nn.MaxPool2d((2,2),stride=(2,2),return_indices=True)
    # 获得最大值的索引
    img_pool,indices = maxpool_layer(img_tensor)
    
    # 上采样
    img_reconstruct = torch.randn_like(img_pool,dtype=torch.float)
    maxunpool_layer = nn.MaxUnpool2d((2,2),stride=(2,2))
    img_unpool = maxunpool_layer(img_reconstruct,indices)
    print("raw_img:\n{}\nimg_pool:\n{}".format(img_tensor,img_pool))
    print("img_reconstruct:\n{}\nimg_unpool:\n{}".format(img_reconstruct, img_unpool))
    
    raw_img:
    tensor([[[[1., 4., 2., 3.],
              [1., 4., 4., 3.],
              [3., 3., 1., 2.],
              [2., 3., 4., 3.]]]])
    img_pool:
    tensor([[[[4., 4.],
              [3., 4.]]]])
    img_reconstruct:
    tensor([[[[ 0.8310, -0.2477],
              [-0.8029,  0.2366]]]])
    img_unpool:
    tensor([[[[ 0.0000,  0.8310,  0.0000,  0.0000],
              [ 0.0000,  0.0000, -0.2477,  0.0000],
              [-0.8029,  0.0000,  0.0000,  0.0000],
              [ 0.0000,  0.0000,  0.2366,  0.0000]]]])
    

    2、 线性层——Linear layer

    在这里插入图片描述
    在这里插入图片描述

    # 线性层又称全连接层,其每一个神经元与上一层所有神经元相连
    # 实现对前一层的线性组合,线性变换
    inputs = torch.tensor([[1.,2,3]])
    # 对一维信号进行线性组合
    # 计算公式:y = x*W^T + bias
    linear_layer = nn.Linear(3,4)
    # 权重参数
    linear_layer.weight.data = torch.tensor([[1.,1.,1.],
                                            [2.,2.,2.],
                                            [3.,3.,3.],
                                            [4.,4.,4.]])
    # 偏置
    linear_layer.bias.data.fill_(0.5)
    output = linear_layer(inputs)
    print(inputs,inputs.shape)
    print(linear_layer.weight.data,linear_layer.weight.data.shape)
    print(output,output.shape)
    
    tensor([[1., 2., 3.]]) torch.Size([1, 3])
    tensor([[1., 1., 1.],
            [2., 2., 2.],
            [3., 3., 3.],
            [4., 4., 4.]]) torch.Size([4, 3])
    tensor([[ 6.5000, 12.5000, 18.5000, 24.5000]], grad_fn=<AddmmBackward>) torch.Size([1, 4])
    

    在这里插入图片描述
    参考机器之心:激活函数

    # 激活函数:对特征进行非线性变换,赋予多层神经网络具有深度的意义
    # 激活函数层
    # 1、nn.Sigmoid:输出值在(0,1)之间,符合概率,导数范围在[0,0.25],容易出现梯度消失,输出为非零均值,破坏数据分布
    # 2、nn.tanh:输出值在(-1,1),数据符合0均值,导数范围是(0,1),容易导致梯度消失
    # 3、nn.ReLU:输出值均为正数,导数为1,缓解梯度爆炸
    # 4、nn.LeakyReLU:negative_slope:负半轴斜率
    # 5、nn.PReLU:init:可学习斜率
    # 6、nn.RReLU:lower:均匀分布下限,upper:均匀分布上限
    
    # 查看使用方法
    # 1、help(nn.Sigmoid)
    # 2、nn.Sigmoid?
    # 3、nn.Sigmoid??
    
    cs