Pytorch学习记录[3]
神经网络基本骨架、卷积
P16:神经网络的基本骨架
理论:
pytorch.nn的Container
在pytorch官网关于nn的帮助文档可以看到,torch.nn帮我们提供了许多神经网络骨架,而Module是其中一个最基本的骨架。
实操:
示例:python源码
import torch
from torch import nn
class MyModule(nn.Module): # MyModule继承Module
def __init__(self):
super().__init__() # 构造函数
def forward(self, input):
output = input + 1
return output
mymodel = MyModule()
x = torch.tensor(1.0) # 构造一个tensor为1.0的x
y = mymodel(x) # 利用mymodule的forward处理x并赋值给y
print(y)
细解释
新的MyModule继承于nn.Module,实际上是拿nn.Module这么一个骨架来进行自己的改装,比如在__init__()、forward()进行自定义。
而对于x = torch.tensor(1.0)这句话
看torch.tensor()这个变量
可以知道,这是将一个数据data转换为Tensor类
P18:卷积层
import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
# 下面这两行是解决 dataset下载的ssl证书报错
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
dataset = torchvision.datasets.CIFAR10("../data", train = False, transform = torchvision.transforms.ToTensor(), download = True)
dataloader = DataLoader(dataset, batch_size = 64)
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.conv1 = Conv2d(in_channels = 3, out_channels = 6, kernel_size = 3, stride = 1, padding = 0)
def forward(self, x):
x = self.conv1(x)
return x
mymodule = MyModule()
writer = SummaryWriter("../logs")
step = 0
for data in dataloader:
imgs, targets = data
# 调用了MyModule父类nn.Module的__call__函数,而__call__函数里面调用了forward函数, forward已在子类MyModule中重写
output = mymodule(imgs)
print(imgs.shape)
print(output.shape)
#torch.Size([64, 3, 32, 32])
writer.add_images("Input", imgs, step)
#torch.Size([64, 6, 30, 30])
output = torch.reshape(output, [-1, 3, 30, 30])
writer.add_images("Output", output, step)
step = step + 1
P19:池化层
池化层的作用:将输入进行采样,以达到减少训练数据量
矩阵
import tensorboard.compat.tensorflow_stub.dtypes
import torch
from torch import nn
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.maxpool = nn.MaxPool2d(kernel_size=3, ceil_mode=True)
def forward(self, input):
output = self.maxpool(input)
return output
input = torch.tensor([[1, 2, 0, 3, 1],
[0, 1, 2, 3, 1],
[1, 2, 1, 0, 0],
[5, 2, 3, 1, 1],
[2, 1, 0, 1, 1]], dtype=torch.float32)
input = torch.reshape(input, [-1, 1, 5, 5])
mymodule = MyModule()
output = mymodule(input)
print(output)
图片集
import torchvision.datasets
import torchvision.transforms
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.maxpool = nn.MaxPool2d(kernel_size=3, ceil_mode=True)
def forward(self, input):
output = self.maxpool(input)
return output
dataset = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset=dataset, batch_size=64)
mymodule = MyModule()
writer = SummaryWriter("../logs_maxpool")
step = 1
for imgs, targets in dataloader:
output_imgs = mymodule(imgs)
writer.add_images("Input Imgs", imgs, step)
writer.add_images("Output Imgs", output_imgs, step)
step += 1
P20:非线性激活
矩阵
import torch
from torch import nn
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.relu = nn.ReLU()
def forward(self, input):
output = self.relu(input)
return output
input = torch.tensor([[-2, -3],
[1, 4]])
input = torch.reshape(input, [-1, 1, 2, 2])
mymodule = MyModule()
output = mymodule(input)
print(output)
图片集
import torchvision.datasets
import torchvision.transforms
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.sigmoid = nn.Sigmoid()
def forward(self, input):
output = self.sigmoid(input)
return output
dataset = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64)
mymodule = MyModule()
writer = SummaryWriter(log_dir="../logs_sigmoid")
step = 0
for imgs, targets in dataloader:
Output_imgs = mymodule(imgs)
writer.add_images("Input", imgs, step)
writer.add_images("Output", Output_imgs, step)
step += 1
writer.close()
P21:线性层
import torchvision
from torch import nn, flatten
from torch.utils.data import DataLoader
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.linear = nn.Linear(196608, 10)
def forward(self, input):
output = self.linear(input)
return output
dataset = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64)
mymodule = MyModule()
step = 0
for imgs, targets in dataloader:
Output_imgs = flatten(imgs) # 将输入拉平成一维数据
print(Output_imgs.shape)
Output_imgs = mymodule(Output_imgs)
print(Output_imgs.shape)
step += 1
P22:神经网络的搭建
个人理解:
神经网络将我们的输入由大量数据(batches*channel*width*height)综合到少量几个(如下代码便是10个),而这些输出的数据便像集合 x[] ,而我们的target便是y,神经网络模型中的参数alpha则在一次次的 x[] 与 y的对比,计算loss中优化。(代码参考本文P22 P23 P24)
神经网络最后线性层输出的个数是和分类数一致的,经过softmax处理后便是各个类别的概率。
import torch.utils.data
import torchvision.datasets
from torch import nn, ones
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2)
self.maxpool1 = nn.MaxPool2d(2)
self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2)
self.maxpool2 = nn.MaxPool2d(2)
self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2)
self.maxpool3 = nn.MaxPool2d(2)
self.fallten = nn.Flatten()
self.linear1 = nn.Linear(in_features=1024, out_features=64)
self.linear2 = nn.Linear(in_features=64, out_features=10)
self.model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=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(in_features=1024, out_features=64),
nn.Linear(in_features=64, out_features=10)
)
def forward(self, input):
# input = self.conv1(input)
# input = self.maxpool1(input)
# input = self.conv2(input)
# input = self.maxpool2(input)
# input = self.conv3(input)
# input = self.maxpool3(input)
# input = self.fallten(input)
# input = self.linear1(input)
# input = self.linear2(input)
input = self.model(input)
return input
mymodule = MyModule()
dataset = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=64)
for imgs, targets in dataloader:
output = mymodule(imgs)
print(output)
P23:损失函数&反向传播
梯度下降参考这篇文章 通俗易懂讲解梯度下降法 – 知乎 (zhihu.com)
import torch.utils.data
import torchvision.datasets
from torch import nn, ones
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2)
self.maxpool1 = nn.MaxPool2d(2)
self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2)
self.maxpool2 = nn.MaxPool2d(2)
self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2)
self.maxpool3 = nn.MaxPool2d(2)
self.fallten = nn.Flatten()
self.linear1 = nn.Linear(in_features=1024, out_features=64)
self.linear2 = nn.Linear(in_features=64, out_features=10)
self.model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=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(in_features=1024, out_features=64),
nn.Linear(in_features=64, out_features=10)
)
def forward(self, input):
# input = self.conv1(input)
# input = self.maxpool1(input)
# input = self.conv2(input)
# input = self.maxpool2(input)
# input = self.conv3(input)
# input = self.maxpool3(input)
# input = self.fallten(input)
# input = self.linear1(input)
# input = self.linear2(input)
input = self.model(input)
return input
mymodule = MyModule()
dataset = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=64)
for imgs, targets in dataloader:
output = mymodule(imgs)
print(output)
P24:优化器
(1)解释
一言以蔽之,优化器就是在深度学习反向传播过程中,指引损失函数(目标函数)的各个参数往正确的方向更新合适的大小,使得更新后的各个参数让损失函数(目标函数)值不断逼近全局最小。
使用梯度下降进行优化,是几乎所有优化器的核心思想。
引自:优化器(Optimizer) – 知乎 (zhihu.com)
import torch.utils.data
import torchvision.datasets
from torch import nn, ones
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=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(in_features=1024, out_features=64),
nn.Linear(in_features=64, out_features=10)
)
def forward(self, input):
input = self.model(input)
return input
mymodule = MyModule()
dataset = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=1)
loss = nn.CrossEntropyLoss()
optim = torch.optim.SGD(params=mymodule.parameters(), lr=0.01)
for i in range(20):
running_loss = 0.0
for imgs, targets in dataloader:
outputs = mymodule(imgs)
result_loss = loss(outputs, targets)
optim.zero_grad() #将上一次的梯度参数归零
result_loss.backward()
optim.step()
running_loss += result_loss
print(running_loss)