目录
[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数组 (无法转))
[4.查看是否共享内存/浅拷贝 (浅拷贝)](#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)