• 动手学深度学习(Pytorch版)代码实践 -深度学习基础-02线性回归基础版


    02线性回归基础版

    主要内容

    1. 数据生成:使用线性模型 ( y = X*w + b ) 加上噪声生成人造数据集。
    2. 数据读取:通过小批量读取数据集来实现批量梯度下降,打乱数据顺序并逐批返回特征和标签。
    3. 模型参数初始化:随机初始化权重和偏置,并设置为可计算梯度。
    4. 模型定义:实现线性回归模型 ( y = X*w + b )。
    5. 损失函数:实现均方误差损失函数。
    6. 优化函数:实现小批量随机梯度下降用于更新模型参数。
    7. 模型训练:设定学习率和迭代次数,通过每个批量计算损失、反向传播和参数更新。
    import random
    import torch
    
    # 生成数据集
    def synthetic_data(w, b, num_examples):
        """生成 y = Xw + b + 噪声"""
        # torch.normal: 返回一个从均值为0,标准差为1的正态分布中提取的随机数的张量
        # 生成形状为(num_examples, len(w))的矩阵
        X = torch.normal(0, 1, (num_examples, len(w)))
        # torch.matmul: 矩阵乘法
        y = torch.matmul(X, w) + b
        # 添加噪声:torch.normal(0, 0.01, y.shape)
        y += torch.normal(0, 0.01, y.shape)
        # reshape: 只改变张量的视图,不改变数据,将y转换为列向量
        return X, y.reshape((-1, 1))
    
    # 定义真实的权重和偏置
    true_w = torch.tensor([2, -3.4])
    true_b = 4.2
    # 生成特征和标签
    features, labels = synthetic_data(true_w, true_b, 1000)
    
    # 读取数据集
    def data_iter(batch_size, features, labels):
        num_examples = len(features)
        # 生成一个从0到num_examples-1的整数列表
        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]
    
    # 设置批量大小
    batch_size = 10
    
    # 初始化模型参数 
    # 随机初始化权重,设置requires_grad=True以计算梯度
    w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True) 
    
    # 初始化偏置为0,设置requires_grad=True以计算梯度
    b = torch.zeros(1, requires_grad=True)  
    
    # 定义模型
    def linreg(X, w, b):
        """线性回归模型"""
        return torch.matmul(X, w) + b
    
    # 定义损失函数
    def squared_loss(y_hat, y):
        """均方损失函数"""
        return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
    
    # 定义优化函数
    def sgd(params, lr, batch_size):
        """小批量随机梯度下降"""
        # 更新参数时不需要计算梯度
        with torch.no_grad():
            for param in params:
                param -= lr * param.grad / batch_size  # 参数更新
                param.grad.zero_()  # 梯度清零
    
    # 模型训练
    lr = 0.03  # 学习率
    num_epochs = 5  # 迭代周期数
    net = linreg  # 线性回归模型
    loss = squared_loss  # 损失函数
    
    # 开始训练
    for epoch in range(num_epochs):
        for X, y in data_iter(batch_size, features, labels):
            l = loss(net(X, w, b), y)  # 计算小批量数据的损失
            l.sum().backward()  # 计算梯度
            sgd([w, b], lr, batch_size)  # 更新参数
        with torch.no_grad():
            train_l = loss(net(features, w, b), labels)  # 计算整个数据集上的损失
            print(f'第{epoch + 1}轮,损失: {float(train_l.mean()):f}')
    
    # 打印权重和偏置的估计误差
    print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
    print(f'b的估计误差: {true_b - b}')
    
    # 示例输出:
    # 第1轮,损失: 0.036624
    # 第2轮,损失: 0.000131
    # 第3轮,损失: 0.000052
    # 第4轮,损失: 0.000052
    # 第5轮,损失: 0.000052
    # w的估计误差: tensor([-0.0003, -0.0008], grad_fn=)
    # b的估计误差: tensor([0.0007], grad_fn=)
    
  • 相关阅读:
    windows 构建nginx本地服务随系统自启
    Linux操作系统中如何查看系统层面的各项参数
    R - Sonya and Hotels
    dubbo学习资料
    基于SSM的青少年编程学习系统设计与实现
    Redis 的几种集群对比
    初识Linux工具
    通过Oracle Enterprise Manager管理OCI上的RAC
    Python之第六章 内置容器 --- 字典(映射)
    计算机毕业设计Java桂林恒保健康防护有限公司官网(源码+系统+mysql数据库+Lw文档)
  • 原文地址:https://blog.csdn.net/weixin_46560570/article/details/139305615