老饼讲解-深度学习 机器学习 神经网络 深度学习
pytorch入门
1.pytorch学前准备
2.pytorch的基础操作
3.pytorch的梯度计算
4.pytorch的数据
5.pytorch-小试牛刀

【实践】使用pytorch的优化器训练一个逻辑回归

作者 : 老饼 日期 : 2023-12-04 05:46:41 更新 : 2024-01-19 10:01:23
本站原创文章,转载请说明来自《老饼讲解-深度学习》www.bbbdata.com




在pytorch中训练一个模型,往往是直接使用pytorch的优化器对模型进行训练

本文简单介绍pytorch的优化器是什么,并展示如何使用pytorch的优化器对模型进行训练




    01. pytorch的优化器简介    



本节简单介绍pytorch的优化器,并讲述如何使用优化器



    什么是pytorch的优化器   


在pytorch中训练一个模型,往往是直接使用pytorch的优化器进行训练
优化器指的是pytorch已经写好的一套训练算法
例如常见的SGD(随机梯度下降算法)、LBFGS(拟牛顿法)、Adam等等
 对于简单的梯度下降算法,自己手写与调用pytorch的优化器差别不大,
但对于复杂的算法,调用优化器就会方便很多




     如何使用pytorch的优化器     


使用pytorch的优化器主要包括三个步骤
👉1. 初始化优化器                  
👉2. 自行更新梯度                 
👉3. 调用优化器进行参数更新
下面详细介绍使用pytorch优化器时的这三个步骤
优化器的初始化
 
优化器初始化主要是指出要把哪些参数交给优化器进行优化,及设定优化算法中的超参数
 以随机梯度下降SGD为例,初始化一个SGD优化器示例如下:
             
optimizer = torch.optim.SGD({w,b}, lr=0.01)         
其中w和b是我们要优化的参数,而lr则是SGD的超参数-学习率

 
自行更新梯度
由于优化器更新参数时需要用到参数的梯度,所以需要先自行更新梯度
 需要注意的是,pytorch的梯度更新是累加的,因此更新梯度前需要先将梯度清零
为了更方便梯度清零,优化器提供了一次性清零所有参数梯度的方法,如下:
 
optimizer.zero_grad()
 
通过zero_grad就会一次性把之前交给优化器管理的参数w和b的梯度都清零

调用优化器进行参数更新
 
优化器把算法的更新机制进行封装,直接调用就能按算法的机制对参数进行更新
 如下,调用下述语句就会利用参数的梯度对参数进行更新
 
optimizer.step()
 
以梯度下降为例,optimizer.step()就相当于执行w=w-lr*dw这样的操作
✍️pytorch优化器的使用-总结
 
根据上述三大步骤的理解,使用优化器优化参数的形式如下:
初始化优化器                   
for 循环                           
----清空梯度                   
----更新梯度                   
----优化器更新参数         






   02. pytorch使用优化器训练模型实例    




本节展示一个用pytorch的优化器训练一个逻辑回归模型的例子




     使用pytorch的优化器训练一个逻辑回归     


下面展示如何使用pytorch的优化器训练一个逻辑回归模型
主要就是把《》一文中的训练部分改为使用pytorch的优化器进行参数训练
具体代码如下:
import torch
import matplotlib.pyplot as plt
import numpy as np

# ------训练数据----------------
X = np.array([[2.5, 1.3, 6.2, 1.3, 5.4, 6 ,4.3, 8.2]
                ,[-1.2,2.5,3.6,4,3.4,2.3,7.2,3.9]]).T                   # 样本的输入数据
Y = [0,0,1,0,1,1,1,1]                                                   # 样本的标签
x = torch.tensor(X)                                                     # 将训练数据X转为tensor
y = torch.tensor(Y)                                                     # 将训练数据y转为tensor

#-----------训练模型------------------------
w  = torch.tensor([2,2],dtype=(float),requires_grad=True)               # 初始化模型系数w
b  = torch.tensor([1],dtype=(float),requires_grad=True)                 # 初始化模型系数b
optimizer = torch.optim.SGD({w,b}, lr=0.01)                             # 初始化优化器
for i in range(1000):
    L = (torch.log(1+torch.exp(x@w+b)) -y*(x@w+b)).sum()                # 损失函数
    print('第',str(i),'轮的Loss:',L)                                   # 打印当前损失函数值
    optimizer.zero_grad()                                               # 更新梯度之前先清空梯度
    L.backward()                                                        # 用损失函数更新模型系数的梯度
    optimizer.step()
    
# --------------------画出结果----------------
print('--------最终结果-------')
W  = w.detach().numpy()                                                 # 模型的系数,先转回numpy
B  = b.item()                                                           # 模型的阈值,先转回数值
print('W:',W)                                                           # 打印模型系数W
print('B:',B)                                                           # 打印模型系数B
x1 = X[:,0]                                                             # 绘制分割平面的x轴
x2 = (-B - W[0]*x1)/W[1]                                                # 绘制分割平面的y轴
plt.scatter(X[:, 0], X[:, 1],c=Y)                                       # 绘制样本
plt.plot(x1,x2)                                                         # 绘制分割平面             
plt.axis([min(X[:,0])-1,max(X[:,0])+1,min(X[:,1])-1,max(X[:,1])+1])     # 设置坐标范围
plt.show()                                                              # 展示图象




     运行结果    


运行结果如下:
第 0 轮的Loss: tensor(23.8272, dtype=torch.float64, grad_fn=<SumBackward0>)
第 1 轮的Loss: tensor(23.2013, dtype=torch.float64, grad_fn=<SumBackward0>)
第 2 轮的Loss: tensor(22.5759, dtype=torch.float64, grad_fn=<SumBackward0>)
.....
第 997 轮的Loss: tensor(0.4918, dtype=torch.float64, grad_fn=<SumBackward0>)
第 998 轮的Loss: tensor(0.4913, dtype=torch.float64, grad_fn=<SumBackward0>)
第 999 轮的Loss: tensor(0.4908, dtype=torch.float64, grad_fn=<SumBackward0>)
--------最终结果-------
W: [1.50026373 1.46529551]
B: 0.7041382734007223

 
可以看到,逻辑回归模型已成功把样本分为两类,说明训练是成功的










 End 





联系老饼