线性回归模型训练
这段代码是一个简单的线性回归模型训练过程,主要步骤包括数据生成、数据提供器、预测函数、损失函数、优化算法以及训练和可视化结果。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
这段代码是一个简单的线性回归模型训练过程,主要步骤包括数据生成、数据提供器、预测函数、损失函数、优化算法以及训练和可视化结果。下面详细解释每一部分的作用:
提示:以下是本篇文章正文内容,下面案例可供参考
一、导入必要的库
import os
from contourpy.util import data
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import torch
import matplotlib.pyplot as plt #画图的
import random #随机
这些库分别用于环境配置、数据处理、绘图和随机数生成。
os 和 contourpy.util.data 相关的导入在这里没有实际用途,可以忽略。这里主要是解决某个本地配置的重名问题。
torch: PyTorch 库,用于深度学习模型的构建和训练。
matplotlib.pyplot: 用于绘制图表。
random: 用于生成随机数。
二、生成数据
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
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)
create_data 函数用于生成模拟数据集。这里我们生成了500个样本,每个样本有四个特征,并且这些样本遵循一个线性关系 y=Xw+b 加上一些噪声。
- x = torch.normal(0, 1, (data_num, len(w))): 生成一个均值为0、标准差为1的正态分布随机数张量,形状为 (data_num, len(w)),即每个样本有四个特征。这里表示行数为data_num,列数为len(w)。
- y = torch.matmul(x, w) + b: 计算目标变量 y,其中 torch.matmul(x, w) 表示矩阵乘法 y=Xw ,然后加上偏置 b。
- noise = torch.normal(0, 0.01, y.shape): 生成一个均值为0、标准差为0.01的正态分布噪声张量,形状与 y 相同(形状说明直接用的y.shape)。
num = 500: 设置生成的数据样本数量为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): 调用 create_data 函数生成数据集 X 和 Y。
三、绘制散点图
plt.scatter(X[:, 0], Y, 1)
plt.show()
使用matplotlib库绘制第一个特征与目标变量之间的散点图,以便初步观察数据分布情况。
plt.scatter(X[:, 0], Y, 1): 使用 Matplotlib 绘制第一个特征与目标变量之间的散点图。
- X[:, 0]: 提取所有样本的第一个特征。
- Y: 提供对应的目标变量。
- 1: 设置散点的大小。
plt.show(): 显示图形。
四、定义数据提供器
def data_provider(data, label, batchsize): #每次访问这个函数,就能提供一批数据
length = len(data) #length:500
indices = list(range(length)) #0~500的一个列表
#我不能按顺序取 把数据打乱
random.shuffle(indices)
for each in range(0, length, batchsize):
get_indices = indices[each:each+batchsize] #batchsize步长为16,即16个数据为一组
get_data = data[get_indices]
get_label = label[get_indices]
yield get_data, get_label #有存档点的return 即会保留上一次循环的数据
batch_size = 16
data_provider 是一个生成器函数,它每次返回一个批次的数据(这里是16个样本),并且在每次调用时都会打乱数据顺序以减少过拟合的风险。
- length = len(data): 获取数据集的长度(这里是500)。
- indices = list(range(length)): 创建一个索引列表 [0, 1, …, 499]。
- random.shuffle(indices): 打乱索引列表,确保每次获取的数据顺序不同。
- for each in range(0, length, batchsize): 按照 batchsize 分割数据集。
- get_indices = indices[each:each+batchsize]: 获取当前批次的索引。
- get_data = data[get_indices]: 根据索引获取当前批次的数据。
- get_label = label[get_indices]: 根据索引获取当前批次的标签。
- yield get_data, get_label: 返回当前批次的数据和标签,并暂停执行,等待下一次调用。
batch_size = 16: 设置每个小批量的数据量为16。
五、定义预测函数
def fun(x, w, b):
pred_y = torch.matmul(x, w) + b
return pred_y
fun 函数用于计算给定输入特征 x 和参数 w、b 下的目标值预测
- pred_y = torch.matmul(x, w) + b: 计算预测值 y’=Xw+b。
- return pred_y: 返回预测值。
六、定义损失函数
def maeLoss(pre_y, y):
return torch.sum(abs(pre_y - y)) / len(y)
maeLoss 计算均绝对误差(MAE),这是一种常用的回归任务损失函数,衡量预测值与真实值之间的差异。
torch.sum(abs(pre_y - y)): 计算预测值与真实值之间绝对误差的总和。
/ len(y): 将总和除以样本数量,得到平均值。
七、定义优化算法
def sgd(paras, lr): #随机梯度下降,更新参数
with torch.no_grad(): #属于这句代码的部分,不计算梯度
for para in paras:
para -= para.grad * lr #lr为学习率 不能写成para = para - para.grad*lr(这会新创一个para)
para.grad.zero_() #使用过的梯度,归0
sgd 实现了随机梯度下降法来更新模型参数。通过减去学习率乘以参数梯度来调整权重,并清空梯度以备下次迭代使用。
- with torch.no_grad(): 在此上下文中,禁用梯度计算,防止在更新参数时影响后续的梯度计算。
- for para in paras: 遍历所有需要更新的参数(这里是权重 w 和偏置 b)。
- para -= para.grad * lr: 更新参数,通过减去学习率乘以参数的梯度(不可以para = para - lr*para.grad,因为会新创一个para)。
- para.grad.zero_(): 清空参数的梯度,以便下次迭代重新计算。
八、初始化参数并开始训练
lr = 0.03
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True) #这个w需要计算梯度
b_0 = torch.tensor(0.01, requires_grad=True)
print(w_0, b_0)
epochs = 50 #要训练的轮数
for epoch in range(epochs):
data_loss = 0
for batch_x, batch_y in data_provider(X, Y, batch_size):
pred_y = fun(batch_x, w_0, b_0)
loss = maeLoss(pred_y, batch_y) #pred_y是预测值 batch_y是真实值
loss.backward() #梯度回传
sgd([w_0, b_0], lr)
data_loss += loss
print("epoch %03d: loss: %.6f"%(epoch, data_loss))
初始化权重 w_0 和偏置 b_0,然后进行多轮训练(这里选择50轮)。每一轮中,从数据提供器获取一个小批量数据,计算预测值和损失,并通过反向传播更新参数。最后打印出每轮的总损失。
初始化参数:
- w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True): 初始化权重 w_0,设置其形状与真实权重相同,并启用梯度计算。
- b_0 = torch.tensor(0.01, requires_grad=True): 初始化偏置 b_0,并启用梯度计算。
- print(w_0, b_0): 打印初始化后的权重和偏置。
开始训练:
- data_loss = 0: 初始化本轮的总损失。
- for batch_x, batch_y in data_provider(X, Y, batch_size): 从数据提供器获取一个小批量数据。
- pred_y = fun(batch_x, w_0, b_0): 计算预测值。
- loss = maeLoss(pred_y, batch_y): 计算损失。
- loss.backward(): 反向传播,计算梯度。
- sgd([w_0, b_0], lr): 使用 SGD 更新参数。
- data_loss += loss: 累加当前批次的损失。
- print(“epoch %03d: loss: %.6f”%(epoch, data_loss)): 打印每轮的总损失。
九、输出真实的参数和训练得到的参数
print("真实的函数值是", true_w, true_b)
print("训练得到的参数值是", w_0, b_0)
分别打印真实的和训练得到的权重和偏置
十、可视化结果
idx = 0 #取第一列(行)
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()
最后,根据训练得到的参数绘制一条直线,表示模型学到的关系,并与原始数据点一起显示出来,以便直观地评估模型性能。
idx = 0: 设置要可视化的特征列为第一个特征。
plt.plot(X[:,idx].detach().numpy(), X[:,idx].detach().numpy()*w_0[idx].detach().numpy() + b_0.detach().numpy()): 绘制训练得到的线性回归模型的拟合直线。
- X[:,idx].detach().numpy(): 提取第一个特征并转换为 NumPy 数组。
- X[:,idx].detach().numpy()*w_0[idx].detach().numpy() + b_0.detach().numpy(): 计算对应的预测值。
plt.scatter(X[:, idx], Y, 1): 绘制原始数据点。
plt.show(): 显示图形
更多推荐

所有评论(0)