池化运算: 对信号进行“收集”并“总结” ,类似水池收集水资源,因而 ,得名池化层
nn.MaxPool2d(kernel_size,
stride=None,
padding=0,
dilation=1,
return_indices=False,
ceil_mode=False)
功能: 对二维信号(图像)进行最大值池化
主要参数:
最大值反池化上采样:
早期的自编码器和图像分割任务中都会涉及图像上采样的操作,当时常使用最大值反池化上采样
如上图所示,图片先进行池化下采样,然后再进行上采样,此时就出现问题:2*2的图像中的像素值上采样后应该放到哪个位置?
而return_indices记录了最大池化下采样时,每个像素值来自的位置,在上采样时就可以根据记录的位置进行上采样
代码:
# -*- coding: utf-8 -*-
import os
import torch
import random
import numpy as np
import torchvision
import torch.nn as nn
from torchvision import transforms
from matplotlib import pyplot as plt
from PIL import Image
from tools.common_tools import transform_invert, set_seed
set_seed(1) # 设置随机种子
# ================================= load img ==================================
path_img = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lena.png")
img = Image.open(path_img).convert('RGB') # 0~255
# convert to tensor
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(img)
img_tensor.unsqueeze_(dim=0) # C*H*W to B*C*H*W
# ================================= create convolution layer ==================================
# ================ maxpool
flag = 1
# 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)
# ================================= visualization ==================================
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.subplot(121).imshow(img_raw)
plt.show()
nn.AvgPool2d(kernel_size,
stride=None,
padding=0,
ceil_mode=False,
count_include_pad=True,
divisor_override=None)
功能:对二维信号(图像)进行平均值池化
主要参数:
# -*- coding: utf-8 -*-
import os
import torch
import random
import numpy as np
import torchvision
import torch.nn as nn
from torchvision import transforms
from matplotlib import pyplot as plt
from PIL import Image
from tools.common_tools import transform_invert, set_seed
set_seed(1) # 设置随机种子
# ================================= load img ==================================
path_img = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lena.png")
img = Image.open(path_img).convert('RGB') # 0~255
# convert to tensor
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(img)
img_tensor.unsqueeze_(dim=0) # C*H*W to B*C*H*W
# ================================= create convolution layer ==================================
# ================ avgpool
flag = 1
# flag = 0
if flag:
avgpoollayer = nn.AvgPool2d((2, 2), stride=(2, 2)) # input:(i, o, size) weights:(o, i , h, w)
img_pool = avgpoollayer(img_tensor)
# ================ avgpool divisor_override
# flag = 1
flag = 0
if flag:
img_tensor = torch.ones((1, 1, 4, 4))
avgpool_layer = nn.AvgPool2d((2, 2), stride=(2, 2), divisor_override=3)
img_pool = avgpool_layer(img_tensor)
print("raw_img:\n{}\npooling_img:\n{}".format(img_tensor, img_pool))
# ================================= visualization ==================================
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.subplot(121).imshow(img_raw)
plt.show()
nn.MaxUnpool2d(kernel_size,
stride=None,
padding=0)
forward(self, input, indices, output_size=None)
功能: 对二维信号(图像)进行最大值池化上采样
注意: forward中要传入indices
主要参数:
# -*- coding: utf-8 -*-
import os
import torch
import random
import numpy as np
import torchvision
import torch.nn as nn
from torchvision import transforms
from matplotlib import pyplot as plt
from PIL import Image
from tools.common_tools import transform_invert, set_seed
set_seed(1) # 设置随机种子
# ================================= load img ==================================
path_img = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lena.png")
img = Image.open(path_img).convert('RGB') # 0~255
# convert to tensor
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(img)
img_tensor.unsqueeze_(dim=0) # C*H*W to B*C*H*W
# ================================= create convolution layer ==================================
# ================ max unpool
flag = 1
# flag = 0
if flag:
# pooling
img_tensor = torch.randint(high=5, size=(1, 1, 4, 4), dtype=torch.float)
maxpool_layer = nn.MaxPool2d((2, 2), stride=(2, 2), return_indices=True)
img_pool, indices = maxpool_layer(img_tensor)
# unpooling
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))
线性层又称全连接层,其每个神经元与上一层所有神经元相连实现对前一层的线性组合, 线性变换
nn.Linear(in_features, out_features, bias=True)
功能: 对一维信号(向量)进行线性组合
主要参数:
计算公式: y = x W T + b i a s y=xW^T + bias y=xWT+bias
代码:
# -*- coding: utf-8 -*-
import os
import torch
import random
import numpy as np
import torchvision
import torch.nn as nn
from torchvision import transforms
from matplotlib import pyplot as plt
from PIL import Image
from tools.common_tools import transform_invert, set_seed
set_seed(1) # 设置随机种子
# ================================= load img ==================================
path_img = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lena.png")
img = Image.open(path_img).convert('RGB') # 0~255
# convert to tensor
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(img)
img_tensor.unsqueeze_(dim=0) # C*H*W to B*C*H*W
# ================================= create convolution layer ==================================
# ================ linear
flag = 1
# flag = 0
if flag:
inputs = torch.tensor([[1., 2, 3]])
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)
运行结果:
注意:由上面计算公式可知,线性层计算时,对权值矩阵是进行转置后再运算的,所以设置权值矩阵时需要按转置形式设置
激活函数对特征进行非线性变换, 赋予多层神经网络具有深度的意义
当使用线性激活函数时,如上图所示,输出就变成了输入的线性组合,中间的隐藏层就失去了意义,所以,通过引入非线性激活函数,增加了网络的深度,同时给予了网络的非线性
计算公式: y = 1 1 + e − x y=\frac{1}{1+e^{-x}} y=1+e−x1
梯度公式: y ′ = y ∗ ( 1 − y ) y'=y* (1-y) y′=y∗(1−y)
特性:
计算公式: y = s i n x c o s x = e x − e − x e x + e − x = 2 1 + e − 2 x + 1 y=\frac{sinx}{cosx}=\frac{e^x-e^{-x}}{e^x+e^{-x}}=\frac{2}{1+e^{-2x}}+1 y=cosxsinx=ex+e−xex−e−x=1+e−2x2+1
梯度公式: y ′ = 1 − y 2 y'=1-y^2 y′=1−y2
特性:
计算公式: y = m a x ( 0 , x ) y= max(0,x) y=max(0,x)
梯度公式: y ′ = { 1 , x > 0 u n d e f i n e d , x = 0 0 , x < 0 y'= \begin{cases} 1, \qquad \qquad \quad x>0 \\undefined, \quad x=0 \\0,\qquad \qquad \quad x<0\end{cases} y′=⎩⎪⎨⎪⎧1,x>0undefined,x=00,x<0
功能:负半轴增加一个很小的斜率,防止死神经元
功能:使负半轴的斜率是可学习的,随着网络更新斜率参数会变化
功能:随机地从均匀分布中采样斜率