首页 / PyTorch 入门教程 / 线性回归与逻辑回归

PyTorch 入门教程

线性回归与逻辑回归

本教程共 60 篇 · 第 18 篇 · 更新于 2026-08-17 · 约 3 分钟阅读

PyTorch线性回归逻辑回归nn.LinearMSELosssigmoid深度学习入门

本节目标:从最简单的模型出发,搞懂回归和分类两大任务,并会用 nn.Linear 写出完整的线性模型。

两个最基础的任务

机器学习任务分两大类。预测房价、温度这种连续数值,叫回归(regression)。判断邮件是不是垃圾、图片里是猫还是狗,叫分类(classification)。

这章的两个模型正好各管一个:线性回归管回归,逻辑回归管分类。它们也是深度学习的地基,后面所有网络都从这里长出来。

线性回归:画一条线

线性回归(linear regression)假设输出和输入是线性关系。一个特征时就是一条直线:

y = wx + b

w 是权重(weight),决定线的斜率;b 是偏置(bias),决定线的位置。模型要学的,就是找出让预测最准的那组 w 和 b。

特征多起来之后,直线变成平面,再变成高维空间里的超平面。名字变来变去,本质还是「每个特征乘一个权重,加起来再加偏置」这一件事。

在 PyTorch 里,这活交给 nn.Linear。它自动创建权重和偏置,帮你算 x @ w.T + b

import torch.nn as nn

model = nn.Linear(2, 1)   # 输入 2 个特征,输出 1 个值
Note

nn.Linear 会把权重、偏置自动注册成可训练参数,不用手动定义,更不用手动初始化。

怎么衡量「准不准」

预测值和真实值的差距,用均方误差(MSE,Mean Squared Error)衡量:每个样本差值的平方,再取平均。平方有两个作用:去掉正负号,让大误差受更重的惩罚。

PyTorch 里现成可用:

criterion = nn.MSELoss()
loss = criterion(pred, target)

有了损失,就靠梯度下降让它变小。顺便说一句,最小二乘是线性回归的解析解,适合小问题;梯度下降是迭代逼近,才是深度学习的标准做法。

学习率在这步很关键。太大,参数来回横跳不收敛;太小,几百轮都挪不动。先试试 0.01,再根据 loss 曲线的样子微调。

完整小例子

造一批带噪声的线性数据,让模型把真实的 w 和 b 学回来:

import torch
import torch.nn as nn

torch.manual_seed(42)

# 1. 造数据:真实规律是 y = 2*x1 + 3*x2 + 4,再加一点噪声
X = torch.randn(100, 2)
true_w = torch.tensor([2.0, 3.0])
true_b = 4.0
Y = X @ true_w + true_b + torch.randn(100) * 0.1

# 2. 模型、损失、优化器
model = nn.Linear(2, 1)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# 3. 训练
for epoch in range(500):
    pred = model(X).squeeze()          # (100, 1) -> (100)
    loss = criterion(pred, Y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if (epoch + 1) % 100 == 0:
        print(f"epoch {epoch + 1}, loss = {loss.item():.4f}")

# 4. 看学到的参数
print("学到的 w:", model.weight.data)
print("学到的 b:", model.bias.data)

跑完你会发现,学到的 w 接近 [2.0, 3.0],b 接近 4.0。噪声没难倒模型,线性关系被完整复原。

这个例子麻雀虽小,五脏俱全。换个真实数据集,把 nn.Linear(2, 1) 的输入维度改成真实特征数,剩下的代码几乎不用动。

Note

pred.squeeze() 把形状从 (100, 1) 压成 (100),才能和 Y 对上。形状不匹配是新手最常踩的坑,报错先查形状。

逻辑回归:换一层皮

分类问题不能直接输出连续值。逻辑回归(logistic regression)的思路:还是算线性组合,但用一个激活函数把结果压到 0 到 1 之间,当作「属于正类的概率」。

这个函数叫 sigmoid。数值很大时它接近 1,很小时接近 0,中间平滑过渡:

import torch

z = torch.tensor([-2.0, 0.0, 2.0])
p = torch.sigmoid(z)
print(p)   # 输出接近 0、0.5、接近 1

预测时取 0.5 当阈值:概率大于它判正类,小于它判负类。

Tip

sigmoid 的输出天然是 0 到 1,正好当概率用。多分类问题不逐个用 sigmoid,而是用 softmax 一次算出一组概率,第 13 章讲过,忘了可以回头翻。

逻辑回归的损失

分类不再用 MSE,改用交叉熵。二分类用 BCEWithLogitsLoss,它把 sigmoid 和损失合并成一步,数值上更稳:

import torch.nn as nn

criterion = nn.BCEWithLogitsLoss()   # 内部自带 sigmoid

pred = model(X)                      # 直接传原始分数 logits
loss = criterion(pred.squeeze(), Y)  # Y 必须是 0/1 的 float 张量
Warning

用了 BCEWithLogitsLoss,就别再手动 torch.sigmoid(pred) 再算损失。双重 sigmoid 会破坏训练,loss 会异常。

另外注意,标签 Y 必须是 float 类型,不能是整数张量。分类标签平时习惯用整数,这一步经常被忽略。

逻辑回归小例子

造两类点,让模型学一条分界线。这是逻辑回归最经典的玩法:

import torch
import torch.nn as nn

torch.manual_seed(0)

# 1. 造数据:两个坐标之和为正的算 1,否则算 0
X = torch.randn(200, 2)
Y = (X[:, 0] + X[:, 1] > 0).float()

# 2. 模型、损失、优化器
model = nn.Linear(2, 1)
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.05)

# 3. 训练
for epoch in range(300):
    pred = model(X).squeeze()
    loss = criterion(pred, Y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if (epoch + 1) % 100 == 0:
        print(f"epoch {epoch + 1}, loss = {loss.item():.4f}")

# 4. 评估:sigmoid 转概率,0.5 定类别
with torch.no_grad():
    prob = torch.sigmoid(model(X).squeeze())
    pred_class = (prob > 0.5).float()
    acc = (pred_class == Y).float().mean()
print(f"准确率: {acc.item() * 100:.1f}%")

训练完准确率会非常高。因为这两类点本来就是被一条直线分开的,逻辑回归学这条线,天经地义。

两个模型一张表

对比项线性回归逻辑回归
任务回归(连续值)分类(0/1)
输出任意实数0 到 1 的概率
损失MSELossBCEWithLogitsLoss
典型场景房价、温度预测垃圾邮件、患病判断

逻辑回归名字带「回归」,干的却是分类的活。别被名字骗了,记住:看输出,不看名字。

怎么选

拿到一个问题,先问一句:输出是什么?输出是连续数值,从线性回归起步;输出是类别,从逻辑回归起步。

两个模型都搞不定时,说明数据不是线性的。恭喜,该上第 19 章的 MLP 了。这两个模型就像新手村的木剑,先拿它们练手,再换高级装备。

常见坑

下面这几个坑,新手十有八九都会踩一遍。先打预防针,真遇到时知道往哪看。

  • 特征尺度差太大:一个特征在 0 到 1,另一个到上万,梯度会被大尺度特征牵着走。先做标准化(归一化到均值 0、方差 1),训练会稳很多
  • loss 不降:先试学习率 0.1、0.01、0.001 三档;还不行就检查数据有没有归一化
  • 输出形状对不上:模型输出是 (100, 1),标签是 (100,),用 squeeze()unsqueeze() 对齐,别硬算

这几个坑在 MLP 上同样适用,现在记住,后面少踩。