具有品牌的做网站/网络推广的方法有多选题
自动微分模块
自动微分就是自动计算梯度值,也就是计算导数。
- 什么是梯度
- 对函数求导的值就是梯度
- 什么是梯度下降法
- 是一种求最优梯度值的方法,使得损失函数的值最小
- 梯度经典语录
- 对函数求导得到的值就是梯度
(在数值上的理解)
(在方向上理解)
训练神经网络时,最常用的算法就是反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应参数的梯度进行调整。为了计算这些梯度,PyTorch内置了名为 torch.autograd 的微分模块。它支持任意计算图的自动梯度计算:

接下来我们使用这个结构进行自动微分模块的介绍,我们使用 backward 方法、grad 属性来实现梯度的计算和访问。
梯度基本计算
- pytorch不支持向量张量对向量张量的求导,只支持标量张量对向量张量的求导
- x如果是张量,y必须是标量(一个值)才可以进行求导
- 计算梯度: y.backward(), y是一个标量
- 获取x点的梯度值: x.grad, 会累加上一次的梯度值
- 标量张量梯度计算
# 定义一个标量张量(点)
# requires_grad=:默认为False,不会自动计算梯度;为True的话是将自动计算的梯度值保存到grad中
x = torch.tensor(10, requires_grad=True, dtype=torch.float32)
print("x-->", x)# 定义一个曲线
y = 2 * x ** 2
print("y-->", y)
# 查看梯度函数类型,即曲线函数类型
print(y.grad_fn)# 计算x点的梯度
# 此时y是一个标量,可以不用使用y.sum()转换成标量
print("y.sum()-->", y.sum())
# y'|(x=10) = (2*x**2)'|(x=10) = 4x|(x=10) = 40
# 因为y是一个标量,所以不需要调用y.sum().backward()方法会自动计算y关于x的梯度,并将结果存储在x.grad中。#y.sum().backward()
y.backward()# 打印x的梯度值
print("x的梯度值是:", x.grad)"""
x--> tensor(10., requires_grad=True)
y--> tensor(200., grad_fn=<MulBackward0>)
<MulBackward0 object at 0x000002042A749420>
y.sum()--> tensor(200., grad_fn=<SumBackward0>)
x的梯度值是: tensor(40.)
"""
y.sum()函数用于计算张量y中所有元素的总和。这个函数非常有用,特别是在处理多维张量时,可以将多维张量缩减为一个标量值。这在许多深度学习任务中非常常见,例如在计算损失函数时,通常需要将模型的输出张量缩减为一个标量损失值,以便进行反向传播。
- 向量张量梯度计算
# 定义一个向量张量(点)
x = torch.tensor([10, 20], requires_grad=True, dtype=torch.float32)
print("x-->", x)# 定义一个曲线
y = 2 * x ** 2
print("y-->", y)# 计算梯度
# x和y都是向量张量,不能进行求导,需要将y转换成标量张量-->y.sum()
# y'|(x=10) = (2*x**2)'|(x=10) = 4x|(x=10) = 40
# y'|(x=20) = (2*x**2)'|(x=20) = 4x|(x=20) = 80
y.sum().backward()# 打印x的梯度
print("x.grad-->", x.grad)"""
x--> tensor([10., 20.], requires_grad=True)
y--> tensor([200., 800.], grad_fn=<MulBackward0>)
x.grad--> tensor([40., 80.])
"""
梯度下降法求最优解
- 梯度下降法公式: w = w - r * grad (r是学习率, grad是梯度值)
- 清空上一次的梯度值: x.grad.zero_()
# 求 y = x**2 + 20 的极小值点 并打印y是最小值时 w的值(梯度)
# 1 定义点 x=10 requires_grad=True dtype=torch.float32
# 2 定义函数 y = x**2 + 20
# 3 利用梯度下降法 循环迭代1000 求最优解
# 3-1 正向计算(前向传播)
# 3-2 梯度清零 x.grad.zero_()
# 3-3 反向传播
# 3-4 梯度更新 x.data = x.data - 0.01 * x.grad# 1 定义点x=10 requires_grad=True dtype=torch.float32
x = torch.tensor(10, requires_grad=True, dtype=torch.float32)# 2 定义函数 y = x ** 2 + 20
y = x ** 2 + 20
print('开始 权重x初始值:%.6f (0.01 * x.grad):无 y:%.6f' % (x, y))# 3 利用梯度下降法 循环迭代1000 求最优解
for i in range(1, 1001):# 3-1 正向计算(前向传播)y = x ** 2 + 20# 3-2 梯度清零 x.grad.zero_()# 默认张量的 grad 属性会累加历史梯度值 需手工清零上一次的提取# 一开始梯度不存在, 需要做判断if x.grad is not None:x.grad.zero_()# 3-3 反向传播y.sum().backward()# 3-4 梯度更新 x.data = x.data - 0.01 * x.grad# x.data是修改原始x内存中的数据,前后x的内存空间一样;如果使用x,此时修改前后x的内存空间不同x.data = x.data - 0.01 * x.grad # 注:不能 x = x - 0.01 * x.grad 这样写print('次数:%d 权重x: %.6f, (0.01 * x.grad):%.6f y:%.6f' % (i, x, 0.01 * x.grad, y))print('x:', x, x.grad, 'y最小值', y)
梯度计算注意点
- 不能将自动微分的张量转换成numpy数组,会发生报错,可以通过detach()方法实现
# 定义一个张量
x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)# 将x张量转换成numpy数组
# 发生报错,RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
# 不能将自动微分的张量转换成numpy数组
# print(x1.numpy())# 通过detach()方法产生一个新的张量,作为叶子结点
x2 = x1.detach()
# x1和x2张量共享数据,但是x2不会自动微分
print(x1.requires_grad)
print(x2.requires_grad)
# x1和x2张量的值一样,共用一份内存空间的数据
print(x1.data)
print(x2.data)
print(id(x1.data))
print(id(x2.data))# 将x2张量转换成numpy数组
print(x2.numpy())
9.4 自动微分模块应用
import torch# 输入张量 2*5
x = torch.ones(2, 5)
# 目标值是 2*3
y = torch.zeros(2, 3)
# 设置要更新的权重和偏置的初始值
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
# 设置网络的输出值
z = torch.matmul(x, w) + b # 矩阵乘法# 设置损失函数,并进行损失的计算
loss = torch.nn.MSELoss()
loss = loss(z, y)
# 自动微分
loss.backward()
# 打印 w,b 变量的梯度
# backward 函数计算的梯度值会存储在张量的 grad 变量中
print("W的梯度:", w.grad)
print("b的梯度", b.grad)
"""
W的梯度: tensor([[-1.7421, -3.0443, 0.4371],[-1.7421, -3.0443, 0.4371],[-1.7421, -3.0443, 0.4371],[-1.7421, -3.0443, 0.4371],[-1.7421, -3.0443, 0.4371]])
b的梯度 tensor([-1.7421, -3.0443, 0.4371])
"""
PyTorch构建线性回归模型
我们使用 PyTorch 的各个组件来构建线性回归模型。在pytorch中进行模型构建的整个流程一般分为四个步骤:
- 准备训练集数据
- 构建要使用的模型
- 设置损失函数和优化器
- 模型训练

要使用的API:
- 使用 PyTorch 的 nn.MSELoss() 代替平方损失函数
- 使用 PyTorch 的 data.DataLoader 代替数据加载器
- 使用 PyTorch 的 optim.SGD 代替优化器
- 使用 PyTorch 的 nn.Linear 代替假设函数
例子
import torch
from torch.utils.data import TensorDataset # 构造数据集对象
from torch.utils.data import DataLoader # 数据加载器
from torch import nn # nn模块中有平方损失函数和假设函数
from torch import optim # optim模块中有优化器函数
from sklearn.datasets import make_regression # 创建线性回归模型数据集
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号# 构造数据集
def create_dataset():# 使用 make_regression 生成回归数据集x, y, coef = make_regression(n_samples=100, # 样本数量n_features=1, # 特征数量noise=10, # 噪声水平coef=True, # 返回系数bias=14.5, # y轴截距random_state=0) # 随机种子,确保结果可复现# 将构建数据转换为张量类型x = torch.tensor(x, dtype=torch.float32) # 确保数据类型为 float32y = torch.tensor(y, dtype=torch.float32) # 确保数据类型为 float32return x, y, coef# 训练模型
def train():# 构造数据集x, y, coef = create_dataset()# 构造数据集对象dataset = TensorDataset(x, y)# 构造数据加载器# dataset=:数据集对象# batch_size=:批量训练样本数据# shuffle=:样本数据是否进行乱序dataloader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)# 构造模型# in_features指的是输入的二维张量的大小,即输入的[batch_size, size]中的size# out_features指的是输出的二维张量的大小,即输出的[batch_size,size]中的sizemodel = nn.Linear(in_features=1, out_features=1)# 构造平方损失函数criterion = nn.MSELoss()# 构造优化函数# params=model.parameters():训练的参数,w和b# lr=1e-2:学习率, 1e-2为10的负二次方print("w和b-->", list(model.parameters()))print("w-->", model.weight)print("b-->", model.bias)optimizer = optim.SGD(params=model.parameters(), lr=1e-2)# 初始化训练次数epochs = 100# 损失的变化epoch_loss = [] total_loss=0.0 train_sample=0.0for _ in range(epochs):for train_x, train_y in dataloader:# 将一个batch的训练数据送入模型y_pred = model(train_x.type(torch.float32))# 计算损失值loss = criterion(y_pred, train_y.reshape(-1, 1).type(torch.float32))total_loss += loss.item() train_sample += len(train_y)# 梯度清零optimizer.zero_grad()# 自动微分(反向传播)loss.backward()# 更新参数optimizer.step()# 获取每个batch的损失 epoch_loss.append(total_loss/train_sample)# 打印回归模型的wprint(model.weight)# 打印回归模型的bprint(model.bias)# 绘制损失变化曲线 plt.plot(range(epochs), epoch_loss) plt.title('损失变化曲线') plt.grid() plt.show()# 绘制拟合直线plt.scatter(x, y)x = torch.linspace(x.min(), x.max(), 1000)y1 = torch.tensor([v * model.weight + model.bias for v in x])y2 = torch.tensor([v * coef + 14.5 for v in x])plt.plot(x, y1, label='训练')plt.plot(x, y2, label='真实')plt.grid()plt.legend()plt.show()if __name__ == '__main__':train()


TensorDataset
在 PyTorch 中,TensorDataset 是一个非常方便的类,用于将多个张量组合成一个数据集对象。这个数据集对象可以与 DataLoader 一起使用,以便在训练过程中批量加载数据并进行乱序等操作。
TensorDataset 的使用假设你有两个张量 x 和 y,分别表示特征和目标值,你可以使用 TensorDataset 将它们组合成一个数据集对象。
以下是一个完整的示例,展示了如何使用 TensorDataset 和 DataLoader:
import torch
from torch.utils.data import TensorDataset, DataLoader
from sklearn.datasets import make_regression# 生成回归数据集
x, y, coef = make_regression(n_samples=100, n_features=1, noise=10, coef=True, bias=14.5, random_state=0)# 将数据转换为 PyTorch 张量
x = torch.tensor(x, dtype=torch.float32)
y = torch.tensor(y, dtype=torch.float32)# 创建 TensorDataset 对象
dataset = TensorDataset(x, y)# 创建 DataLoader 对象
dataloader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)# 使用 DataLoader 加载数据
for batch_idx, (batch_x, batch_y) in enumerate(dataloader):print(f"Batch {batch_idx + 1}:")print(f" x: {batch_x}")print(f" y: {batch_y}")print()
代码解释
- 生成回归数据集:使用 make_regression 生成回归数据集,生成100个样本,每个样本有一个特征,噪声水平为10,y轴截距为14.5,随机种子为0。
- 将数据转换为 PyTorch 张量:x 和 y 被转换为浮点型张量。
- 创建 TensorDataset 对象:TensorDataset(x, y) 将特征 x 和目标值 y 组合成一个数据集对象 dataset。
- 创建 DataLoader 对象:DataLoader(dataset=dataset, batch_size=16, shuffle=True) 创建一个 DataLoader 对象,批量大小为16,数据在每个轮次开始时会进行乱序。
- 使用 DataLoader 加载数据:使用 for 循环遍历 DataLoader,每次迭代获取一个批次的数据 batch_x 和 batch_y,并打印出来。