这段代码实现了一个完整的线性回归模型,从数据生成、数据加载、模型定义、损失函数、优化器到训练和可视化。
我们使用随机梯度下降(SGD)优化器,通过最小化平均绝对误差(MAE)来学习线性模型的参数(权重和偏置)。
最终,我们比较了训练得到的参数和真实参数,并可视化了其中一个特征与标签的关系以及模型预测的直线。



1.导入必要的库
import torch
import matplotlib.pyplot as plt #画图的

import random #随机函数

2.定义生成数据的函数
def create_data(w, b, data_num):  #生成数据
    x = torch.normal(0, 1, (data_num, len(w)))
    y = torch.matmul(x, w) + b    #matmul表示矩阵相乘

    noise = torch.normal(0, 0.01, y.shape)#噪声要加到y上
    y +=noise

    return x, y
3.设置参数并生成数据
num = 500

true_w = torch.tensor([8.1, 2, 2, 4])
true_b = torch.tensor(1.1)

X, Y = create_data(true_w, true_b, num)


4.绘制散点图
plt.scatter(X[:, 3], Y, 1)
plt.show()

5.定义数据提供器 data_provider
def data_provider(data, label, batchsize):      #每次访问这个函数, 就能提供一批数据
    length = len(label)
    indices = list(range(length))
    #range(length):生成一个从 0 到 length-1 的整数序列
    #list():将 range 对象转换为 Python 列表
    random.shuffle(indices)#我不能按顺序取  把数据打乱

    for each in range(0, length, batchsize):
        get_indices = indices[each: each+batchsize] # 获取一个批次的索引
        get_data = data[get_indices] # 获取批次数据
        get_label = label[get_indices] # 获取批次标签

        yield get_data, get_label  #有存档点的return, 以生成器的方式返回,避免一次性加载所有数据

6.设置批次大小并测试数据提供器
batchsize = 16
# for batch_x, batch_y in data_provider(X, Y, batchsize):
#     print(batch_x, batch_y)
#

7.定义模型函数 fun
def fun(x, w, b):#这就是我们的线性模型:y = xw + b。
    pred_y = torch.matmul(x, w) + b
    return pred_y

8.定义损失函数 maeLoss
def maeLoss(pre_y, y):
    return torch.sum(abs(pre_y - y))/len(y)

9.定义优化器 sgd(随机梯度下降)
def sgd(paras, lr):
    with torch.no_grad():
        for para in paras:
            para -= para.grad * lr # 更新参数
            para.grad.zero_() # 将梯度归零


10.设置学习率和初始化参数
lr = 0.03 # 学习率
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad= True) # 初始化权重,需要计算梯度
b_0 = torch.tensor(0.01, requires_grad=True) # 初始化偏置,需要计算梯度
print(w_0, b_0)


11.训练模型
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))


12.打印训练得到的参数和真实参数
print("真实的函数值是", true_w, true_b)
print("训练得到的参数值是", w_0, b_0)


13.绘制训练结果
idx = 3 # 选择第3个特征进行绘制
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()

真实参数(w_true, b_true) 
    ↓
生成数据(X, Y) = X * w_true + b_true + 噪声
    ↓
分批加载 → (batch_X, batch_Y)
    ↓
模型预测 → pred_Y = batch_X * w_0 + b_0
    ↓
计算损失 → MAE(pred_Y, batch_Y)
    ↓
反向传播 → 计算梯度(grad_w, grad_b)
    ↓
参数更新 → w_0 = w_0 - lr * grad_w
           b_0 = b_0 - lr * grad_b

更多推荐