神经网络的基本骨架
神经网络的基本骨架构成为:input–>卷积层–>池化层–>正则化层–>非线性激活–>线性层。(个别层可以根据模型训练需要进行添加或删除),下面是各个层的依次介绍。
卷积层
卷积原理
-
通过卷积核在图片上按指定步长向右向下移动,将卷积核覆盖的像素乘以对应位置卷积核的值再的相加,最终得到一个总和,作为卷积后图片的对应位置的像素,然后卷积核向右或向下移动step步,继续重复上面的操作,直到原图片的所有像素均被卷积,这时卷积操作完成。
如上,卷积核为3x3的一个全1的核,原图为4x5的一个单通道图片,卷积后的图片为2x3的一个单通道图片。
(单通道即只有一个维度)(作为对比彩色图片为3通道图(分别为RGB三个通道)),
2.卷积核首先覆盖在图片的左上角,即覆盖了[[1,2,3][1,2,3],[1,2,3]],将该位置的像素进行卷积,即1x1+2x1+3x1+1x1+2x1+3x1+1x1+2x1+3x1=18
所以卷积后的图片的左上角第一个像素为18,然后将卷积核向右移动step步(这里step设置为1),此时卷积核覆盖了[[2,3,4][2,3,4],[2,3,4]],进行卷积操作,即
2x1+3x1+4x1+2x1+3x1+4x1+2x1+3x1+4x1=27
这就是卷积后的图片的第二个像素,然后继续向右……………
当右边走到头后就可以将卷积核开始向下移动step步,然后重复上面的操作。
注意:卷积核必须完全在图片上,不能在图片外,也不能一半在外一半在内,如果不满足上述要求,就表示卷积核走到头了
pytorch中的卷积函数
头文件
from torch.nn import Conv2d
函数
Conv2d(in_channels=3, out_channels=32,
kernel_size=(5, 5),
stride=(1, 1), padding=0)
#参数:
# in_channels 输入图片的通道数 (输入图片层数)
# out_channels 输出图片的通道数 (输出图片层数)
# kernel_size 卷积核 (卷积核个数=in_channels * out_channels)
# stride 卷积核每次移动的步长(横向移动步长,纵向移动步长)
# padding 围绕着原图填充一圈,填充值为0。该参数作用:让在图片边缘
# 的小于卷积核大小的位置的像素可以借助填充,单独进行一次卷积。
池化层
1.与卷积层类似,但是需要的不是卷积核,而是空洞卷积,进行“卷积”的方式也不同,其余性质与卷积层一致。
- 由上图可见,空洞卷积将普通卷积核中的每一个值用0隔开了,从而构成了一种新的卷积核,这就叫做空洞卷积核(简称空洞卷积)
- 池化层进行"卷积"的方式:卷积核覆盖的位置的所有像素,找出其中像素值最大的像素,作为结果进行输出,这就叫最大池化。
pytorch中的池化函数
头文件
from torch.nn import MaxPool2d
函数
MaxPool2d(kernel_size=(3, 3), ceil_mode=True)
#参数
#kernel_size 池化核(stride一般取默认即与池化核
# 大小一致)(这里会自动将3x3的核转化成空洞卷积核)
#ceil_mode 向上取整--沙鲁模式
#(当图片像素不足池化核大小时,是否依然保留并计算)
#最大池化层作用:保留数据特征同时减小数据量
非线性激活
作用
- 在神经网络中加入一些非线性的特征
头文件
from torch.nn import ReLU
函数
ReLU()
# 非线性激活作用:在网络中引入一些非线性特征
# ReLU()函数作用:图片像素小于或等于0的返回0,大于0的返回原值
正则化层
头文件
from torch.nn import BatchNorm2d
函数
BatchNorm2d(num_features=3)
#参数
#num_features 图片通道数
#正则化作用: 防止过拟合
线性层
头文件
from torch.nn import Linear
函数
self.linear=Linear(196608, 10)
#参数
#in_features :输入图像(必须为线性图
# --->[1,1,1,xxx](可简化为[xxx],如torch.flatten输出[xxx]))
#out_features :输出图像(同样为线性图[xxx])
# 线性层作用:保留数据特征同时减小数据量
介绍一个可以将图片展开的函数(变为线性图)
#torch.flatten(imgs)
# 参数
# input 图片(tensor类型)
# 函数作用:将图片展平(即变为[1,1,1,xxx])
简单神经网络的搭建
from torch import nn
from torch.nn import Conv2d, MaxPool2d, ReLU, BatchNorm2d, Linear
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
import torchvision
import torch
#nn.Module 为神经网络的基本骨架,所有的神经网络都要继承它
data_compose=torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
test_dataset2=torchvision.datasets.CIFAR10(root="./test_dataset2", train=False, transform=data_compose, download=True)
dataload=DataLoader(test_dataset2, batch_size=64, shuffle=True, num_workers=0, drop_last=True)
#神经网络的搭建
class NetWork(nn.Module):
def __init__(self):
super(NetWork, self).__init__()
#卷积层
self.conv1=Conv2d(in_channels=3, out_channels=6, kernel_size=(3, 3), stride=(1, 1), padding=0)
#参数:
# in_channels 输入图片的通道数 (输入图片层数)
# out_channels 输出图片的通道数 (输出图片层数)
# kernel_size 卷积核
#(卷积核个数=in_channels * out_channels)
# stride 卷积核每次移动的步长(横向移动步长,纵向移动步长)
#池化层(与卷积层类似)
self.maxpool=MaxPool2d(kernel_size=(3, 3), ceil_mode=True)
#参数
#kernel_size 池化核(stride一般取默认即与池化核大小一致)
#ceil_mode 向上取整--沙鲁模式(当图片像素不足池化核大小时,是否依然保留并计算)
#最大池化层作用:保留数据特征同时减小数据量
#非线性激活
self.relu=ReLU()
#非线性激活作用:在网络中引入一些非线性特征
# ReLU()函数作用:图片像素小于或等于0的返回0,大于0的返回原值
#线性层
self.linear=Linear(196608, 10)
#参数
#in_features :输入图像(必须为线性图--->[1,1,1,xxx]
#(可简化为[xxx],如torch.flatten输出[xxx]))
#out_features :输出图像(同样为线性图[xxx])
# 线性层作用:保留数据特征同时减小数据量
# 正则化层
self.batchnormal=BatchNorm2d(num_features=3)
#参数
#num_features 图片通道数
#正则化作用: 防止过拟合
self.model=nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=6,
kernel_size=(3, 3), stride=(1, 1), padding=0),
nn.ReLU(),
)
#类似transform中的Compose()函数,输入的图片会依次经过
#各个层的处理
def forward(self, x, y): #输出函数(对父类方法的重写)
#(神经网络传入数据后自动调用)
return self.conv1(x), self.maxpool(x), self.linear(y)
#torch.flatten(imgs)
# 参数
# input 图片(tensor类型)
# 函数作用:将图片展平(即变为[1,1,1,xxx])
if __name__ == '__main__':
net=NetWork()
writer = SummaryWriter(r"E:\python\pythonProject_pyTorch\
nn_model")
# print(net)
step=0
for data in dataload:
imgs, targets =data
output1, output2, output3=net(imgs, torch.flatten(imgs))
print("原图大小:"+str(imgs.shape))
#.shape-->[N,C,W,H](batch_size(图片数 量),channel(图片
#通道数),图片高,图片宽)
print("卷积后图的大小:"+str(output1.shape))
writer.add_images("imgs", imgs, step)
#tensorBoard最多显示三通道的图片,及彩色图片,
#高于3通道的图片若想要显示,需要改变图片通道数即维度
output=torch.reshape(output1, (-1, 3, 30, 30))
#函数作用:
#改变图片维度即通道数
#参数
#input: 要改变的图片(图片类型必须是Tensor)
#(shape): 要改变的大小
#返回值: 改变后的图片(Tensor类型)
print("最大池化后图的大小:"+str(output2.shape))
writer.add_images("output", output, step)
writer.add_images("output2", output2, step)
step=step+1
print("线性层输出后大小:"+str(output3.shape))
writer.close()