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 = [] # 定义列表,用于接收每一步的学习率 # 设置退化学习率,每50步乘以0.99 scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[200, 700, 800], gamma=0.9) 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()
运行结果:
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 = [] # 定义列表,用于接收每一步的学习率 # 设置退化学习率,每50步乘以0.99 scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', # 要监控模型的最大值max还是最小值min factor=0.5, # 退化学习率参数gamma patience=5, # 不再减小(或增加)的累计次数 verbose=True, # 出发规则时是否打印信息 threshold=0.0001, # 监控值出发规则的阈值 threshold_mode='abs', # 计算触发规则的方法 cooldown=0, # 触发规则后的停止监控步数,避免lr下降过快 min_lr=0, # 允许的最小退化学习率 eps=1e-08 # 当退化学习率的调整幅度小于该值的时候,停止调整 ) for i in range(epochs): loss = model.getloss(xt, yt) losses.append(loss.item()) # 保存中间状态的损失值 scheduler.step(loss.item()) # 调用退化学习率对象 optimizer.zero_grad() # 清空之前的梯度 loss.backward() # 反向传播损失值 optimizer.step() # 更新参数 lr_list.append(optimizer.state_dict()['param_groups'][0]['lr']) plt.plot(range(epochs), lr_list, color='r') # 输出学习率的可视化结果 plt.show()
运行结果:
scheduler.step(loss.item())