2023.04.01
class NN继承父类:在pycharm中选择code - generate - override methods(重写父类)即可自动生成。
(一)卷积层
在pytorch官网找到torch.nn , nn.Conv2d是我们常用的卷积层,点击查看他的官方案例,一般只有前五个参数需要我们手动设置
一个简单的神经网络(作用为将输入图片(三通道的RGB图片)进行卷积,其中卷积核为3 * 3,步长为1 不进行池化)
整体代码:
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10('./data_Conv2d', train=False,
transform=torchvision.transforms.ToTensor(),
download=True)
dataloader = DataLoader(dataset, batch_size=64)
# 下面搭建简单的神经网络
class NerualNetwork(nn.Module):
def __init__(self):
# 先将父类初始化
super(NerualNetwork, self).__init__()
# 然后定义卷积层
self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3,
stride=1, padding=0)
def forward(self, x): # x是输出
# 先让x卷积
x = self.conv1(x)
return x
# 初始化网络
nerualnetwork = NerualNetwork()
# 查看网络结构
# print(nerualnetwork)
# 查看每一张图像
for data in dataloader:
imgs, targets = data
output = nerualnetwork(imgs) # 将图片放入网络中处理并返回到output
(二)池化层
最大池化的作用:保留输入特征的同时减少数据量
创建神经网络 - 初始化父类 - 定义池化层 - 初始化网络 - 使用网络处理图片
具体代码:
import torchvision.datasets
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10('./data_Conv2d', train=False,
transform=torchvision.transforms.ToTensor()
)
dataloader = DataLoader(dataset, batch_size=64)
# 创建神经网络
class NerualNetwork(nn.Module):
def __init__(self):
super(NerualNetwork, self).__init__()
self.maxpool = MaxPool2d(kernel_size=3, ceil_mode=False)
def forward(self, input):
output = self.maxpool(input)
return output
# 初始化网络
nerualnetwork = NerualNetwork()
writer = SummaryWriter('logs_maxpool')
step = 0
for data in dataloader:
imgs, targets = data
writer.add_images('input', imgs, step)
output = nerualnetwork(imgs)
writer.add_images('output', output, step)
step += 1
writer.close()
结果:
(三)非线性激活
3.1 ReLU激活函数
将输入矩阵中小于1的元素输入都置零,在图象上的效果不太直观
3.2 Sigmoid激活函数
self.sigmoid1 = Sigmoid()
整体代码:
mport torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
input = torch.tensor([
[0, 0.5],
[-1, 3]])
input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)
dataset = torchvision.datasets.CIFAR10('./new_dataset', train=False, download=True, transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=64)
class NerualNetwork(nn.Module):
def __init__(self):
super(NerualNetwork, self).__init__()
self.relu1 = ReLU()
self.sigmoid1 = Sigmoid()
def forward(self, input):
output = self.sigmoid1(input)
return output
nerualnetwork = NerualNetwork()
# output = nerualnetwork(input)
# print(output)
'''
relu作用:将小于1的输入都置零,在图象上的效果不太直观,以下换一种非线性激活:Sigmoid来说明
'''
writer = SummaryWriter('logs_sigmoid')
step = 0
for data in dataloader:
imgs, targets = data
writer.add_images('input', imgs, step)
output = nerualnetwork(imgs)
writer.add_images('output', output,step)
step += 1
writer.close()
结果
(四)线性层
线性层的作用就是把倒数第二步 64*4*4shape的图片通过 Flatten 后变成 1024 shape的图片 进行映射 将1024映射(或者叫分类?)成64幅图,再将64幅图映射到10幅图。
(五)上图的整体代码为:
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.tensorboard import SummaryWriter
class NerualNetwork(nn.Module):
def __init__(self):
super(NerualNetwork, self).__init__()
# self.conv1 = Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2)
# self.maxpool1 = MaxPool2d(kernel_size=2)
# self.conv2 = Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2)
# self.maxpool2 = MaxPool2d(kernel_size=2)
# self.conv3 = Conv2d(32, 64, 5, padding=2)
# self.maxpool3 = MaxPool2d(2)
# self.flatten = Flatten()
# self.linear1 = Linear(1024, 64)
# self.linear2 = Linear(64, 10)
# 使用 Sequential 来简化代码(注释掉的为复杂版
self.model1 = nn.Sequential(
Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x):
# x = self.conv1(x)
# x = self.maxpool1(x)
# x = self.conv2(x)
# x = self.maxpool2(x)
# x = self.conv3(x)
# x = self.maxpool3(x)
# x = self.flatten(x)
# x = self.linear1(x)
# x = self.linear2(x)
# 简单版调用:
x = self.model1(x)
return x
writer = SummaryWriter('logs_Seq')
nerualnetwork = NerualNetwork()
print(nerualnetwork)
input = torch.ones((64, 3, 32, 32))
output = nerualnetwork(input)
print(output.shape)
writer.add_graph(nerualnetwork, input,)
writer.close()
结果为
双击可以查看详细的网络信息
(六)交叉熵损失函数
loss = nn.CrossEntropyLoss()
使用交叉熵损失函数时需要使用反向传播:
output = nerualnetwork(imgs) # 计算交叉熵损失函数 result_loss = loss(output, targets) # 梯度下降(反向传播 result_loss.backward()
反向传播得到每个参数更新对应的梯度,后面调用优化器时,参数会根据其梯度进行优化,另外每一次循环后梯度应该清零。
这样网络会自动计算出偏置(梯度?grad),以便于实现梯度下降(损失函数最小化?)
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10('./new_dataset',train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=1)
class NerualNetwork(nn.Module):
def __init__(self):
super(NerualNetwork, self).__init__()
self.model1 = nn.Sequential(
Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x):
x = self.model1(x)
return x
# 交叉熵损失函数
loss = nn.CrossEntropyLoss()
nerualnetwork = NerualNetwork()
for data in dataloader:
imgs, targets = data
output = nerualnetwork(imgs)
# 计算交叉熵损失函数
result_loss = loss(output, targets)
# 梯度下降(反向传播
result_loss.backward()
print('ok') # 用于debug