1. 线性回归基础与PyTorch实现

线性回归是机器学习中最基础的算法之一,它通过寻找自变量(x)和因变量(y)之间的线性关系来进行预测。想象一下你正在根据房屋面积预测房价,或者根据学习时间预测考试成绩,这些都是线性回归的典型应用场景。

在PyTorch中实现线性回归,我们需要理解几个核心概念:

  1. 权重(w)和偏置(b) :这是线性方程y=wx+b中的两个参数,w决定了x对y的影响程度,b是当x为0时y的基准值。

  2. 前向传播(forward pass) :这是模型进行预测的过程,简单来说就是计算wx+b的过程。

  3. 张量(Tensor) :PyTorch中的基本数据结构,类似于Numpy数组,但支持GPU加速和自动微分。

让我们从一个最简单的例子开始:假设我们有一个线性关系y=3x+1,我们如何在PyTorch中表示这个关系并进行预测?

import torch

# 定义参数,requires_grad=True表示这些参数需要被优化
w = torch.tensor(3.0, requires_grad=True)
b = torch.tensor(1.0, requires_grad=True)

# 前向传播函数
def forward(x):
    return w * x + b

# 在x=2处进行预测
x = torch.tensor([[2.0]])
print(forward(x))  # 输出: tensor([[7.]], grad_fn=<AddBackward0>)

这段代码完美地预测了x=2时的y值(3*2+1=7)。但现实中我们很少会知道真实的w和b值,这正是机器学习要解决的问题。

2. 使用PyTorch的Linear类

在实际项目中,我们更常使用PyTorch提供的现成模块。 torch.nn.Linear 就是一个封装好的线性层,它自动处理了参数的初始化和前向计算。

2.1 初始化线性层

from torch.nn import Linear

# 设置随机种子保证结果可复现
torch.manual_seed(42)

# 创建一个输入输出维度都为1的线性层
linear_layer = Linear(in_features=1, out_features=1)

# 查看初始化的参数
print(list(linear_layer.parameters()))
# 输出: [Parameter containing: tensor([[0.5153]], requires_grad=True), 
#        Parameter containing: tensor([-0.4414], requires_grad=True)]

这里有几个关键点需要注意:

  1. in_features out_features 分别指定了输入和输出的维度
  2. 参数是随机初始化的,这是深度学习的标准做法
  3. 我们可以通过 parameters() 方法访问所有可训练参数

2.2 进行预测

使用PyTorch的Linear层进行预测非常简单:

# 单个输入预测
x = torch.tensor([[2.0]])
print(linear_layer(x))  # 输出: tensor([[0.5891]], grad_fn=<AddmmBackward0>)

# 多个输入预测
x = torch.tensor([[3.0], [4.0]])
print(linear_layer(x))
# 输出: tensor([[1.1044],
#               [1.6197]], grad_fn=<AddmmBackward0>)

注意:PyTorch的Linear层期望输入的形状为(batch_size, in_features)。即使只有一个样本,也要保持二维张量的形式,这就是为什么我们使用[[2.0]]而不是[2.0]。

3. 构建自定义线性模型

虽然PyTorch提供了现成的Linear类,但了解如何从头构建自定义模型对于理解深度学习原理至关重要。这也能为将来构建更复杂的模型打下基础。

3.1 创建自定义类

from torch import nn

class LinearRegression(nn.Module):
    def __init__(self, input_size, output_size):
        super(LinearRegression, self).__init__()
        self.linear = nn.Linear(input_size, output_size)
    
    def forward(self, x):
        return self.linear(x)

这个自定义类有几个关键组成部分:

  1. 继承自 nn.Module :这是所有PyTorch模型的基类
  2. __init__ 方法:初始化模型结构
  3. forward 方法:定义前向传播逻辑

3.2 使用自定义模型

# 创建模型实例
model = LinearRegression(1, 1)

# 查看模型参数
print(list(model.parameters()))
# 输出: [Parameter containing: tensor([[0.5153]], requires_grad=True), 
#        Parameter containing: tensor([-0.4414], requires_grad=True)]

# 进行预测
x = torch.tensor([[2.0], [3.0], [4.0]])
print(model(x))
# 输出: tensor([[0.5891],
#               [1.1044],
#               [1.6197]], grad_fn=<AddmmBackward0>)

4. 实际应用中的注意事项

在实际项目中使用PyTorch进行线性回归时,有几个关键点需要注意:

  1. 数据预处理 :确保输入数据经过适当的标准化/归一化处理。对于线性模型,这可以显著提高训练效果。

  2. 损失函数选择 :对于回归问题,最常用的是均方误差(MSE)损失:

    criterion = nn.MSELoss()
    
  3. 优化器选择 :随机梯度下降(SGD)或Adam是常见选择:

    optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
    
  4. 训练循环 :典型的训练过程包括:

    for epoch in range(100):
        # 前向传播
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        
        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    
  5. GPU加速 :如果有可用的GPU,可以将模型和数据转移到GPU上:

    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model = model.to(device)
    inputs = inputs.to(device)
    

5. 常见问题与调试技巧

在实现线性回归时,可能会遇到以下问题:

  1. 梯度爆炸/消失 :如果学习率设置不当,可能导致训练不稳定。解决方案是调整学习率或使用学习率调度器。

  2. 预测结果不理想 :检查数据是否有线性关系,或者是否需要更复杂的模型。

  3. 维度不匹配错误 :确保输入数据的形状符合模型要求。PyTorch通常期望(batch_size, feature_size)的形状。

  4. 参数不更新 :确保在反向传播前调用了 optimizer.zero_grad() 清空梯度。

调试技巧:

  • 使用 print(model.state_dict()) 检查参数值
  • 可视化损失曲线观察训练过程
  • 在小型数据集上测试模型是否能过拟合,验证模型能力

6. 从线性回归到深度学习

虽然线性回归看似简单,但它包含了深度学习的核心概念:

  1. 参数化模型 :模型由可学习的参数(w,b)组成
  2. 前向传播 :计算模型输出
  3. 损失函数 :衡量预测与真实的差距
  4. 反向传播 :计算梯度并更新参数

理解这些基础后,扩展到更复杂的神经网络就水到渠成了。例如,只需堆叠多个线性层并添加非线性激活函数,就能构建深度神经网络:

class DeepNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer1 = nn.Linear(10, 50)
        self.layer2 = nn.Linear(50, 20)
        self.output = nn.Linear(20, 1)
        
    def forward(self, x):
        x = torch.relu(self.layer1(x))
        x = torch.relu(self.layer2(x))
        return self.output(x)

线性回归作为深度学习的"Hello World",其重要性不仅在于它的实用性,更在于它为我们理解更复杂模型提供了坚实的基础框架。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐