编程基础很弱,需要机器学习,学习记录,按自己理解写的,希望以后能学懂吧,要是有大神看到还请赐教。
损失函数与反向传播
1.损失函数:
计算实际输出和目标计算之间的差距,衡量网络的预测效果越小越好。比如说损失函数较大,它会计算梯度然后调整权重使损失函数降低,即预测与实际之间的差距缩小。
为更新输出提供依据。(反向传播)梯度下降。
注意损失函数的input和target
loss_function需要根据问题去选取,在使用时要注意输入是什么输出是什么。
import torch
from torch.nn import L1Loss
from torch import nn
inputs = torch.tensor([1, 2, 3], dtype=float)
targets = torch.tensor([1, 2, 5], dtype=float)
inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))
#
loss = L1Loss()
result = loss(inputs, targets)
print(result)
# MSE
loss_mse = nn.MSELoss()
result_mse = loss_mse(inputs, targets)
print(result_mse)
# 交叉熵 常用于分类问题
x = torch.tensor([0.1, 0.2, 0.3])
y = torch.tensor([1])
x = torch.reshape(x, (1, 3))
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(x, y)
print(result_cross)
如何在之前的神经网络中使用
# 如何在神经网络中用到Loss Function
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
cifar_path = "D:\\Scientific_Research\\Pycharmproject\\Biji\\dataset"
dataset = torchvision.datasets.CIFAR10(root=cifar_path, train=False, transform=torchvision.transforms.ToTensor(),
download=True)
dataloader = DataLoader(dataset, batch_size=1)
class Lizi(nn.Module):
def __init__(self):
super(Lizi, self).__init__()
self.model1 = Sequential(
Conv2d(3, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 64, 5, 1, 2),
MaxPool2d(2),
Flatten(),
Linear(64 * 4 * 4, 64),
Linear(64, 10)
)
def forward(self, input):
output = self.model1(input)
return output
loss = nn.CrossEntropyLoss()
lizi = Lizi()
for data in dataloader:
imgs, targets = data
outputs = lizi(imgs)
# print(outputs)
# print(targets)
result_loss = loss(outputs, targets)
print(result_loss)
反向传播:
在以上代码加一点然后debug:
# 如何在神经网络中用到Loss Function
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
cifar_path = "D:\\Scientific_Research\\Pycharmproject\\Biji\\dataset"
dataset = torchvision.datasets.CIFAR10(root=cifar_path, train=False, transform=torchvision.transforms.ToTensor(),
download=True)
dataloader = DataLoader(dataset, batch_size=1)
class Lizi(nn.Module):
def __init__(self):
super(Lizi, self).__init__()
self.model1 = Sequential(
Conv2d(3, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 64, 5, 1, 2),
MaxPool2d(2),
Flatten(),
Linear(64 * 4 * 4, 64),
Linear(64, 10)
)
def forward(self, input):
output = self.model1(input)
return output
loss = nn.CrossEntropyLoss()
lizi = Lizi()
for data in dataloader:
imgs, targets = data
outputs = lizi(imgs)
# print(outputs)
# print(targets)
result_loss = loss(outputs, targets)
print(result_loss)
#如何进行反向传播
result_loss.backward()
print("ok")
断点打在这里,可以发现在反向传播前,这里是没有梯度的。
再往下运行,发现计算了梯度。
优化器,就是根据这些梯度对神经网络中的这些参数进行更新,使得对整体的loss进行降低的效果。
优化器(一)
之前讲了,使用损失函数时,可以调用损失函数的backward进行反向传播可以求出每个需要调节的参数的梯度,有了这个梯度,就可以用优化器对梯度进行调增。
先构造优化器:
有了优化器后,调用优化器的step方法。
调用step时,会根据backward得到的参数对以上步骤进行重新计算,神经网络中的参数会进行一定调整。调整完后会再次进行循环,因此要将之前的梯度清零。
#优化套路
先定义一个优化器,然后梯度清零,调用反向传播,再调用优化器调优。
代码:
# 24 优化器
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
cifar_path = "D:\\Scientific_Research\\Pycharmproject\\Biji\\dataset"
dataset = torchvision.datasets.CIFAR10(root=cifar_path, train=False, transform=torchvision.transforms.ToTensor(),
download=True)
dataloader = DataLoader(dataset, batch_size=1)
class Lizi(nn.Module):
def __init__(self):
super(Lizi, self).__init__()
self.model1 = Sequential(
Conv2d(3, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 64, 5, 1, 2),
MaxPool2d(2),
Flatten(),
Linear(64 * 4 * 4, 64),
Linear(64, 10)
)
def forward(self, input):
output = self.model1(input)
return output
loss = nn.CrossEntropyLoss()
lizi = Lizi()
# 此处开始设置优化器
optim=torch.optim.SGD(lizi.parameters(),lr=0.01)
#依次从dataloader中取数据
for data in dataloader:
imgs, targets = data
outputs = lizi(imgs)#将数据送入网络中
result_loss = loss(outputs, targets)#计算损失
#将每个参数的对应梯度调为0
optim.zero_grad()#这句就是调为0
result_loss.backward()#反向传播,此句得到每个可以调节的参数对应梯度
#接着调用优化器
optim.step()
print(result_loss)
Debug一下:
会发现梯度发生了变化。
运行一下看看loss效果:
以上代码相当于只看了一遍数据集,也就是只进行了一轮的学习,那么在这个循环外面再嵌套一层循环,运行20次epoch。
# 此处开始设置优化器
optim=torch.optim.SGD(lizi.parameters(),lr=0.01)
#依次从dataloader中取数据
#分epoch进行循环
for epoch in range(20):
#每一轮loss是多少
running_los=0.0
for data in dataloader:
imgs, targets = data
outputs = lizi(imgs)#将数据送入网络中
result_loss = loss(outputs, targets)#计算损失
#将每个参数的对应梯度调为0
optim.zero_grad()#这句就是调为0
result_loss.backward()#反向传播,此句得到每个可以调节的参数对应梯度
#接着调用优化器
optim.step()
running_los = running_los+result_loss
print(running_los)
最开始减小了,然后增大了。