当前位置: 首页 > article >正文

深度学习2-线性回归表示

数据处理-模型训练-梯度下降回传

深度学习步骤

image-20250319153656305

目标

利用预测的w0,b0,使用生成数据求出真实的w,b即得到函数y=wx+b

给定500条数据,有关颜值、财富、幽默、人品四个方面对于按恋爱次数的影响到底有多大?下列为真实的w和b,需要我们设计合适的线性模型来进行拟合真实的函数

  • 实现了一个简单的线性回归模型,通过生成合成数据并使用梯度下降优化方法来训练模型参数。
  • 它采用了批量训练和 MAE 损失函数,通过可视化来检查模型拟合效果。

image-20250318224207996

image-20250319141122373

生成数据500*4的用户数据

loss=y^-y

import torch #框架
import matplotlib.pyplot as plt #画图
import random #随机

def create_data(w,b,data_num):#用于生成数据    w对应四个特征
    x = torch.normal(0,0.1,(data_num,len(w)))#长应为数据个数500行,宽应为w个数
    y = torch.matmul(x,w)+b #矩阵乘法

    #加噪声给y
    noise = torch.normal(0,0.1,y.shape)
    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)

plt.scatter(X[:,3],Y,1)#画散点图 (x某列,Y,1点大小)
plt.show()
  1. 导入库
import torch # 导入 PyTorch,用于张量操作和机器学习
import matplotlib.pyplot as plt # 用于绘图
import random # 用于生成随机数
  1. 定义生成数据的函数
def create_data(w, b, data_num):
    # w 对应四个特征
    x = torch.normal(0, 0.1, (data_num, len(w))) # 生成均值为 0,方差为 0.1 的正态分布数据,形状为 (500, 4)
    y = torch.matmul(x, w) + b # 线性关系:y = x*w + b
    
    # 加入噪声
    noise = torch.normal(0, 0.1, y.shape) # 生成同形状的噪声
    y += noise
    
    return x, y
  • torch.normal(0, 0.1, (data_num, len(w))):生成一个 500 行 4 列的正态分布张量,模拟 500 个样本,每个样本有 4 个特征。
  • torch.matmul(x, w) + b:对特征进行线性变换,生成真实的标签值。
  • 加入噪声,模拟真实数据中的误差。

  1. 设置参数
num = 500 # 样本数量
true_w = torch.tensor([8.1, 2, 2, 4]) # 真实权重(4 个特征)
true_b = torch.tensor(1.1) # 真实偏置

  1. 生成数据

X, Y = create_data(true_w, true_b, num)
  • X 形状为 (500, 4),表示 500 个样本,每个样本有 4 个特征。
  • Y 形状为 (500,),表示 500 个标签。

  1. 绘制散点图
plt.scatter(X[:, 3], Y, 1) # 取第 4 个特征(索引 3)作为横坐标
plt.show()
  • X[:, 3] 取出第 4 个特征作为横坐标。
  • Y 作为纵坐标。
  • 1 表示点的大小。

运行结果

  • 散点图展示的是第 4 个特征与标签之间的关系。
  • 如果线性关系明显,散点应该围绕在一条直线附近。
  • 加入噪声后,散点会有一定的离散度,但仍然呈现线性趋势。

image-20250319134057618

生成随机批数据

  1. 定义生成器函数
def datas_provider(data, label, batch_size):
    length = len(label) # 获取标签的长度(即样本数量)
    indexs = list(range(length)) # 创建索引列表 [0, 1, 2, ..., length-1]
    random.shuffle(index)  # 随机打乱索引,增加数据的随机性
    
    for each in range(0, length, batch_size): 
        get_indexs = indexs[each: each + batch_size] # 切片获取当前批次的索引
        get_data = data[get_indexs] # 根据索引取出对应的数据
        get_label = label[get_indexs] # 根据索引取出对应的标签
        
        yield get_data, get_label # 通过生成器返回数据和标签
  • range(0, length, batch_size):每次步长为 batch_size(16),生成批量的起始索引。
  • get_indexs = indexs[each: each + batch_size]:取出当前批次的样本索引。
  • data[get_indexs]:根据索引取出样本。
  • yield:生成器返回当前批次的数据和标签,供外部迭代使用。

  1. 设置一次性产生数据批量大小

batch_size = 16

  1. 调用生成器
for batch_x, batch_y in datas_provider(X, Y, batch_size):
    print(batch_x.shape)
    print(batch_y.shape)
    break
  • batch_x:一个批次的数据,形状为 (16, 4),表示每批 16 个样本,每个样本有 4 个特征。
  • batch_y:一个批次的标签,形状为 (16,)
  • break:只输出第一个批次。

输出示例

输出第一个批次的数据和标签形状:

torch.Size([16, 4])
torch.Size([16])

解释:

  • 16 表示批次大小(16 个样本)。
  • 4 表示每个样本有 4 个特征。
  • 16 表示每批对应的 16 个标签。

定义梯度函数

所有参数都带有梯度,都会保存在里面,需清0

image-20250319141030627

定义线性模型

def model(w, x, b):
    return torch.matmul(x, w) + b
  • 这个函数表示一个简单的线性模型。它根据输入 x 和权重 w 计算预测值,并加上偏置 b

定义 MAE 损失函数LOSS

def mae_loss(pred_y, y):
    return torch.mean(torch.abs(pred_y - y))  # 计算预测值与真实值之间的绝对误差
    #torch.sum(torch.abs(pred_y - y)/len(y))
  • 这里使用 MAE (Mean Absolute Error) 损失函数来衡量模型的预测值和实际值之间的误差。该函数计算预测值和实际值的绝对差的平均值。

梯度下降法优化参数

def sgd(params, lr):
    with torch.no_grad():  # 在不计算梯度的情况下更新参数
        for param in params:
            param -= lr * param.grad  # 按照学习率更新参数
            param.grad.zero_()  # 清空已经计算的梯度
  • 这里实现了一个 SGD (Stochastic Gradient Descent) 优化器,它根据计算的梯度更新参数。
  • lr 是学习率,表示每次更新的步长。param.grad.zero_() 用于在每次更新后清零梯度。

生成数据

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)  # 生成数据
  • true_wtrue_b 是真实的权重和偏置。
  • XY 是生成的输入数据和目标数据。

查看数据的散点图

plt.scatter(X[:, 3], Y, s=1)
plt.title("Generated Data")
plt.show()
  • 这部分代码绘制 X[:, 3]Y 之间的散点图。通过这个图可以查看生成的数据分布。

初始化模型参数

w = torch.normal(0, 0.01, true_w.shape, requires_grad=True)  # 初始化权重
b = torch.tensor(0.01, requires_grad=True)  # 初始化偏置
  • 在训练开始前,初始化权重 w 和偏置 b,并允许计算梯度。

定义超参数

learning_rate = 0.03
batch_size = 16
epochs = 50
  • 这里定义了超参数:学习率 learning_rate,批次大小 batch_size 和训练的轮数 epochs

训练过程

for epoch in range(epochs):
    total_loss = 0
    for batch_x, batch_y in data_provider(X, Y, batch_size):
        pred_y = model(w, batch_x, b)  # 使用当前参数进行预测
        loss = mae_loss(pred_y, batch_y)  # 计算损失
        loss.backward()  # 反向传播,计算梯度
        sgd([w, b], learning_rate)  # 使用SGD优化器更新参数
        total_loss += loss.item()  # 累加损失
    avg_loss = total_loss / (num / batch_size)  # 计算平均损失
    print(f"Epoch {epoch + 1:03d}, Loss: {avg_loss:.6f}")
  • 在训练循环中,使用批次数据进行预测、计算损失、反向传播以及更新参数。每个 epoch 输出一次平均损失。

输出结果

print(f"\n真实的参数值:w = {true_w.numpy()}, b = {true_b:.2f}")
print(f"预测的参数值:w = {w.detach().numpy()}, b = {b.detach().numpy():.2f}")
  • 训练结束后,打印真实的参数值和预测的参数值。

可视化结果

idx = 1
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy() * w[idx].detach().numpy() + b.detach().numpy(),
         color='red', label='Fitted line')
plt.scatter(X[:, idx].detach().numpy(), Y.detach().numpy(), s=1, label='Data points')
plt.title("Fitting Result")
plt.legend()
plt.show()

image-20250319221728084
基于预测的参数w0,b0经训练得到的拟合直线拟合真实数据

全部代码

import torch
import matplotlib.pyplot as plt
import random


# 生成数据函数
def create_data(w, b, data_num):
    x = torch.normal(0, 1, (data_num, len(w)))
    y = torch.matmul(x, w) + b
    noise = torch.normal(0, 0.1, y.shape)  # 加入噪声
    y += noise
    return x, y


# 批数据生成器
def data_provider(data, label, batch_size):
    length = len(label)
    indices = list(range(length))
    random.shuffle(indices)
    for i in range(0, length, batch_size):
        batch_indices = indices[i: i + batch_size]
        yield data[batch_indices], label[batch_indices]


# 定义线性模型
def model(w, x, b):
    return torch.matmul(x, w) + b


# 定义 MAE 损失函数
def mae_loss(pred_y, y):
    return torch.mean(torch.abs(pred_y - y))


# SGD优化器(梯度下降法更新参数)
def sgd(params, lr):
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad
            param.grad.zero_()


# 生成数据
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)

# 查看数据的散点图
plt.scatter(X[:, 3], Y, s=1)
plt.title("Generated Data")
plt.show()

# 初始化模型参数
w = torch.normal(0, 0.01, true_w.shape, requires_grad=True)
b = torch.tensor(0.01, requires_grad=True)

# 定义超参数
learning_rate = 0.03
batch_size = 16
epochs = 50

# 训练过程
for epoch in range(epochs):
    total_loss = 0
    for batch_x, batch_y in data_provider(X, Y, batch_size):
        pred_y = model(w, batch_x, b)
        loss = mae_loss(pred_y, batch_y)
        loss.backward()  # 反向传播
        sgd([w, b], learning_rate)
        total_loss += loss.item()

    avg_loss = total_loss / (num / batch_size)
    print(f"Epoch {epoch + 1:03d}, Loss: {avg_loss:.6f}")

# 输出结果
print(f"\n真实的参数值:w = {true_w.numpy()}, b = {true_b:.2f}")
print(f"预测的参数值:w = {w.detach().numpy()}, b = {b.detach().numpy():.2f}")

# 结果可视化
idx = 1
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy() * w[idx].detach().numpy() + b.detach().numpy(),
         color='red', label='Fitted line')
plt.scatter(X[:, idx].detach().numpy(), Y.detach().numpy(), s=1, label='Data points')
plt.title("Fitting Result")
plt.legend()
plt.show()


http://www.kler.cn/a/599049.html

相关文章:

  • Elasticsearch 中的数据分片问题
  • Linux中查找标准库函数的定义
  • 【容器运维】docker搭建私有仓库
  • SpringBoot分布式定时任务实战:告别重复执行的烦恼
  • 蓝桥杯_DS1302时钟
  • 游戏引擎学习第174天
  • 【C++复习】——类型转换
  • git,openpnp - 根据安装程序打包名称找到对应的源码版本
  • LeetCode 3038 相同分数的最大操作数目I
  • 基于单片机的农作物自动灌溉系统
  • 蓝桥杯第九天 2022 省赛 第 4 题 最少刷题数
  • nt!KeWaitForMultipleObjects函数分析之一个例子ExpWorkerThreadBalanceManager
  • 【玩转全栈】---- Django 基于 Websocket 实现群聊(解决channel连接不了)
  • 【QA】QT事件处理流程是怎么样的?
  • Linux内核Netfilter框架分析
  • 【CC2530 教程 二】CC2530定时器实现微秒、毫秒、秒延时函数
  • 【Vue3入门1】04-计算属性 + 侦听器
  • 01 Java微服务架构(SpringBootSpringCloudJDK)_企业级升级方案指导手册
  • 【计算机操作系统】深入剖析操作系统中的存储器管理:从基础到高级
  • LORA 中的 梯度外积是什么意思; 方差和协方差的实际含义:衡量变量的离散程度和变量间的线性相关性