视频(我是土堆)+笔记【我是土堆 - PyTorch教程】学习随手记
1.损失函数与反向传播
Loss Functions
作用:
- 计算实际输出和目标之间的差距;
- 为我们更新输出提供一定的依据(反向传播);给每一个卷积核中的参数提供了梯度 grad,采用反向传播时,每一个要更新的参数都会计算出对应的梯度,优化过程中根据梯度对参数进行优化,最终达到整个 loss 进行降低的目的
import torch
from torch.nn import L1Loss
from torch import nn
inputs=torch.tensor([1,2,3],dtype=torch.float32)
targets=torch.tensor([1,2,5],dtype=torch.float32)
inputs=torch.reshape(inputs,[1,1,1,3])
targets=torch.reshape(targets,[1,1,1,3])
#L1Loss
loss=L1Loss(reduction='sum')
# reduction属性:sum 表示差值绝对值相加;若是默认值,即mean,则为差值绝对值的均值
result=loss(inputs,targets)
print(result)
#MSELoss 均方误差
loss_mse=nn.MSELoss()
result_mse=loss_mse(inputs,targets)
print(result_mse)
#CROSSENTROPYLOSS 交叉熵
x=torch.tensor([0.1,0.2,0.3]) #属于某一类的概率,0.1属于0类的概率
y=torch.tensor([1]) #图片真实的label的下标
x=torch.reshape(x,(1,3))
loss_cross=nn.CrossEntropyLoss()
result_cross=loss_cross(x,y)
print(result_cross)
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
datasets=torchvision.datasets.CIFAR10("./datasets",train=False,transform=torchvision.transforms.ToTensor(),
download=True)
dataloader=DataLoader(datasets,batch_size=1)
class Tudui(nn.Module): #搭建模型
def __init__(self):
super(Tudui,self).__init__()
self.module1=Sequential( #把上述的步骤进行简单化
Conv2d(3, 32, 5, padding=2, stride=1),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2, stride=1),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(), # 展平,
Linear(1024, 64),
Linear(64, 10)
)
def forward(self,input):
output=self.module1(input)
return output
#如何在模型中运行loss function(实际输出和目标之间的差距)
loss=nn.CrossEntropyLoss() #使用交叉熵函数
tudui=Tudui()
for data in dataloader:
imgs,targets=data
output=tudui(imgs)
result_loss=loss(output,targets)
print(result_loss) #tensor(2.3803, grad_fn=<NllLossBackward0>)
result_loss.backward() #反向传播是在loss中的,有一个参数grad(记录梯度),优化器会根据它的值对参数进行更新,以降低loss
#通过不断更新梯度来减少梯度就可以使loss最小
print("ok")
2.优化器
当使用损失函数时,可以调用损失函数的 backward,得到反向传播,反向传播可以求出每个需要调节的参数对应的梯度,有了梯度就可以利用优化器,优化器根据梯度对参数进行调整,以达到整体误差降低的目的
(lr:learning rate 学习率)
TORCH.OPTIM
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
#加载数据集并转为tensor数据类型
datasets=torchvision.datasets.CIFAR10("./datasets",train=False,transform=torchvision.transforms.ToTensor(),
download=True)
#dataloader 进行加载
dataloader=DataLoader(datasets,batch_size=1)
class Tudui(nn.Module): #搭建网络
def __init__(self):
super(Tudui,self).__init__()
self.module1=Sequential( #把上述的步骤进行简单化
Conv2d(3, 32, 5, padding=2, stride=1),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2, stride=1),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(), # 展平,
Linear(1024, 64),
Linear(64, 10)
)
def forward(self,input):
output=self.module1(input)
return output
loss=nn.CrossEntropyLoss() #使用交叉熵函数,计算loss
tudui=Tudui() #实例化,搭建网络
# SGD 随机梯度下降
optim=torch.optim.SGD(tudui.parameters(),lr=0.01) #定义优化器
for epoch in range(20): #多次训练数据
running_loss=0.0
for data in dataloader: #只对数据训练一次
imgs,targets=data
output=tudui(imgs)
result_loss=loss(output,targets)
optim.zero_grad() #每个参数对应调节的梯度设置为0,优化器清0
result_loss.backward() #反向传播是在result_loss中的,有一个参数grad(记录梯度),优化器会根据它的值对参数进行更新,以降低loss
#通过不断更新梯度来减少梯度就可以使loss最小
optim.step() #执行单个优化步骤(参数更新)
running_loss=running_loss+result_loss #整体误差总和
print(running_loss)
3.现有网络模型的使用及修改
import torchvision
from torch import nn
vgg16_false=torchvision.models.vgg16(weights=None)
vgg16_true=torchvision.models.vgg16(weights='DEFAULT')
print(vgg16_true)
#如何利用现有的网络来改动它的结构
train_data=torchvision.datasets.CIFAR10("./datasets",train=True,transform=torchvision.transforms.ToTensor(),
download=True)
# vgg16_true.add_module('add_liner',nn.Linear(1000,10)) #加入一个线性层
vgg16_true.classifier.add_module('add_liner',nn.Linear(1000,10)) #在(classifier)中加入线性层
print(vgg16_true)
print(vgg16_false)
vgg16_false.classifier[6]=nn.Linear(4096,10) #直接对(classifier)结构进行修改
print(vgg16_false)
4.网络模型的保存和读取
import torch
import torchvision
from torch import nn
vgg16=torchvision.models.vgg16(weights=None)
#保存方式1
torch.save(vgg16,"vgg16_method1.pth")#保存网络模型的结构+模型参数
#保存方式2(官方推荐的保存方式)
torch.save(vgg16.state_dict(),"vgg16_method2.pth") #保存网络模型的参数,以字典的形式展现出来
#陷阱 针对于保存方式1的
class Module(nn.Module):
def __init__(self):
super(Module,self).__init__()
self.conv1=nn.Conv2d(3,64,kernel_size=3)
def forward(self,x):
x=self.conv1(x)
return x
module=Module()
torch.save(module,"module_method1.pth")
import torch
import torchvision
from torch import nn
# 方式1-->对应保存方式1来加载模型
module=torch.load("vgg16_method1.pth")
#print(module)
#方式2 加载模型
#module2=torch.load("vgg16_method2.pth") #对应保存方式2,打印出的是参数的字典形式
# 或者
# 如何恢复网络模型结构?
vgg16=torchvision.models.vgg16(weights=None)
vgg16.load_state_dict(torch.load("vgg16_method2.pth")) #load_state_dict:下载数据,以字典的方式读取
print(vgg16)
#陷阱--针对于方式1
class Module(nn.Module):
def __init__(self):
super(Module,self).__init__()
self.conv1=nn.Conv2d(3,64,kernel_size=3)
def forward(self,x):
x=self.conv1(x)
return x
module2=torch.load("module_method1.pth")
print(module2)
#这样会出错
# AttributeError: Can't get attribute 'Module' on <module '__main__' from 'E:\\study\\pytorch_learn\\pythonProject\\module_load.py'>
#加上Module这个类(网络)
# 实际写项目过程中,直接定义在一个单独的文件中(如model_save.py),再在 model_load.py 中:或者from model_save import *