import torch.nn as nn import torch import numpy as np import matplotlib.pyplot as plt # 继承nn.Module类,构建网络模型 class LogicNet(nn.Module): def __init__(self, inputdim, hiddendim, outputdim): # 初始化网络结构 super(LogicNet, self).__init__() self.Liner1 = nn.Linear(inputdim, hiddendim) # 定义全连接层 self.Liner2 = nn.Linear(hiddendim, outputdim) # 定义全连接层 self.criterion = nn.CrossEntropyLoss() # 定义交叉熵函数, 一定要加上括号,不可以直接写。 def forward(self, x): # 搭建用两个全连接层构建的网络模型 x = self.Liner1(x) # 将输入数据传入第1个全连接层 x = torch.tanh(x) # 对第一个连接层的结果进行非线性变换,使用激活函数tanh实现 x = self.Liner2(x) # 将网络数据传入第2个链接层 return x def predict(self, x): # 实现LogicNet类的预测接口 # 调用自身网络模型,并对结果进行softmax处理,分别得出预测数据属于每一类的概率 pred = torch.softmax(self.forward(x), dim=1) return torch.argmax(pred, dim=1) # 返回每组预测概率中最大值的索引 def getloss(self, x, y): # 实现LogicNet类的损失值接口 y_pred = self.forward(x) loss = self.criterion(y_pred, y) # 计算损失值的交叉熵 return loss
import sklearn.datasets # 数据集 import torch import numpy as np import matplotlib.pyplot as plt from code_04_moons import LogicNet X, Y = sklearn.datasets.make_moons(20, noise=0.2) # 生成两组半圆形数据 model = LogicNet(inputdim=2, hiddendim=3, outputdim=2) # 实例化模型 optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # 定义Adam优化器 xt = torch.from_numpy(X).type(torch.FloatTensor) # 将numpy数据转化为张量 yt = torch.from_numpy(Y).type(torch.LongTensor) epochs = 1000 # 定义迭代次数 losses = [] # 定义列表,用于接收每一步的损失值 lr_list = [] # 定义列表,用于接收每一步的学习率 for i in range(epochs): loss = model.getloss(xt, yt) losses.append(loss.item()) # 保存中间状态的损失值 optimizer.zero_grad() # 清空之前的梯度 loss.backward() # 反向传播损失值 optimizer.step() # 更新参数 # 实现退化学习率的功能 if i %50 == 0: for p in optimizer.param_groups: # 将学习率乘以0.99 p['lr'] *= 0.99 lr_list.append(optimizer.state_dict()['param_groups'][0]['lr']) plt.plot(range(epochs), lr_list, color='r') # 输出学习率的可视化结果 plt.show()
运行结果:
import sklearn.datasets # 数据集 import torch import numpy as np import matplotlib.pyplot as plt from code_04_moons import LogicNet X, Y = sklearn.datasets.make_moons(20, noise=0.2) # 生成两组半圆形数据 model = LogicNet(inputdim=2, hiddendim=3, outputdim=2) # 实例化模型 optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # 定义Adam优化器 xt = torch.from_numpy(X).type(torch.FloatTensor) # 将numpy数据转化为张量 yt = torch.from_numpy(Y).type(torch.LongTensor) epochs = 1000 # 定义迭代次数 losses = [] # 定义列表,用于接收每一步的损失值 lr_list = [] # 定义列表,用于接收每一步的学习率 # 设置退化学习率,每50步乘以0.99 scheduler = torch.optim.lr_scheduler.StepLR(optimizer,step_size=50, gamma=0.99) for i in range(epochs): loss = model.getloss(xt, yt) losses.append(loss.item()) # 保存中间状态的损失值 optimizer.zero_grad() # 清空之前的梯度 loss.backward() # 反向传播损失值 optimizer.step() # 更新参数 scheduler.step() # 调用退化学习率对象 lr_list.append(optimizer.state_dict()['param_groups'][0]['lr']) plt.plot(range(epochs), lr_list, color='r') # 输出学习率的可视化结果 plt.show()
运行结果:
lr_scheduler接口还支持了多种退化学习率的实现,每种退化学习率都是通过一个类来实现的,具体的介绍如下:
其中LambdaLR最为灵活,可以根据需求指定任何策略的学习率变化。
它在fine-tune(微调模型中的一种方法)中特别有用,不但可以为不同层设置不同的的学习率,而且可以为不同层设置不同的学习率调整策略。