Pytorch —— 自动微分模块

目录

一、自动微分模块

1.定义模型权重参数

2.定义一个损失函数

[3.backward(). 反向传播计算导数/梯度](#3.backward(). 反向传播计算导数/梯度)

[4.w.grad 获取导数值/梯度](#4.w.grad 获取导数值/梯度)

[5.更新参数: W新 = W旧 - 学习率 * 梯度](#5.更新参数: W新 = W旧 - 学习率 * 梯度)

二、梯度下降法

[梯度下降法 求损失函数的最小值](#梯度下降法 求损失函数的最小值)

计算过程:

[三、detch() 函数](#三、detch() 函数)

[1.定义张量,开启梯度计算requires_grad = True](#1.定义张量,开启梯度计算requires_grad = True)

[2.直接转为numpy数组 (无法转)](#2.直接转为numpy数组 (无法转))

3.使用detach().numpy()来转数组

[4.查看是否共享内存/浅拷贝 (浅拷贝)](#4.查看是否共享内存/浅拷贝 (浅拷贝))

四、Pytorch框架_模型线性回归

1.准备数据集

2.构建模型

3.设置损失函数和优化器

4.模型训练


一、自动微分模块

是Pytorch内部的自动求导模块 自动微分:自动求导

作用:自动精确求导,无需手动计算

自动微分模型在神经网络训练中的作用:计算损失梯度

1.定义模型权重参数

2.定义一个损失函数

3.backward(). 反向传播计算导数/梯度

4.w.grad 获取导数值/梯度

5.更新参数: W新 = W旧 - 学习率 * 梯度

python 复制代码
# 1.定义变量,模拟模型权重参数w
w = torch.tensor([10,20],requires_grad=True,dtype=torch.float32)
print(f"w:{w}, requires_grad: {w.requires_grad}")
# 2.定义函数,模拟损失函数
loss = w**2 + 10    # [110,410]
# 打印导函数
print(f"loss.grad_fn:{loss.grad_fn}")
loss_mean = loss.mean()
print(f"loss_mean:{loss_mean}")
# loss' = 2*w = [2*w1,2*w2]
# loss_mean' = 2*w = [w1,w2]
# 3.需要执行反向传播来调用自动微分模块
loss.mean().backward()
# 4.打印loss_mean对w的梯度
print(f"w.grad:{w.grad}")
# 5.更新参数:w新 = w旧 - 学习率 * 梯度
w.data = w.data - 0.01 * w.grad.data
# 10 - 0.01*20=9.8
# [10,20] - 0.01*[10.,20.]=[9.9,19.8]
print(f"w:{w}")

二、梯度下降法

针对损失函数,沿着损失函数导数的反方向更新模型参数,使得损失函数降低

目标:获取 损失函数的最小值,对应的模型参数,也就是最优模型

梯度下降法 求损失函数的最小值

如:求 loss = w**2 + 20 的极小值点 并打印loss是最小值时 w的值(梯度)

计算过程:

1 定义点 w=10, requires_grad=True, dtype=torch.float32

2 定义函数 loss = w**2 + 20

3 利用梯度下降法 循环迭代 求最优解/最小值

3.1 前向传播,计算损失

3.2 梯度清零 w.grad.zero_()

3.3 反向传播 loss.backward()

3.4 更新参数 w.data = w.data - 0.01 * w.grad

1-3

python 复制代码
# 1 定义点 w=10, requires_grad=True, dtype=torch.float32
w = torch.tensor([10.0,20.0],requires_grad=True,dtype=torch.float32)
# 2 定义函数 loss = w**2 + 20
loss = w**2 + 20    # 120.0
# 3 利用梯度下降法 循环迭代 求最优解/最小值
print(f"初始值:w:{w.data}, w.grad: {w.grad}, loss.mean():{loss.mean()}")

3.1-3.4

python 复制代码
# 记录损失均值
loss_list = []
for i in range(500):
    # 3.1 前向传播, 计算损失
    loss = w**2 + 20
    # 3.2 梯度清零 w.grad.zero_()
    if w.grad is not None:
        w.grad.zero_()
    # 3.3 反向传播 loss.backward()
    loss.mean().backward()
    # loss_mean' = 2*w
    # 3.4 更新参数 w.data = w.data - 0.01 * w.grad
    w.data = w.data - 0.01 * w.grad
    # loss_mean' =1/2* 2*w = w = [w1,w2]
    print(f"第{i+1}次迭代:w:{w.data}, w.grad:{w.grad.data}, loss.mean():{loss.mean()}")
    # 添加到loss_list
    loss_list.append(loss.mean().item())

绘制损失曲线

python 复制代码
iterations = range(500)
plt.figure(figsize=(12,8))
plt.plot(iterations,loss_list)
plt.xlabel("迭代次数")
plt.ylabel("损失均值loss.mean")
plt.grid()
plt.show()

三、detch() 函数

detach() 函数的功能,

解决 开启梯度计算 requires_grad=True 的张量,无法转为numpy对象的问题

1.定义张量,开启梯度计算requires_grad = True

python 复制代码
w = torch.tensor([1.0,2.0,3.0], requires_grad=True, dtype=torch.float32)
print(f"w:{w}, shape: {w.shape}, requires_grad: {w.requires_grad}")

2.直接转为numpy数组 (无法转

python 复制代码
# 2.直接转为numpy数组
# n1 = w.numpy()
# print(f"n1:{n1}, shape: {n1.shape}")

3.使用detach().numpy()来转数组

python 复制代码
t1 = w.detach()
print(f"t1:{t1}, shape: {t1.shape}, type: {type(t1)}, requires_grad: {t1.requires_grad}")
n2 = w.detach().numpy()
print(f"n2:{n2}, shape: {n2.shape}")

4.查看是否共享内存/浅拷贝 (浅拷贝

python 复制代码
n2[0]=28.0
print(f"w:{w}, shape: {w.shape}")
print(f"n2:{n2}, shape: {n2.shape}")

四、Pytorch框架_模型线性回归

1.准备数据集

2.构建模型

3.设置损失函数和优化器

4.模型训练

python 复制代码
"""
    Pytorch 框架 模型线性回归

    1.准备数据集
        numpy数组 -> 张量 -> 数据集对象Dataset -> 数据加载器DataLoader(分批次加载)
    2.构建神经网络模型
        nn.Linear()
    3.设置损失函数和优化器
        nn.MESLoss, optiom.SGD
    4.模型训练
        1.前向传播
        2.计算损失
        3.梯度清零
        4.反向传播
        5.更新参数  W新 = W旧 - 学习率*梯度
    5.模型测试
"""

import torch

#构造数据集对象
from torch.utils.data import TensorDataset
#数据加载器,按批次加载数据
from torch.utils.data import DataLoader
#提供 MSE 损失函数 和 线性层,线性用来模拟线性回归模型
from torch import nn
#提供各种优化器,用于更新模型参数,公司为 W新 = W旧 - 学习率lr * 梯度 grad
from torch import optim
#创建线性回归的示例数据集
from sklearn.datasets import make_regression

import matplotlib.pyplot as plt

# 1.准备数据集
def create_dataset():
    x, y, coef = make_regression(
        n_samples=100,      #样本数
        n_features=1,       #特征数
        n_targets=1,        #目标数
        noise= 10,          #噪声
        bias= 13.9,         #偏移
        coef=True,          #是否返回系数  真实的权重 w(斜率)
        random_state=5      #随机种子
    )

    # 转化为 张量
    x = torch.tensor(x,dtype=torch.float)
    y = torch.tensor(y,dtype=torch.float)

    return x, y, coef

# 2.模型训练
def train_model(x,y,coef):
    # <1> 张量 -> 数据集
    dataset = TensorDataset(x,y)
    # <2> 数据加载器
    dataloader = DataLoader(
        dataset,        #数据集
        batch_size=16,  #一次加载数量 批次大小  一般 64、32
        shuffle=True,   #是否打乱数据,训练时打乱,测试时不打乱
        drop_last=False #是否删除最后一个数量不够的批次,一般是False
    )
    # <3> 构建模型 - 这里是模拟线性回归
    model = nn.Linear(1, 1)

    # <4> 损失函数 - MSE损失函数
    loss_fn = nn.MSELoss()

    # <5> 优化器 - 随机梯度 SGD
    optimizer = optim.SGD(model.parameters(), lr=0.01)

    # <6> 模型训练
    # 定义梯度训练的轮次
    count = 100
    # 记录 每个轮次的平均损失
    total_losses = []

    # 开始遍历轮次 训练
    for epoch in range(count):
        # 1.初始化 当前轮次的训练总损失
        total_loss = 0.0
        # 2.初始化 当前轮次的总样本数.  总共是100个样本
        total_samples = 0
        # 3.根据批次 遍历数据 加载器,分批训练
        for x_train, y_train in dataloader:
            # 3.1 前向传播,计算预测值
            y_pred = model(x_train)
            # 3.2 计算损失
            # reshped(-1,1) 因为标签 y 只有1个,是标量 => 要升维度 (1,1)
            loss = loss_fn(y_pred, y_train.reshape(-1,1))
            # 3.3 梯度清零 - 因为在pytorch 中,梯度会自动累加
            optimizer.zero_grad()
            # 3.4 反向传播
            loss.backward()
            # 3.5 更新参数 W新 = W旧 - 学习率 lr * 梯度 grad
            optimizer.step()
            # 3.6 统计 训练损失 和 样本数.
            # 这批次的损失值 * 样本数
            total_loss += loss.item() * x_train.shape[0]
            total_samples += x_train.shape[0]
        # 4.计算当前批次的平均损失
        train_loss = total_loss / total_samples
        # 5.将每一批次的损失值 存到数组
        total_losses.append(train_loss)
        # 6.打印本轮训练的平均损失
        print(f"{epoch + 1}/{count}': | "
              f"{train_loss:.4f}")

    # <7> 可视化训练过程
    # 图 1
    plt.rcParams['font.family'] = 'Arial Unicode MS'
    print(f"损失列表:{total_losses}")
    plt.figure(figsize=(15,8))
    # 绘制第一个子图:训练损失曲线图
    plt.subplot(1,2,1)
    plt.title("训练损失曲线")
    x_epoch = range(count)
    plt.plot(x_epoch, total_losses, label="训练损失")
    plt.xlabel("epoch")
    plt.ylabel("loss")
    plt.grid()
    plt.legend()
    # 图 2 -------
    # 真实值和预测值的对比
    plt.subplot(1, 2, 2)
    plt.title("真实值和预测值的对比")
    plt.scatter(x, y, label="真实散点")
    # 计算理论的真实线性回归直线   codf.item() 是真实斜率    13.9 是截距 B
    y_true = [v*coef.item()+13.9 for v in x]
    plt.plot(x, y_true, label="真实线性回归")
    # 计算模型预测值
    with torch.no_grad():   # 关闭梯度计算
        """
        model(x) 得到的预测张量,原本连着梯度计算图(和模型权重、输入 x 绑定)
        .detach():强制断开和梯度图的所有联系,得到一个纯数值、无梯度、叶子张量
        .numpy():把断开后的张量转成 numpy 数组
        """
        y_pred = model(x).detach().numpy()
    # 绘制模型预测的线性回归直线
    plt.plot(x, y_pred, label="预测值")
    plt.xlabel("x")
    plt.ylabel("y")
    plt.grid()
    plt.legend()
    plt.show()



if __name__ == '__main__':
    x, y, coef = create_dataset()
    train_model(x,y,coef)
相关推荐
yejqvow122 小时前
如何在 Supabase 中安全实现用户“鼓掌”计数(防刷、防重放、防越权)
jvm·数据库·python
星浩AI2 小时前
手把手带你在 Windows 安装 Hermess Agent,并接入飞书 [喂饭级教程含踩坑经验]
人工智能·后端·agent
争渡假渡2 小时前
Claude Code 工作流 vs 人类程序员工作流
人工智能
海天一色y2 小时前
基于PyTorch的Oxford-IIIT Pet宠物品种细粒度分类:全流程实战指南
pytorch·分类·宠物
m0_678485452 小时前
SQL利用窗口函数实现轻量级报表设计_实战技巧
jvm·数据库·python
m0_747854522 小时前
CSS实现卡片式布局_浮动元素与clearfix的应用
jvm·数据库·python
2401_835956812 小时前
如何处理SQL查询中的逻辑重叠:AND OR嵌套优先级
jvm·数据库·python
配奇2 小时前
集成学习(Ensemble Learning)
人工智能·机器学习·集成学习
2301_796588502 小时前
Redis怎样优化大量Lua并发调用带来的CPU压力
jvm·数据库·python