卷积神经网络
卷积神经网络主要的作用就是提取特征。
卷积计算原理
涉及到几个参数,输入的chanel,输出chanel,卷积核大小,padding,stride(移动步数)
将一张图片的某个区域值相加,然后得到另外的一个矩阵。
视频教程:土堆说卷积
卷积神经网络的结构
卷积神经网络的基本结构由以下几个部分组成:输入层、卷积层、池化层、激活函数层和全连接层。其中,卷积层是卷积神经网络中最基础的操作,它通过滑动窗口的方式在输入数据上进行卷积运算,提取输入数据的局部特征。池化层则用于对卷积层的输出进行下采样,减少数据的空间大小,降低计算复杂度。激活函数层引入非线性因素,增强网络的表达能力。全连接层则负责将学到的特征表示映射到最终的输出。
简单来说,卷积层提取特征,池化层降低大小,激活函数提供非线性,全连接层标准化输出。
结构图如下:
例图说明:
这个神经网络是几层呢?
几层就看对特征进行更新了几次。conv卷积,全连接都进行了更新,池化只是从特征图里面提取最大的值,不算更新,激活函数relu也是。所以这个例子里是7层的神经网络
卷积操作
卷积是为了提取特征,包含的参数是in_channels,out_channels,kernel_size(卷积核大小),stride(移动的步数,可以是元组形式,(1,2)则表示x,y方向移动的距离),padding(是否填充)。
比如输入的图片是(3,32,32)要使输出的特征图为6个(通道数channels为6),则Conv2d(3,6...)就进行了一次卷积。
激活函数
每次卷积之后都要使用激活函数。常见的激活函数有ReLU、sigmoid。
ReLU函数
形式为 𝑓(𝑥)=max(0,𝑥)。
这意味着对于所有正输入值,输出等于输入;而对于所有负输入值,输出为0。
优点:
计算简单:ReLU的计算非常高效,仅需判断输入值的符号。
缓解梯度消失:在正区间内,ReLU的导数为1,避免了梯度消失问题,有助于深度网络的训练。
加速训练:由于其简单的线性特性,ReLU可以加快网络的训练速度。
促进稀疏性:负输入下输出为0,有助于实现网络的稀疏激活,减少计算需求并可能有助于泛化。
缺点:
“Dead ReLU”问题:负输入时梯度为0,可能导致某些神经元在训练过程中“死亡”,不再更新权重。
Sigmoid
定义:Sigmoid函数的形式为它的输出范围在(0, 1)之间,通常用于二分类问题,可以视为概率输出。
优点:
输出范围受限:Sigmoid的输出总是在(0, 1)之间,适合做概率预测。
连续且光滑:Sigmoid函数是连续且可微的,这在某些算法中是有利的。
缺点:
梯度消失:在输入值较大或较小时,Sigmoid函数的导数接近于0,导致梯度消失,影响训练效率。
计算成本较高:相比于ReLU,Sigmoid涉及指数运算,计算成本更高。
饱和效应:在输入值绝对值较大时,Sigmoid函数的输出变化缓慢,限制了信息的流动。
池化
直接取规定的区域中的最大特征值。以降低大小的目的。
MaxPool2d(kernel_size)选择池化的大小,比如MaxPool2d(4),就是在4*4的矩阵中选取最大的值。
全连接
当都完成前面的操作之后,就要将结果进行转换输出,使用nn.Linear类来创建全连接层。例如,nn.Linear(in_features, out_features),其中in_features是输入特征的数量,out_features是输出神经元的数量。
全连接层在神经网络模型中主要用于从提取的特征中进行高级抽象和分类决策,在使用Linear之前通常需要使用nn.Flatten(),添加Flatten层来展平卷积层的输出。
比如,通过卷积和池化之后的特征图为 323210、那如果想要输出为5分类的话,就需要先将323210的图展平为11024的矩阵。然后再使用n.linear(1024,5)。就可以完成【1,1024】【1024,5】相乘得到1*5的五分类结果。
实战--CIFAR10的卷积举例
结构图
这只有四层结构。在卷积时需要通过公式计算padding的大小。可以看官方文档的公式。
代码
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
class Tudui(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Conv2d(3, 32, 5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(1024, 64),
nn.Linear(64, 10)
)
def forward(self,input):
x= self.model(input)
return x
data_set = torchvision.datasets.CIFAR10('Dataset', train=False, transform=torchvision.transforms.ToTensor(), download=False)
data_load = DataLoader(dataset=data_set,batch_size=1)
# print(data.shape)
tudu = Tudui()
for data in data_load:
img , target = data
output = tudu(img)
print(output)
# writers =SummaryWriter('logs_test')
#
# writers.add_graph(tudu,data)
#
#
# writers.close()