刘二大人-Pytorch深度学习实践-用PyTorch实现线性回归-笔记与作业05
使用PyTorch实现线性回归
名词解释:张量、标量、向量、矩阵
-
张量:即前面提到的Tensor,是 PyTorch 存储数据和执行计算的基本单位,张量是一个多维数组,它是标量、向量和矩阵的广义统称。
-
标量:标量是一个零维张量 (0-D Tensor) ,它只包含一个数值,没有方向或大小之分。
- torch.tensor(5.0)
-
向量:向量是一个一维张量 (1-D Tensor),它包含一列有序的数值,只有大小和方向。
- torch.tensor([1, 2, 3])
-
矩阵:矩阵是一个二维张量 (2-D Tensor) ,它由行和列组成,是两个向量的排列。
- torch.tensor([[1, 2], [3, 4]])
[!TIP]
几个 [] 就是几维张量
前置关键代码解释
nn.Linear(in_features, out_features, bias=true)
一共三个主要参数需要填写,Linear源码如下图:

- in_features:输入特征数,或者说输入的维度,比如说你的输入矩阵是一个3*2的矩阵,每一行代表单个样本,也就是说一个样本有两个维度,即列数,那么这里就应该设置in_features=2
- out_features:输出特征数,同上。如果输出是一个4*3的矩阵,每一行代表单个样本,也就是有3个维度,那么就应该设置out_features=3
- bias:默认为True,用于是否要在计算过程中加上偏置项b
[!NOTE]
这里有一个很重要的思想转变,即输入输出的值,从"数字"变成“矩阵”
看网课时我一开始一直没理解老师为什么要一直使用矩阵的知识,我默认认为一个线性模型y = w*x + b中的x、y、w、b都只是一个数字。
但是现在要转变观念,X可以是一个m * n的矩阵,Y可以是一个 m * q 的矩阵
那么又引申出一个问题,W应该是怎样的矩阵?
当使用PyTorch进行线性回归时,将会遵循以下乘法规则:
至于为什么要对W进行转置,请往下看:
-
当你输入nn.Linear(3,2)时,也就意味着你的输入数据集X_Data是形状是 N * 3,输出数据集Y_Data的形状是 N * 2,总共有N个样本
-
如果采用上图的乘法顺序,W的性质应该刚好是 3 * 2,和你括号中输入的顺序是一致的,但是由于PyTorch内部规定了需要取转置后再乘(如下图),所以为了符合直觉,源代码中特地反转了。

optimizer = torch.optim.SGD(my_model.parameters(), lr=0.01)
- my_model.parameters() 的作用是返回一个迭代器 (iterator) ,其中包含了 my_model 实例中所有需要学习和更新的参数 (Parameter) 。
- 反正是pytorch帮忙找,用迭代找的,后续需要再深入学习。
执行my_model(x_data)会自动执行forward返回预测值
具体代码
import torch
from torch import nn ## nn 是 neural network 神经网络的缩写
import matplotlib.pyplot as plt
#定义数据集,设置为矩阵模式,3*1 的矩阵
x_data = torch.tensor([[1.0], [2.0], [3.0]], dtype=torch.float)
y_data = torch.tensor([[2.0], [4.0], [6.0]], dtype=torch.float)
class LinearRegression(nn.Module):
def __init__(self):
# 调用父类的初始化方法
super(LinearRegression, self).__init__()
# nn.Linear 自动创建并初始化 w 和 b,反正会自动,具体可以后续详细了解
self.linear = nn.Linear(1, 1)
# 前馈
def forward(self, x):
# 默认执行 y = xW^T + b.
return self.linear(x)
# 反馈,PyTorch会自动帮你求导,除非你自己写的效率比PyTorch还高
# 实例化自己的模型
my_model = LinearRegression()
# 均方误差损失函数
criterion = nn.MSELoss()
# 使用随机梯度下降优化器(即更新权重的算法)
optimizer = torch.optim.SGD(my_model.parameters(), lr=0.01)
# 打印训练前的参数
w_init = my_model.linear.weight.item()
b_init = my_model.linear.bias.item()
print(f"训练前参数: w={w_init:.4f}, b={b_init:.4f}")
# 3. 训练参数
num_epochs = 500
costs_list = []
epochs_list = []
for epoch in range(num_epochs):
# 每次迭代都需要执行的操作:
# (A) 梯度清零:使用优化器内置的方法,替代 w.grad.zero_()
optimizer.zero_grad()
# (B) 前向传播
y_pred = my_model(x_data)
# (C) 计算损失
loss = criterion(y_pred, y_data)
# (D) 反向传播:计算梯度
loss.backward()
# (E) 更新权重:使用优化器内置的方法,替代 with torch.no_grad(): W -= lr * W.grad
optimizer.step()
# 记录损失(使用更新后的权重计算)
# 如果不在意小精度,也可以直接costs_list.append(loss.item()),也就是使用旧的W
with torch.no_grad():
costs_list.append(criterion(my_model(x_data), y_data).item())
epochs_list.append(epoch)
if (epoch + 1) % 10 == 0:
current_w = my_model.linear.weight.item()
current_b = my_model.linear.bias.item()
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.6f}, w: {current_w:.4f}, b: {current_b:.4f}')
# 5. 最终预测和结果
print("-" * 40)
final_w = my_model.linear.weight.item()
final_b = my_model.linear.bias.item()
# 预测 x=4
x_test = torch.tensor([[4.0]], dtype=torch.float32)
y_test_pred = my_model(x_test).item()
print(f"训练后参数: w={final_w:.4f}, b={final_b:.4f}")
print(f"训练后预测 x=4, y_pred={y_test_pred:.4f}")
# 6. 绘图
plt.plot(epochs_list, costs_list)
plt.ylabel('MSE Loss')
plt.xlabel('Epoch')
plt.show()

使用其他优化器

更多推荐




所有评论(0)