线性回归模型

一、案例背景:

在这里插入图片描述

  • 其中每个特征xi都对应一个权重wi。

二、线性模型定义:

1.文字定义:

在这里插入图片描述

  • x表示一个样本一维向量,其中xi是样本的一个特征wi是每个特征对应的权重,模型定义如上图所示。

2.图像定义:

线性模型可以看做一个只有输入层和输出层的单层神经网络。
在这里插入图片描述

三、训练过程:

1.参数维度:

在这里插入图片描述

  • 特征数决定权重参数W维度:一个特征xi对应一个wi
  • 预测单元(神经元)个数/输出维度决定偏置值b维度:一个神经元对应一个偏置值b,而神经元个数又和输出维度相同。

2.训练集定义:

在这里插入图片描述
其中X为训练集,y为标签真实值。

  • xi表示训练集中的一个样本,是一个向量,包含了该样本的多个特征。(注:这里的xi就是(二)中的x)
  • yi是样本xi的真实值标签

3.损失函数:

3.1单个样本上的损失函数:

3.1.1损失函数定义:

在这里插入图片描述
其中y和yhat都是一个实数。

3.2整个batch上的损失函数:

3.2.1损失函数定义:

训练过程中计算损失是按照整个batch计算的。
在这里插入图片描述

  • 损失函数定义为模型在每个样本上的损失的均值。
  • 输入真实值和预测值后损失函数L是关于参数:一维向量W、偏置值b的函数
3.2.2损失函数简化:

将X和W进行如下定义:X加入一列全1的列向量,W加入参数值b。
在这里插入图片描述
由向量乘积运算可以将上述损失函数公式简写为:
在这里插入图片描述

4.训练目标定义:

在这里插入图片描述

  • 训练目标为:通过不断调整参数使得参数值带入L后损失值最小
  • 如何调整参数值?使用梯度下降算法

5.梯度下降算法:

5.1梯度定义:

梯度表示参数值变化的方向,参数值沿梯度负方向变化时损失值减少最快。
这里的X和w都是简化后的损失函数写法
在这里插入图片描述

5.2梯度下降算法定义:

上述损失函数的计算都是对整个训练集进行的,但是在整个训练集上计算梯度耗时太长,因此一般每次输入一个batch进行训练,而非上述一次性输入整个训练集进行训练计算损失

因此损失函数修改如下:

在这里插入图片描述
注意这里xi是一个样本
相应的梯度下降算法如下:
在这里插入图片描述
在这里插入图片描述

当一个batch进行预测得到预测值y后,损失函数计算损失,然后计算所有参数关于损失函数L的梯度,最后使用梯度下降算法更新参数值后进行下一个batch训练。

6.训练过程举例:******

以的一次训练过程为例:
1.获取一个batch,里面包含batch_size个样本,假设样本特征数为2,则输入维度为:batch_size×2×1(图片数×特征维度[2×1])。
2.参数W维度计算为2×1,参数b维度计算为1×1。
3.每个样本xi分别输入计算yi=Wxi+b,获得预测值yi。
4.整个batch中的输出组合成维度batch_size×1。
5.使用均方损失函数计算batch中所有样本的损失的平方,并取均值。
6.计算各个参数wi、b关于损失函数的梯度。
7.反向传播算法修改参数值。
8.输入下一个batch进行训练。

四、底层训练代码:

import random
import torch


# 1.构造样本数量为num_examples的训练集
true_w = torch.tensor([2, -3.4])# 向量w有两个参数
true_b = 4.2# 偏置值b有一个
def synthetic_data(w, b, num_examples):
    """这里的y = Xtrue_w + true_b是模拟的真实模型,用来构造训练集用的。"""
    X = torch.normal(0, 1, (num_examples, len(w)))# 构造均值为0、方差为1的num_examples个样本,其中每个样本有w个特征(w和特征一一对应)
    y = torch.matmul(X, w) + b# 构造每个样本的标签真实值
    return X, y.reshape((-1, 1))# X维度为num_examples*w,y维度为num_examples*1

# 2.读取训练集中的特征和标签
features, labels = synthetic_data(true_w, true_b, 1000)# features 中的每一行都包含一个长度为2的一维向量,labels 中的每一行都包含一哥标签值(一个标量)

# 3.将训练集划分为batch,每次训练读一个batch
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(indices[i:min(i + batch_size, num_examples)])
        yield features[batch_indices], labels[batch_indices]

# 4.模型参数赋初值
w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)# 向量w有两个参数
b = torch.zeros(1, requires_grad=True)# 偏置值b有一个

# 5.定义模型,X是一个batch,w、b是当前参数取值,返回当前batch上的预测结果一维向量(长度为batch中样本个数)
def linreg(X, w, b):
    """线性回归模型"""
    return torch.matmul(X, w) + b

# 6.定义损失函数,返回batch上各个样本的损失,一维向量
def squared_loss(y_hat, y):
    """均方损失"""
    return (y_hat - y.reshape(y_hat.shape))**2 / 2# 注意这里应该计算均值,但是这里却没有计算均值,而是方便代码编写就在后面计算了

# 7.定义梯度下降算法
def sgd(params, lr, batch_size):
    """小批量随机梯度下降"""
    with torch.no_grad():
        for param in params:# 依次更新每个参数
            param -= lr * param.grad / batch_size# 梯度下降算法,这里除以batch_size是因为我们之前的损失函数没有计算均值
            param.grad.zero_()# 梯度清零

# 8.模型训练
lr = 0.03# 学习率
num_epochs = 3# 训练轮数
net = linreg# 实例化线性模型对象
loss = squared_loss# 实例化损失函数对象
batch_size = 10# batch包含的样本数
# 执行epoch轮
for epoch in range(num_epochs):
    #每次取一个batch
    for X, y in data_iter(batch_size, features, labels):
        # 计算batch中样本的损失,是一个列向量
        l = loss(net(X, w, b), y)
        # 计算损失函数l关于每个参数的梯度
        l.sum().backward()
        # 梯度下降算法更新参数,继续下一个batch的训练
        sgd([w, b], lr, batch_size)

五、Pytorch版训练代码:

import numpy as np
import torch
from torch import nn
from torch.utils import data


# 1.构造样本数量为num_examples的训练集
true_w = torch.tensor([2, -3.4])# 向量w有两个参数
true_b = 4.2# 偏置值b有一个
def synthetic_data(w, b, num_examples):
    """这里的y = Xtrue_w + true_b是模拟的真实模型,用来构造训练集用的。"""
    X = torch.normal(0, 1, (num_examples, len(w)))# 构造均值为0、方差为1的num_examples个样本,其中每个样本有w个特征(w和特征一一对应)
    y = torch.matmul(X, w) + b# 构造每个样本的标签真实值
    return X, y.reshape((-1, 1))# X维度为num_examples*w,y维度为num_examples*1

# 2.读取训练集中的特征和标签
features, labels = synthetic_data(true_w, true_b, 1000)# features 中的每一行都包含一个长度为2的一维向量,labels 中的每一行都包含一哥标签值(一个标量)
dataset = data.TensorDataset(features, labels)# 转换为tensor数据类型

# 3.拆分训练集为多个batch
dataloader = data.DataLoader(dataset, batch_size=10, shuffle=True)

# 4.实例化线性模型,输入特征维度为(batch_size×2)2,标签维度为(batch_size×1)1
net = nn.Linear(2, 1)

# 5.模型参数赋初值
net.weight.data.normal_(0, 0.01)
net.bias.data.fill_(0)

# 6.损失函数
loss = nn.MSELoss()

# 7.梯度下降算法
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

# 8.训练过程
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in dataloader:
        l = loss(net(X), y)# 计算损失,这里net(X)和y是一维列向量,但是输出结果l会是一个值,因为由底层对损失列向量求了均值
        trainer.zero_grad()# 梯度清零
        l.backward()# 计算梯度
        trainer.step()# 梯度下降算法更新参数
  • 37
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姓蔡小朋友

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值