Python----机器学习(基于PyTorch的线性回归)

一、自求导线性回归与PyTorch的区别

自求导线性回归:

需要手动定义参数 ww(权重)和 bb(偏置)。

通过数学公式求导,以便在反向传播中更新参数,通常使用梯度下降法来降低损失值。

PyTorch实现:

自动处理梯度计算和参数更新。

使用框架内置的自动微分机制,简化实现过程。

主要精力放在准备数据、定义模型以及选择损失函数和优化器上。

二、数据准备和模型定义

在使用PyTorch实现线性回归算法时,我们需要准备好数据集,然后通过框架将前向传播的内容做好,并且"选择"好反向传播过程中所用到的一些参数或者参数更新的方法(如梯度下降)。在选择好输入特征和输出特征后,按照自求导线性回归的思路,我们应该进行 w 和 b 的初始化,给模型一个起始点,使其能够开始学习并逐渐优化参数。而在使用框架实现时,参数的初始化是框架自动处理的(随机值),所以就不用我们再去手动初始化这两个参数了。

三、超参数设置

损失函数:

通常选择均方差损失(MSE),这是我们之前一直使用的损失函数。

优化器:

使用随机梯度下降(SGD),为参数更新提供依据。

四、梯度下降与随机梯度下降

梯度下降(GD):

每次迭代计算所有样本的梯度,更新参数。

适用于小规模数据集,但计算量较大,尤其在大规模数据集上。

随机梯度下降(SGD):

每次只使用一部分样本来计算梯度,速度更快,适合大规模数据集。

虽然使用样本梯度来更新参数可能导致更新方向不稳定,从而出现震荡现象并无法收敛到全局最优解,但由于在这里选择全部输入作为样本,所以在实际操作中和梯度下降相似。

五. 迭代过程

在选择好损失函数及优化器之后,我们就可以进行迭代了。通过不断的迭代更新,使 w 和 b 的值不断更新,从而降低损失函数值,使直线的拟合效果更好。

六、基于PyTorch的线性回归

导入模块

python 复制代码
import torch.nn as nn
import numpy as np
import torch
from torch.utils.data import DataLoader, TensorDataset

散点输入

python 复制代码
data = np.array([
    [-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2],
    [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1], [1.5, 75.6],
    [0.4, 34.0], [0.8, 62.3]
])

# 提取x和y并转换为tensor
x_train = torch.tensor(data[:, 0], dtype=torch.float32)
y_train = torch.tensor(data[:, 1], dtype=torch.float32)

#*******用于分装张量,组成数据集
dataset=TensorDataset(x_train,y_train)

#设置随机数种子
seed=42
torch.manual_seed(seed)
#随机取batch_size个
# dataloader可达代的对象,每次达代会生成一个批次的数,由输入张量和目标张量元组 组成
dataloader=DataLoader(dataset,batch_size=10,shuffle=True)

定义前向模型

1、直接定义

这种方式直接创建一个线性层模型,输入一个特征,输出一个特征。适合简单的线性回归任务。

python 复制代码
line_model=nn.Linear(1,1)#输入特征,输出特征

2、n.Sequential

nn.Sequential 是一个容器,可以按顺序组合多个层。在这种情况下,它包含一个线性层。适合顺序结构简单的模型。

python 复制代码
#nn.Sequential是pytorch的一个模块容器,按顺序组合多个网络层
line_model=nn.Sequential(nn.Linear(1,1))

3、nn.ModuleList

nn.ModuleList允许将层放在一个列表中,可以灵活管理,更适合需要多个层的模型结构。forward 方法定义了输入如何通过这些层进行前向传播。

python 复制代码
# nn.ModuleList
#forward方法会定义模型前向传播的逻辑,给定输入,经过逻辑,得出输出

 class LinearModel(nn.Module):
     def __init__(self):
        super(LinearModel,self).__init__()
        self.layers=nn.ModuleList([nn.Linear(1,1)])
     def forward(self,x):
        for layer in self.layers:
            x=layer(x)
        return x
line_model=LinearModel()

4、nn.ModuleDict

nn.ModuleDict允许为每个层赋予名字,便于管理和访问。特别适合需要命名的复杂模型。

python 复制代码
#可以给每个层自定义名字
# nn.ModuleDict
class LinearModel(nn.Module):
     def __init__(self):
        super(LinearModel,self).__init__()
        self.layers=nn.ModuleDict({'liner':nn.Linear(1,1)})
     def forward(self,x):
         for layer in self.layers.values():
            x=layer(x)
         return x
line_model=LinearModel()

5、高频率使用

在这种方式中,模型中定义了多个层。self.liner1self.liner2 赋予各层的名称,使得在 forward 方法中容易使用和复用。适用于复杂的模型构建。

python 复制代码
class LinearModel(nn.Module):
    def __init__(self):
        super(LinearModel,self).__init__()
        self.liner1=nn.Linear(1,1)
        self.liner2=nn.Linear(1,1)
    def forward(self,x):
        x=self.liner1(x)
        # x=self.liner2(x)
        return x
line_model=LinearModel()

总结

根据模型的复杂程度和需求,可以选择不同的定义方式。简单任务可以用直接定义或 nn.Sequential 进行,而复杂的模型则可以使用 nn.ModuleList 或 nn.ModuleDict 来管理多个层,方便扩展和维护。高频率使用的方式适合在构建需要多个层的网络时使用。
定义损失函数和优化器

python 复制代码
#损失函数(均方差损失)
criterion=nn.MSELoss()

#优化器
optimzer=torch.optim.SGD(line_model.parameters(),lr=0.01)

迭代拟合显示

python 复制代码
for i in range(1,501):
    total_loss=0
    for x,y in dataloader:
        y_hat=line_model(x.unsqueeze(1))
        #计算损失
        loss=criterion(y_hat.squeeze(1),y)
        total_loss+=loss
        #清空之前存储在优化器中的梯度
        optimzer.zero_grad()
        #计算损失函数关于模型参数的梯度
        loss.backward()
        #根据优化算法去更新参数
        optimzer.step()

        avg_loss=total_loss/len(dataloader)
        #5.显示
        if i%10==0 or i==1:
            print(i,avg_loss.item())
            # pass
python 复制代码
'''
1 2811.569091796875
10 1693.6490478515625
20 976.31298828125
30 573.5284423828125
40 346.38092041015625
50 217.63870239257812
60 144.24981689453125
70 102.14170837402344
80 77.80529022216797
90 63.62700271606445
100 55.29475021362305
110 50.35265350341797
120 47.3928337097168
130 45.602577209472656
140 44.50886154174805
150 43.83409881591797
160 43.413795471191406
170 43.14963912963867
180 42.98223114013672
190 42.87529373168945
200 42.8065185546875
210 42.762001037597656
220 42.7330436706543
230 42.714115142822266
240 42.70168685913086
250 42.6934928894043
260 42.68808364868164
270 42.684505462646484
280 42.6821174621582
290 42.6805419921875
300 42.67948913574219
310 42.67878341674805
320 42.678314208984375
330 42.678001403808594
340 42.67778778076172
350 42.67765426635742
360 42.67755889892578
370 42.67750930786133
380 42.67746353149414
390 42.67744445800781
400 42.67741775512695
410 42.67740249633789
420 42.677398681640625
430 42.677391052246094
440 42.67738342285156
450 42.6773796081543
460 42.67737579345703
470 42.6773796081543
480 42.67737579345703
490 42.67737579345703
500 42.67737579345703
'''

完整代码

python 复制代码
import torch.nn as nn  
import numpy as np  
import torch  
from torch.utils.data import DataLoader, TensorDataset  

# 1. 散点输入数据 (输入数据点)  
data = np.array([  
    [-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2],  
    [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1], [1.5, 75.6],  
    [0.4, 34.0], [0.8, 62.3]  
])  

# 提取x和y并转换为tensor (提取输入特征和目标值并转换为张量)  
x_train = torch.tensor(data[:, 0], dtype=torch.float32)  # 输入特征 (Input feature)  
y_train = torch.tensor(data[:, 1], dtype=torch.float32)  # 目标值 (Target value)  

#*******用于分装张量,组成数据集 (将张量打包成数据集)  
dataset = TensorDataset(x_train, y_train)  

# 设置随机数种子 (为了结果可重现设置随机种子)  
seed = 42  
torch.manual_seed(seed)  

# 随机取batch_size个 (随机选择batch_size个样本)  
# dataloader是一个可迭代对象,每次迭代会生成一批数据,由输入张量和目标张量组成 (DataLoader是一个可迭代对象,每次迭代会生成一个批次的输入与目标张量)  
dataloader = DataLoader(dataset, batch_size=10, shuffle=True)  

# 2. 定义前向模型 (定义线性模型)  
class LinearModel(nn.Module):  
    def __init__(self):  
        super(LinearModel, self).__init__()  
        self.liner1 = nn.Linear(1, 1)  # 第一层线性变换 (第一个线性层)  
        self.liner2 = nn.Linear(1, 1)  # 第二层线性变换 (第二个线性层,当前未使用)  

    def forward(self, x):  
        x = self.liner1(x)  # 将输入x通过第一层 (将输入x传入第一层线性变换)  
        # x = self.liner2(x)  # 将输入x通过第二层 (将输入x传入第二层线性变换,当前已注释)  
        return x  # 返回经过处理的x (返回处理后的x)  

line_model = LinearModel()  # 实例化线性模型 (创建线性模型的实例)  

# 损失函数(均方差损失)(损失函数: 均方误差损失)  
criterion = nn.MSELoss()  

# 优化器 (设置优化器)  
optimzer = torch.optim.SGD(line_model.parameters(), lr=0.01)  # 使用随机梯度下降优化器  

# 训练模型  
for i in range(1, 501):  
    total_loss = 0  # 初始化总损失 (初始化总损失)  
    for x, y in dataloader:  # 遍历数据加载器中的批次 (遍历数据加载器中的每一个批次)  
        y_hat = line_model(x.unsqueeze(1))  # 获取模型的预测值 (通过模型得到预测值)  
        
        # 计算损失 (计算预测值与真实值之间的损失)  
        loss = criterion(y_hat.squeeze(1), y)  # 计算预测值和真实值的损失  
        total_loss += loss  # 累加损失 (将当前批次的损失加入总损失)  

        # 清空之前存储在优化器中的梯度 (清空优化器中的梯度信息)  
        optimzer.zero_grad()  
        
        # 计算损失函数关于模型参数的梯度 (计算损失函数相对于模型参数的梯度)  
        loss.backward()  
        
        # 根据优化算法更新参数 (根据优化算法更新模型参数)  
        optimzer.step()  

    avg_loss = total_loss / len(dataloader)  # 计算平均损失 (计算当前周期的平均损失)  

    # 5. 显示 (每隔一定轮数显示结果)  
    if i % 10 == 0 or i == 1:  # 每10轮或第一轮显示一次 (每10次迭代或第一次迭代时输出平均损失)  
        print(i, avg_loss.item())  

七、库函数

7.1、TensorDataset()

是 PyTorch 中的一个类,用于将多个张量组合成一个数据集。它方便地将输入数据和目标数据成对存储,可以通过索引访问。

7.2、DataLoader()

是一个 PyTorch 提供的工具,用于在训练过程中批量加载数据。它支持打乱数据、并行加载、以及自动生成批次。

python 复制代码
DataLoader(dataset, batch_size=2, shuffle=True)
方法 描述
dataset 数据集
batch_size 每个批次的样本数量。
shuffle 是否在每个epoch前打乱数据。

7.3、Sequential()

是一个容器,用于按顺序将多个子模块堆叠到一起。用于快速构建简单的前馈神经网络。

python 复制代码
import torch.nn as nn

model = nn.Sequential(
    nn.Linear(1, 10),
    nn.ReLU(),
    nn.Linear(10, 1)
)

输入首先经过一个线性层,然后通过 ReLU 激活函数,最后再通过一个线性层。

7.4、ModuleList()

是一个模块容器,用于存储子模块的有序列表。它让我们可以在迭代时灵活地构造模型,特别是在需要动态网络结构时。

7.5、ModuleDict()

但它允许通过字典的方式存储子模块。它提供了键值对的方式来访问子模块。

7.6、MSELoss()

是 PyTorch 中用于计算均方误差损失(Mean Squared Error Loss)的类。通常用于回归任务,衡量预测值和真实值之间的差异。

python 复制代码
criterion(predictions, targets) 
方法 描述
predictions 是模型的预测值
targets 是真实值

7.7、SGD()

代表随机梯度下降(Stochastic Gradient Descent),是用于优化模型的算法。它根据当前梯度来更新模型参数。

python 复制代码
torch.optim.SGD(model.parameters(), lr=0.01)

| 方法 | 描述 |
| params | 要优化的参数(通常是模型的参数)。 |

lr 学习率(learning rate),决定每次参数更新的步长。

7.8、zero_grad()

用来清空优化器中累积的梯度,以避免梯度在每次迭代中累加。

7.9、backward()

用来计算当前损失相对于模型参数的梯度。

7.10、step()

方法用于根据当前累积的梯度更新模型参数。

相关推荐
lilye661 分钟前
精益数据分析(20/126):解析经典数据分析框架,助力创业增长
大数据·人工智能·数据分析
盈达科技21 分钟前
盈达科技:登顶GEO优化全球制高点,以AICC定义AI时代内容智能优化新标杆
大数据·人工智能
安冬的码畜日常27 分钟前
【AI 加持下的 Python 编程实战 2_10】DIY 拓展:从扫雷小游戏开发再探问题分解与 AI 代码调试能力(中)
开发语言·前端·人工智能·ai·扫雷游戏·ai辅助编程·辅助编程
古希腊掌管学习的神28 分钟前
[LangGraph教程]LangGraph04——支持人机协作的聊天机器人
人工智能·语言模型·chatgpt·机器人·agent
西柚小萌新31 分钟前
【Python爬虫基础篇】--4.Selenium入门详细教程
爬虫·python·selenium
FIT2CLOUD飞致云35 分钟前
问答页面支持拖拽和复制粘贴文件,MaxKB企业级AI助手v1.10.6 LTS版本发布
人工智能·开源
起个破名想半天了36 分钟前
计算机视觉cv入门之答题卡自动批阅
人工智能·opencv·计算机视觉
早睡早起吧40 分钟前
目标检测篇---Fast R-CNN
人工智能·目标检测·计算机视觉·cnn
小墙程序员1 小时前
机器学习入门(二)线性回归
机器学习
爱喝奶茶的企鹅1 小时前
Ethan独立开发产品日报 | 2025-04-24
人工智能·程序员·开源