一、前言
线性回归是机器学习的入门算法,也是理解梯度下降、监督学习的基础。 作为深度学习的初学者,本博客旨在为我的学习复盘以及记录我在学习中的收获。
二、实现步骤
2.1导入模块
python
import torch
import matplotlib.pyplot as plt #用于画图
import random #用于生成随机值
2.2生成线性数据集
我们需要构造符合 y = w*x +b 的线性数据集,其中,需要入噪音,来模拟我们现实生活中的扰动。
①生成带有噪声的线性数据集
python
# 生成均值为0、方差为1的随机特征矩阵,形状为(data_num, 特征数)
x = torch.normal(0, 1, (data_num, len(w)))
# 计算真实标签:y = X*w + b
y = torch.matmul(x, w) + b
# 添加均值为0、方差为0.01的噪声,模拟真实数据
noise = torch.normal(0, 0.01, y.shape)
y += noise
return x, y
②定义真实的权重和偏置(这些值就是我们模型需要去拟合的)
python
num = 500 # 数据集大小
true_w = torch.tensor([8.1, 2, 2, 4]) #权重,需要用矩阵表示
true_b = torch.tensor(1.1) #偏置
③可视化权重与标签的关系(以第二列权重为例)
python
X, Y = create_data(true_w, true_b, num)
plt.scatter(X[:, 1], Y, 1) # 1表示点的大小
plt.show()
2.3实现批次处理
①核心代码
python
def data_provider(data, label, batchsize): #每次访问这个函数,就可以提供一批数据
length = len(label)
indices = list(range(length)) #0到500的一个列表
#一般来说,不能按顺序取数据,缺少随机性
random.shuffle(indices) #打乱列表,保证数据的随机性
for each in range(0, length, batchsize): #步长16 16、32、48......
get_indices = indices[each: each+batchsize]
get_data = data[get_indices]
get_label = label[get_indices]
yield get_data, get_label #有存档点的return
②批次大小定义
python
batchsize = 16 # 批次大小
2.4定义模型、损失函数与优化器
线性回归的核心公式是 y = x*w + b,此功能用函数即可轻松实现
①定义线性回归模型
python
def fun(x, w, b):
pred_y = torch.matmul(x, w) + b
return pred_y
②MAE损失函数
损失函数是用于衡量模型预测值和现实值差距的函数,本代码采用平均绝对误差的方法

python
#定义Loss
def maeloss(pre_y, y):
return torch.sum(abs(pre_y-y))/len(y) #先求绝对值之和,在取平均
③随机梯度下降优化器
python
#梯度下降 求导,随机梯度下降
def sgd(paras, lr): #参数,学习率
#我们只需要偏差loss产生的梯度
with torch.no_grad(): #属于这句代码的部分,不产生梯度
for para in paras:
para -= para.grad * lr
para.grad.zero_() #使用过的梯度清零
lr = 0.03 #学习率
2.5模型初始化与训练
①初始化模型参数
首先,我们需要初始化我们的权重 w 和偏置 b
python
# 初始化权重和偏置(正态分布随机值)
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True) #这个w需要计算梯度
b_0 = torch.tensor(0.01, requires_grad=True) #这个b需要计算梯度
print("初始化参数:w={}, b={}".format(w_0, b_0))
②多轮训练
这个训练的核心逻辑是:
遍历epoch → 按批次读取数据 → 计算预测值 → 计算损失 → 求梯度 → 更新参数
持续多轮
python
#开始训练 50轮
epochs = 50
for epoch in range(epochs):
data_loss = 0 #累计当前轮次的总损失
for batch_x, batch_y in data_provider(X, Y, batchsize):
pred_y = fun(batch_x, w_0, b_0) #计算预测值
loss = maeloss(pred_y, batch_y) #计算损失
loss.backward() #回传,计算梯度
sgd([w_0, b_0], lr) #更新参数
data_loss += loss #累计损失
print("epoch %03d: loss: %.6f"%(epoch, data_loss)) #打印损失
③对比真实值与训练后得到的参数
python
print("真实参数:w={}, b={}".format(true_w, true_b))
print("训练后参数:w={}, b={}".format(w_0.detach(), b_0.detach()))
2.6结果可视化
选取一个权重(以第1列为例)
python
idx = 0 #x取第一列,那么w0也只能取第一个值
#该模型生成的线:
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy()*w_0[idx].detach().numpy()+b_0.detach().numpy())
plt.scatter(X[:, idx], Y, 1) #原始数据点
plt.show()
