pytorch api文档:nn.Linear类(线性层/全连接层) 作者:马育民 • 2026-01-18 22:41 • 阅读:10001 # 介绍 `nn.Linear` 类(线性层/全连接层),是深度学习中最基础也最核心的层,用于实现线性变换 $$y = x * W^T + b$$,广泛应用于分类、回归、特征映射等场景。 ### 作用 是 PyTorch 封装的线性层,核心作用是对输入张量执行**线性变换**: $$y = x \cdot W^T + b$$ - `x`:输入张量(形状 `[..., in_features]`,`...` 代表批量/序列等任意前置维度); - `W`:权重矩阵(形状 `[out_features, in_features]`,可训练参数); - `b`:偏置向量(形状 `[out_features]`,可训练参数,可选); - `y`:输出张量(形状 `[..., out_features]`)。 ### 关键特征 - 输入要求:最后一维必须等于 `in_features`(线性层的输入特征数); - 输出特征:最后一维变为 `out_features`(线性层的输出特征数); - 参数自动初始化:权重默认用 Kaiming 均匀分布初始化,偏置默认初始化为 0。 # 语法 ``` nn.Linear(in_features, out_features, bias=True, device=None, dtype=None) ``` #### 参数 | 参数 | 作用 | 注意事项 | |----------------|----------------------------------------------------------------------|--------------------------------------------------------------------------| | `in_features` | 输入特征数(输入张量最后一维的维度)| 必传,需与输入数据的最后一维匹配 | | `out_features` | 输出特征数(输出张量最后一维的维度)| 必传,决定线性层的输出维度 | | `bias` | 是否启用偏置(默认 True)| 设为 False 时,线性变换为 $y = xW^T$,无偏置项 `b` | | `device` | 指定层参数的存储设备(cpu/cuda)| 可省略,后续用 `model.to(device)` 统一设置更方便 | | `dtype` | 指定参数的数据类型(float32/float64)| 可省略,默认与输入数据类型一致 | # 例子 先通过极简示例掌握 `nn.Linear` 的核心用法: ```python import torch import torch.nn as nn # 步骤1:定义线性层(输入特征数=5,输出特征数=3,启用偏置) linear = nn.Linear(in_features=5, out_features=3, bias=True) # 步骤2:准备输入(最后一维必须=in_features=5,前置维度任意) # 示例1:单样本(shape [5]) x1 = torch.randn(5) # 1个样本,5维特征 y1 = linear(x1) print("单样本输出形状:", y1.shape) # torch.Size([3]) # 示例2:批量样本(shape [4,5] → 4个样本,5维特征) x2 = torch.randn(4, 5) y2 = linear(x2) print("批量样本输出形状:", y2.shape) # torch.Size([4, 3]) # 示例3:高维输入(shape [2,4,5] → 2个序列,4个样本,5维特征) x3 = torch.randn(2, 4, 5) y3 = linear(x3) print("高维输入输出形状:", y3.shape) # torch.Size([2, 4, 3])(仅最后一维变换) ``` ### 参数示例(禁用偏置/指定设备) ```python # 示例1:禁用偏置的线性层 linear_no_bias = nn.Linear(5, 3, bias=False) print("是否有偏置参数:", hasattr(linear_no_bias, 'bias')) # False # 示例2:指定设备(需CUDA环境) if torch.cuda.is_available(): linear_cuda = nn.Linear(5, 3, device="cuda") print("权重设备:", linear_cuda.weight.device) # cuda:0 print("偏置设备:", linear_cuda.bias.device) # cuda:0 else: print("无CUDA环境,参数默认在CPU") ``` # 核心特性:可训练参数 `nn.Linear` 的权重(`weight`)和偏置(`bias`)是 `nn.Parameter` 类型的可训练参数,会自动注册到模型参数列表中: ```python # 查看线性层的可训练参数 print("=== 线性层参数 ===") # 权重:shape [out_features, in_features] = [3,5] print("权重形状:", linear.weight.shape) print("权重初始化值:\n", linear.weight) # 偏置:shape [out_features] = [3] print("\n偏置形状:", linear.bias.shape) print("偏置初始化值:", linear.bias) # 默认为0 # 遍历参数(模型训练时优化器会更新这些参数) for name, param in linear.named_parameters(): print(f"\n参数名:{name},形状:{param.shape},是否可求梯度:{param.requires_grad}") # 输出: # 参数名:weight,形状:torch.Size([3, 5]),是否可求梯度:True # 参数名:bias,形状:torch.Size([3]),是否可求梯度:True ``` # 实战场景:集成到自定义模型 `nn.Linear` 几乎是所有自定义模型的基础组件,以下是分类任务的典型用法: ```python # 示例:自定义简单分类模型(输入28×28=784维,输出10类) class SimpleClassifier(nn.Module): def __init__(self): super().__init__() # 线性层1:784 → 128(隐藏层) self.fc1 = nn.Linear(784, 128) # 线性层2:128 → 64(隐藏层) self.fc2 = nn.Linear(128, 64) # 线性层3:64 → 10(输出层,对应10个类别) self.fc3 = nn.Linear(64, 10) # 激活函数(线性层后需加非线性激活,否则多层等价于单层) self.relu = nn.ReLU() def forward(self, x): # 输入:[batch, 28, 28] → 展平为 [batch, 784] x = x.flatten(1) # 从第1维开始展平(保留batch维度) # 前向传播:线性层 + 激活函数 x = self.relu(self.fc1(x)) x = self.relu(self.fc2(x)) x = self.fc3(x) # 输出层不激活(交给CrossEntropyLoss处理) return x # 测试模型 model = SimpleClassifier() # 模拟输入:4个样本,28×28像素 x = torch.randn(4, 28, 28) output = model(x) print("模型输出形状:", output.shape) # torch.Size([4, 10])(4个样本,10个类别logits) # 查看模型所有线性层参数 print("\n=== 模型所有参数 ===") for name, param in model.named_parameters(): print(f"{name}: {param.shape}") ``` # 常见易错点与技巧 ### (1)输入维度不匹配(最常见错误) ```python # 错误示例:输入最后一维≠in_features linear = nn.Linear(5, 3) x_bad = torch.randn(4, 4) # 最后一维=4≠5 # y_bad = linear(x_bad) # 报错:size mismatch, m1: [4 x 4], m2: [5 x 3] # 解决:确保输入最后一维等于in_features x_good = torch.randn(4, 5) y_good = linear(x_good) # 正常运行 ``` ### (2)手动初始化参数 默认初始化可能不满足需求,可手动重置权重/偏置: ```python # 手动初始化权重(正态分布) nn.init.normal_(linear.weight, mean=0.0, std=0.01) # 手动初始化偏置(常数1) nn.init.constant_(linear.bias, 1.0) print("手动初始化后权重:\n", linear.weight) print("手动初始化后偏置:", linear.bias) ``` ### (3)冻结线性层参数(不更新) 训练时若想冻结某层参数,设置 `requires_grad=False`: ```python # 冻结fc1层的权重(仅更新其他层) for param in model.fc1.parameters(): param.requires_grad = False # 优化器仅更新未冻结的参数 optimizer = torch.optim.SGD( [p for p in model.parameters() if p.requires_grad], lr=0.1 ) ``` ### (4)线性层的“维度变换”特性 `nn.Linear` 仅关注最后一维,因此可处理任意前置维度的输入(如序列、图像展平后的数据): ```python # 图像数据:[batch, channel, H, W] → 展平为 [batch, C×H×W] img = torch.randn(4, 1, 28, 28) # 4张灰度图,28×28 img_flat = img.flatten(1) # [4, 784] linear_img = nn.Linear(784, 10) output_img = linear_img(img_flat) print("图像输入输出形状:", output_img.shape) # [4, 10] ``` # 总结 1. `nn.Linear(in_features, out_features)` 实现线性变换 $y = xW^T + b$,核心是将输入最后一维从 `in_features` 映射到 `out_features`。 2. 关键参数:`in_features` 匹配输入最后一维,`out_features` 定义输出维度,`bias` 控制是否启用偏置。 3. 核心特性:权重/偏置是可训练的 `nn.Parameter`,自动注册到模型参数列表,支持梯度更新。 4. 实战技巧:线性层后需加非线性激活(如ReLU);输入需展平为二维(batch, features);可手动初始化参数或冻结部分层。 原文出处:http://malaoshi.top/show_1GW2cIbomFfg.html