PyTorch学习第六天

        卷积的stride默认为1,而池化默认为kernel_size(卷积核的大小) 

        Floor向下取整,ceiling向上取整

一、卷积(conv2d的应用)

        224*224*3 -> 224*224*64   输出通道为64(可以理解为64种结果),说明需要64个卷积核。

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset, batch_size=64)


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, 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


tudui = Tudui()
print(tudui)

writer = SummaryWriter("logs")

step = 0
for data in dataloader:
    imgs, targrts = data
    output = tudui(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]) -> 令batch_size变多,channel就会变少  [xxx, 3, 30, 30]
    #  AssertionError:assert I.ndim == 4 and I.shape[1] == 3 即6个channel不知道怎么显示
    # -1的意思是可以根据后面的3、30、30自动计算这个batch_size
    output = torch.reshape(output, (-1, 3, 30, 30))
    writer.add_images("output", output, step)
    step = step + 1

writer.close()

二、最大池化的使用

        使用:最大池化是取9宫格里的最大值,减少数据量,使少数据量也能保留所需信息

        ceil_mode:False = Floor向下取整(不保留),True = ceiling向上取整(保留)

import torch
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", train=False, download=True, transform=torchvision.transforms.ToTensor())

dataloader = DataLoader(dataset, batch_size=64)

#  "max_pool2d" not implemented for 'Long' 解决:变为浮点数
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)

# batch_size,channel,w,h
input = torch.reshape(input, (-1, 1, 5, 5))

print(input.shape)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)

    def forward(self, input):
        output = self.maxpool1(input)
        return output

tudui = Tudui()
# output = tudui(input)
# print(output)

# ../表示返回上级目录
writer = SummaryWriter("logs_maxpool")
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input", imgs, step)
    output = tudui(imgs)
    writer.add_images("output",output,step)
    step = step + 1

writer.close()

三、非线性激活(如ReLU、Sigmoid)

        作用:引入非线性特征

        ReLU:input>0就取input自身的值,input<0就取0; inplace为True,就是对原来位置的值进行替换,为False,则不替换原来位置的值

        Sigmoid:1/(1+exp(-x))

import torch
import torchvision.datasets
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([[1, -0.5],
                      [-1, 3]])

input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)

dataset = torchvision.datasets.CIFAR10("../data",train=False, transform=torchvision.transforms.ToTensor(),download=True)

dataloader = DataLoader(dataset, batch_size=64)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.relu1 = ReLU()
        self.sigmoid1 = Sigmoid()

    def forward(self,input):
        # output = self.relu1(input)
        output = self.sigmoid1(input)
        return output

tudui = Tudui()

writer = SummaryWriter("logs_relu")
step = 0

for data in dataloader:
    imgs, targets = data
    writer.add_images("input",imgs,step)
    output = tudui(imgs)
    writer.add_images("output", output, step)
    step = step + 1
# output = tudui(input)
# print(output)
writer.close()

四、线性层及其他层介绍

(1)正则化层(Normalization layer)

        作用:加快训练速度

        参数:

  • num_features – C from an expected input of size (N,C,H,W) channe

(2)线性层(Linear layer) 

import torch
import torchvision.datasets
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10("../data",train=False,download=True,transform=torchvision.transforms.ToTensor())

dataloader = DataLoader(dataset, batch_size=64, drop_last=True)    #丢弃无法整除的数据

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.linear1 = Linear(196608, 10)  #input_feature对应于reshape得到的-1,output_feature设置为10

    def forward(self, input):
        output = self.linear1(input)
        return output


tudui = Tudui()

for data in dataloader:
    imgs, targets = data
    print(imgs.shape)
    # output = torch.reshape(imgs, (1,1,1,-1))   #变成一行数据,-1为自动计算  等价于torch.flatten(imgs)
    output = torch.flatten(imgs)
    print(output.shape)
    output = tudui(output)
    print(output.shape)

五、Sequential的使用及搭建小实战

        Sequential作用:顺序模块型写法

import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # self.conv1 = Conv2d(3, 32, 5, padding=2)
        # self.maxpool1 = MaxPool2d(2)   # kernel_size为2
        # self.conv2 = Conv2d(32, 32, 5, padding=2)  # 图片保持不变 padding=(kernel_size - 1)/2
        # self.maxpool2 = MaxPool2d(2)
        # self.conv3 = Conv2d(32, 32, 5, padding=2)
        # self.maxpool3 = MaxPool2d(2)
        # self.flatten = Flatten()
        # # 测试前 self.linear1 = Linear(1024, 64)
        # self.linear1 = Linear(512, 64)
        # self.linear2 = Linear(64, 10)

        # 使用Sequential
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(512, 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)
        # # 假设未知flatten的结果是1024   得到torch.Size([64, 512]) ,batch_size有64张图片  ,每张图片都展成1*512
        # x = self.linear1(x)
        # x = self.linear2(x)

        # 使用Sequential
        x = self.model1(x)
        return x


tudui = Tudui()
print(tudui)
input = torch.ones((64, 3, 32, 32))
output = tudui(input)
print(output.shape)


writer = SummaryWriter("../logs_seq")
writer.add_graph(tudui, input)   #第一个参数是模型名
writer.close()


   六、损失函数(loss)与反向传播    

        loss函数的作用:

                1、计算实际输出和目标之间的差距;

                2、用来指导output去接近target,是训练的依据,为我们更新输出提供了一定的依据(反向传播)  grad(梯度,weight根据梯度的方向下降改变以降低loss):反向传播计算梯度,根据梯度来更新参数,实现loss最小化

        (1)常用函数

import torchvision.datasets
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10("../data", train=False, transform= torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=1)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(512, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        x = self.model1(x)
        return x

loss = nn.CrossEntropyLoss()
tudui = Tudui()
for data in dataloader:
    imgs, targets = data
    outputs = tudui(imgs)
    # print(outputs)
    # print(targets)
    result_loss = loss(outputs, targets)   # 是对result_loss这个变量进行反向传播
    result_loss.backward()   # 反向传播
    print(result_loss)

        (2)引入反向传播

import torchvision.datasets
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10("../data", train=False, transform= torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=1)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(512, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        x = self.model1(x)
        return x

loss = nn.CrossEntropyLoss()
tudui = Tudui()
for data in dataloader:
    imgs, targets = data
    outputs = tudui(imgs)
    # print(outputs)
    # print(targets)
    result_loss = loss(outputs, targets)   # 是对result_loss这个变量进行反向传播
    result_loss.backward()   # 反向传播
    print(result_loss)

七、优化器(torch.optim)

import torch.optim
import torchvision.datasets
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10("../data", train=False, transform= torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=1)
# 网络模型:土堆
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(512, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        x = self.model1(x)
        return x

loss = nn.CrossEntropyLoss()
tudui = Tudui()

# 设置优化器  —— 随机梯度下降
optim = torch.optim.SGD(tudui.parameters(), lr=0.01)
for epoch in range(20):
    running_loss = 0.0   #这一轮loss的总和
    # 这只是一次学习
    for data in dataloader:
        imgs, targets = data
        outputs = tudui(imgs)
        result_loss = loss(outputs, targets)   # 是对result_loss这个变量进行反向传播
        # 1、网络中每一个可以调节的参数的梯度设置为0
        optim.zero_grad()
        # 2、反向传播计算梯度
        result_loss.backward()
        # 3、对每一个参数调优
        optim.step()
        running_loss = running_loss +result_loss
    print(running_loss)

八、现有网络模型的使用及修改

import torchvision.datasets
from torch import nn

# train_data = torchvision.datasets.ImageNet("../data_image_net", split='train', download = True,
#                                            transform=torchvision.transforms.ToTensor())

vgg16_false = torchvision.models.vgg16(pretrained=False)  # 没有预训练,只需要加载已有的网络架构,相当于初始化的样子,都是默认的参数
vgg16_true = torchvision.models.vgg16(pretrained=True)   # 需要训练,网络参数是训练好的

print('ok')

# 可以打印出训练好的参数
print(vgg16_true)

train_data = torchvision.datasets.CIFAR10('../data', train=True,transform=torchvision.transforms.ToTensor(),
                                          download=True)

# 1、修改网络模型,使in_features为1000,out_features为10
# modele是指Conv2d、Linear这种
vgg16_true.add_module('add_linear', nn.Linear(1000, 10))
print(vgg16_true)

# 2、修改网络模型,将增加的module放到classifier中
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
print(vgg16_true)

# 3、在未预训练的模型中修改
print(vgg16_false)
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)

九、网络模型的保存与读取

(1)保存方式

import torch
import torchvision
from torch import nn

vgg16 = torchvision.models.vgg16(pretrained = False)
# 保存方式1  保存了模型结构 + 模型参数
torch.save(vgg16, "vgg16_method1.pth")

# 保存方式2  将vgg16模型中的参数保存为字典[[[],[]],[]](官方推荐)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")

# 陷阱
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

    def forward(self, x):
        x=self.conv1(x)
        return x


tudui = Tudui()
torch.save(tudui, "tudui_method1.pth")

(2)读取方式

import torch
import torchvision.models
from module_save import *

# 方式1-》保存方式1.加载模型
model = torch.load("vgg16_method1.pth")
print(model)

# 方式2-》保存方式2.加载模型
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
print(vgg16)

# 陷阱1 Can't get attribute 'Tudui' on <module '__main__' from 'G:\\learn_pytorch\\module_load.py'>
# model = torch.load("tudui_method1.pth")
# print(model)

# 解决陷阱1  无需创建模型tudui = Tudui(),但是要定义模型
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

    def forward(self, x):
        x=self.conv1(x)
        return x


model2 = torch.load("tudui_method1.pth")
print(model2)

# 解决陷阱1  或者from module_save import *

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值