Pytorch学习记录[3]

神经网络基本骨架、卷积

P16:神经网络的基本骨架


理论:

pytorch.nn的Container

图1

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()这个变量

图2、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)

发表回复