pytorch自动微分机制探寻

想起在很久之前,曾经学习机器学习的时候,手写过梯度求导来拟合一个散点的函数参数

https://blog.csdn.net/m0_72678953/article/details/133291795

现在准备下定决心系统性学习下torch,我发现torch可以自动求导,适用于给定散点x序列,在自行指定拟合目标y = 5x + 3的情况下,定义参数w、b,可以让torch使用自动反向传播 + 梯度更新。

这是原先的代码,拟合目标是y = x (虽然现在看也不知道为什么当时随机的y轴会有b=1的偏差,但是结果应该是没问题的)

python 复制代码
import numpy #发现直接用List就行了
import random
import matplotlib.pyplot as plt
# random.random()
# random.randint(start,stop)
#################全局数据定义区
# 数组大小
listSize=10
# 定义学习率 取尽量小0.001
learningRate=0.0001
#定义初始直线的 斜率k 和 截距b 45° 1单位距离
# 现在设置 k=0.5 检验程序
k,b=0.5,1
#定义迭代次数
bfsNums=9999
#################全局数据定义区END
# 生成随机数
def generateRandomInteger(start, end):
    # [1-100]
    return random.randint(start, end)
 
# 打印本次随机生成的X,Y 便于快速粘贴复现
def printXYArray(XData,YData):
    # 打印X
    print("[", ",".join([str(i) for i in XData]), "]")
    # 打印Y
    print("[", ",".join([str(i) for i in YData]), "]")
 
# 最小二乘法定义损失函数 并计算
#参考链接:https://blog.csdn.net/zy_505775013/article/details/88683460
# 求最小二乘法的最小值 最终结果应当是在learningRate一定情况下  这个最小的sum
def calcLoseFunction(k,b,XData,YData):
    sum=0
    for i in range(0,listSize):
        # 使用偏离值的平方进行累和
        sum+=(YData[i]-(k*XData[i]+b))**2
    return sum
 
#梯度下降法
def calcGradientCorrection(b, k, XData, YData, learningRate, bfsNums):
    for i in range(0, bfsNums):
        sumk, sumb = 0, 0
        for j in range(0, listSize):
            # 定义预测值Y'
            normalNum = k * XData[j] + b
            # 计算逆梯度累和  注意这里求偏导应当是两倍 不知道为什么写成1了
            # 求MSE的偏导
            sumk += -(2 / listSize) * (normalNum - YData[j]) * XData[j]
            sumb += -(2 / listSize) * (normalNum - YData[j])
        # 在逆梯度的方向上进行下一步搜索
        k += learningRate * sumk
        b += learningRate * sumb
    return k, b
 
# 随机生成横坐标
XData=[generateRandomInteger(1,100) for i in range(listSize) ]
# 随机生成纵坐标
YData=[XData[i]+generateRandomInteger(-10,10) for i in range(listSize) ]
# 纯随机生成 但是可视化效果不直观
# YData=[generateRandomInteger(1,100) for i in range(listSize) ]
# 死值替换区
# XData=testArrayX
# YData=testArrayY
 
print("初始选取k={},b={}的情况下的损失函数值为sum={}".format(k,b,calcLoseFunction(k,b,XData,YData)))
# 对k,b进行梯度修正
k,b=calcGradientCorrection(b,k,XData,YData,learningRate,bfsNums)
print("修正后:k={},b={},最小损失sum={}".format(k,b,calcLoseFunction(k,b, XData, YData)))
print("调试数组")
printXYArray(XData,YData)
 
#画图
plt.plot(XData, YData, 'b.')
plt.plot(XData, k*numpy.array(XData)+b, 'r')
plt.show()
print("END")

下面是使用torch编写的代码:

python 复制代码
import torch

# 输入数据(不需要梯度),目标是使用一次函数拟合x
x = torch.tensor([1.0, 2.0, 3.0])
# 真实值
y_true = 5 * x + 3 # tensor([8., 13., 18.])

# 要学习的参数(叶子节点,需要梯度)
w = torch.tensor([0.], requires_grad=True)
b = torch.tensor([0.], requires_grad=True)

# 定义一个优化器,并告诉它要优化哪些参数
optimizer = torch.optim.SGD([w, b], lr=0.01)

# 模拟训练过程
for epoch in range(9999):
    # 前向传播: y_pred = w * x
    y_pred = w * x + b # 这是一个关于x的复杂函数,但关于w是线性的
    # 计算损失
    loss = ((y_pred - y_true) ** 2).sum()
    # 反向传播
    loss.backward()
    # 打印梯度。这个梯度是 loss 相对于 w 的导数,即 d(loss)/dw
    print(f"Epoch {epoch}: w.grad = {w.grad.item()}, b.grad = {b.grad.item()}")

    # 自动参数更新
    optimizer.step()       # 优化器根据梯度更新参数(内部已经处理了no_grad逻辑)
    # 手动更新参数(通常用优化器,这里为了演示)
    # with torch.no_grad():
    #     w -= 0.01 * w.grad
    #     b -= 0.01 * b.grad

    # # 清零梯度!!!非常重要
    # torch的梯度累加特性,可以让大量数据按照小批次分批训练,
    # 一定批次后再调用参数清空,这样就能实现小显存训练大批次的效果
    w.grad.zero_()
    b.grad.zero_()

print(f"Final w: {w.item()}, b: {b.item()}")

可以看到torch编写的代码非常优雅,定义一个优化器,指定学习率和参数,然后嗲用反向传播和参数自动更新,依赖广播机制就能替代之前一长串的循环和参数更新了。非常方便

相关推荐
Hcoco_me1 天前
大模型面试题40:结合RoPE位置编码、优秀位置编码的核心特性
人工智能·深度学习·lstm·transformer·word2vec
刘立军1 天前
程序员应该熟悉的概念(8)嵌入和语义检索
人工智能·算法
Mr.Lee jack1 天前
TileRT超低延迟的大语言模型推理系统
人工智能·pytorch·deepseek
kisshuan123961 天前
基于VFNet的轮胎标签检测与分类系统
人工智能·分类·数据挖掘
Nautiluss1 天前
一起调试XVF3800麦克风阵列(六)
人工智能·单片机·音频·语音识别·dsp开发·智能硬件
北京耐用通信1 天前
耐达讯自动化Profibus三路中继器:低成本搞定阀门定位器稳定组网的硬核方案
人工智能·物联网·自动化
敢敢のwings1 天前
VGGT-Long:极简主义驱动的公里级单目三维重建系统深度解析(Pytorch安装手册版)
人工智能·pytorch·python
技术狂人1681 天前
(七)大模型工程落地与部署 10 题!vLLM/QPS 优化 / 高可用,面试实战必备(工程篇)
人工智能·深度学习·面试·职场和发展·vllm
新芒1 天前
海尔智家加速全球体育营销
大数据·人工智能