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

【pytorch-04】:线性回归案例(手动构建)

文章目录

  • 1 构建数据集
  • 2 构建假设函数
  • 3 损失函数
  • 4 优化方法
  • 5 训练函数
  • 6.总结

1 构建数据集

为什么构建数据加载器?
在进行训练的时候都是采用的不是全部的数据,而是采用一个batch_size的数据进行训练,每次向模型当中送入batch_size数据,所以需要一个能够按照batch_size生成数据的数据加载器

import torch
from sklearn.datasets import make_regression # 构造数据加载器
import matplotlib.pyplot as plt
import random


# 1. 构建数据集

def create_dataset():
    # n_samples - 100 样本数量
    # n_feature - 设置特征个数
    # noise - 设置噪声,可以进行调整,出现波动
    # coef = True - 需要权重
    # bias = 14.5 - 偏置
    # random_state = 0 - 能够复现数据
    x, y, coef = make_regression(n_samples=100,
                                 n_features=1,
                                 noise=10,
                                 coef=True,
                                 bias=14.5,
                                 random_state=0)

    # 将构建数据转换为张量类型
    x = torch.tensor(x)
    y = torch.tensor(y)

    return x, y, coef


# 2. 构建数据加载器, 按照一定的数据量产生数据
def data_loader(x, y, batch_size):

    # 2.1 计算下样本的数量
    data_len = len(y)
    # 2.2 构建数据索引
    data_index = list(range(data_len))
    # 2.3 数据集打乱
    random.shuffle(data_index)
    # 2.4 计算总的batch数量
    batch_number = data_len // batch_size

    # 遍历一个batch
    for idx in range(batch_number):
        
        start = idx * batch_size
        end = start + batch_size

        batch_train_x = x[start: end]
        batch_train_y = y[start: end]

        yield batch_train_x, batch_train_y


def test01():

    x, y = create_dataset()
    plt.scatter(x, y)
    plt.show()
    
    
    for x, y in data_loader(x, y, batch_size=10):
        print(y)

2 构建假设函数

# 假设函数 y = wx + b
# 只有一个特征值,所以w初始值为一个标量,b的初始值也是一个标量
w = torch.tensor(0.1, requires_grad=True, dtype=torch.float64)
b = torch.tensor(0.0, requires_grad=True, dtype=torch.float64)

def linear_regression(x):
    return w * x + b

3 损失函数

# 损失函数,采用MAS作为损失函数
def square_loss(y_pred, y_true):
    return (y_pred - y_true) ** 2

4 优化方法

# 优化方法 - 采用梯度下降法,进行权重参数的更新
def sgd(lr=1e-2):
    # 此处除以 16 使用的是批次样本的平均梯度值
    w.data = w.data - lr * w.grad.data / 16
    b.data = b.data - lr * b.grad.data / 16

5 训练函数

import torch
from sklearn.datasets import make_regression # 构造数据集
import matplotlib.pyplot as plt
import random


# 1. 构建数据集

def create_dataset():
    # n_samples - 100 样本数量
    # n_feature - 设置特征个数
    # noise - 设置噪声,可以进行调整,出现波动
    # coef = True - 需要权重
    # bias = 14.5 - 偏置
    # random_state = 0 - 能够复现数据
    x, y, coef = make_regression(n_samples=100,
                                 n_features=1,
                                 noise=10,
                                 coef=True,
                                 bias=14.5,
                                 random_state=0)

    # 将构建数据转换为张量类型
    x = torch.tensor(x)
    y = torch.tensor(y)

    return x, y, coef


# 2. 构建数据加载器, 按照一定的数据量产生数据
def data_loader(x, y, batch_size):

    # 2.1 计算下样本的数量
    data_len = len(y)
    # 2.2 构建数据索引
    data_index = list(range(data_len))
    # 2.3 数据集打乱
    random.shuffle(data_index)
    # 2.4 计算总的batch数量
    batch_number = data_len // batch_size

    # 遍历一个batch
    for idx in range(batch_number):

        start = idx * batch_size
        end = start + batch_size

        batch_train_x = x[start: end]
        batch_train_y = y[start: end]

        yield batch_train_x, batch_train_y


def test01():

    x, y = create_dataset()
    plt.scatter(x, y)
    plt.show()
    
    
    for x, y in data_loader(x, y, batch_size=10):
        print(y)


# 假设函数 y = wx + b
# 只有一个特征值,所以w初始值为一个标量,b的初始值也是一个标量
w = torch.tensor(0.1, requires_grad=True, dtype=torch.float64)
b = torch.tensor(0.0, requires_grad=True, dtype=torch.float64)

def linear_regression(x):
    return w * x + b


# 损失函数,采用MAS作为损失函数
def square_loss(y_pred, y_true):
    return (y_pred - y_true) ** 2


# 优化方法 - 采用梯度下降法,进行权重参数的更新
def sgd(lr=1e-2):
    # 此处除以 16 使用的是批次样本的平均梯度值
    w.data = w.data - lr * w.grad.data / 16
    b.data = b.data - lr * b.grad.data / 16


def train():

    # 1.加载数据集
    x, y, coef = create_dataset()

    # 2.定义训练参数
    # epoch - 所有样本在模型中训练一遍称为一个epoch
    epochs = 100
    learning_rate = 1e-2

    # 3.存储训练信息
    epoch_loss = [] # 记录每一个epoch的损失
    total_loss = 0.0
    train_samples = 0 # 统计训练的样本的数量


    for _ in range(epochs):

        # 4. 进行训练
        # 获取到数据,这里对于data_loader进行遍历,会一直将所有样本都取出
        # for循环执行一次就是一个epoch
        for train_x, train_y in data_loader(x, y, batch_size=16):

            # 1. 将训练样本送入模型进行预测
            y_pred = linear_regression(train_x)  # shape[16,1]

            # 2. 计算预测值和真实值的平方损失
            # reshape(-1,1) 将形状进行多行一列,让y_pred和train_y形状一样
            # print(len(y_pred),y_pred.size()) # 16 torch.Size([16, 1])
            # print(len(train_y),train_y.size()) # 16 torch.Size([16])

            loss = square_loss(y_pred, train_y.reshape(-1, 1)).sum()
            total_loss += loss.item()
            train_samples += len(train_y)

            # 3. 梯度清零
            # 对w和b进行求导,所以需要对于w和b进行梯度清零
            if w.grad is not None:
                w.grad.data.zero_()

            if b.grad is not None:
                b.grad.data.zero_()

            # 4. 自动微分
            loss.backward()

            # 5. 参数更新
            sgd(learning_rate)

            print('loss: %.10f' % (total_loss / train_samples))

            # 记录每一个 epoch 的平均损失
        epoch_loss.append(total_loss / train_samples)


    # 绘制数据集散点图

    plt.rcParams['font.sans-serif'] = ['SimHei']

    plt.scatter(x, y)
    # 绘制拟合的直线
    x = torch.linspace(x.min(), x.max(), 1000)
    y1 = torch.tensor([v * w + b for v in x])
    y2 = torch.tensor([v * coef + 14.5 for v in x])

    plt.plot(x, y1, label='训练')
    plt.plot(x, y2, label='真实')
    plt.grid()
    plt.legend()
    plt.show()


    # 打印损失变化曲线
    plt.plot(range(epochs), epoch_loss)
    plt.grid()
    plt.title('损失变化曲线')
    plt.show()


if __name__ == '__main__':
    train()

在这里插入图片描述
在这里插入图片描述

6.总结

  • 采用sklearn中的make_regression()可以构造回归数据

指定:
n_samples - 样本个数
n_features - 特征个数
noise - 噪声
coef - 斜率(生成数据参考)
bias - 偏置
random_state - 指定随机种子,让实验重现

  • 采用data_loader(数据加载器),每次拿总样本的一部分进行训练

数据加载器需要知道:
x - 特征,可以计算得到特征的个数和特征的索引
y - 目标值
batch_size - 每次产生多少个,
batch数量计算:用总的样本个数//batch_size = batch
data_loader采用生成器,对batch数量进行循环,由多少个batch就循环多少次,每次产生一个batch_size的数据
data_loader是一个生成器,本质上也是一个迭代器,所以对data_loader进行一次完整的for循环,就会得到全部的数据

  • 假设函数

首先有假设函数的形式 - y = wx + b
x 如果是一个向量,有多个因变量
y 也是一个向量
将y w x b 都转换为tensor的形式,进行计算
y 就是函数的返回值

  • 训练函数

1.先加载数据集

2.获取到数据之后定义训练参数

  • epochs = 数据集中训练样本的个数,将数据集中的样本都训练一遍,称作一个epoch
  • 每个epoch的损失都要进行收集,所以定义一个epoch_loss列表
  • 进行梯度迭代的时候指定超参数学习率

3.存储信息定义参数

  • loss_epoch
  • total_loss
  • train_samples

4.分多个epoch,多个batch进行训练

  • 获取数据
  • 训练模型,得到y_pred
  • 计算损失函数
  • 进行梯度计算,反向传播
  • 进行参数更新

5.绘图展示


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

相关文章:

  • 介绍一下strncmp(c基础)
  • FreeRTOS之vTaskDelete实现分析
  • C++ 中的移动语义
  • ara::com 与 AUTOSAR 元模型的关系总结
  • css:感觉稍微高级一点的布局
  • 51c嵌入式~IO合集2
  • mongoDB回顾笔记(一)
  • springboot嗨玩旅游网站
  • 11.21 深度学习-tensor常见操作
  • Project指针pointer 作业
  • 【日常经验】Mysql中的某个存储过程中如果有查数据,存数据和删除数据,会自动在一个事务中吗
  • AWTK VSCode 实时预览插件端口冲突的解决办法
  • ubuntu 之 安装mysql8
  • 如何用redis+lua来实现高并发限流,超时数据进行等待
  • 基于Java Springboot北京医疗企业固定资产管理系统
  • HTML5和CSS3新增特性
  • cocos creator 3.8 Node学习 3
  • 【spring】spring单例模式与锁对象作用域的分析
  • 【IOS】Undefined symbol: _OBJC_CLASS_$_PAGFile
  • Java通过calcite实时读取kafka中的数据
  • 学习threejs,通过SkinnedMesh来创建骨骼和蒙皮动画
  • WSL2 ubuntu配置redis
  • Simulink学习笔记【PID UG联动仿真】
  • 算法.图论-习题全集(Updating)
  • 【Android、IOS、Flutter、鸿蒙、ReactNative 】自定义View
  • 力扣 LeetCode 513. 找树左下角的值(Day8:二叉树)