From a8d78878fc73e12ef4c1878c390059e803a2b5b8 Mon Sep 17 00:00:00 2001 From: e2hang <2099307493@qq.com> Date: Tue, 9 Sep 2025 15:56:55 +0800 Subject: [PATCH] Added nn --- Pytorch/nn/Functional/Functional.md | 295 ++++++++++++++ .../OnlyCalculateNoRecordingPms-Use.nn.Func | 0 .../nn/Module/List(Dict)AreUsedToStoreModule | 0 Pytorch/nn/{ => Module}/nn.Module.md | 0 Pytorch/nn/Module/nn.ModuleDict.md | 359 ++++++++++++++++++ Pytorch/nn/Module/nn.ModuleList.md | 359 ++++++++++++++++++ .../nn/Parameter/List(Dict)AreUsedToStorePms | 0 Pytorch/nn/Parameter/nn.Parameter.md | 225 +++++++++++ Pytorch/nn/Parameter/nn.ParameterDict.md | 359 ++++++++++++++++++ Pytorch/nn/Parameter/nn.ParameterList.md | 359 ++++++++++++++++++ Pytorch/nn/{ => Sequential}/nn.Sequential.md | 0 Pytorch/nn/viFunc/DirectlyUse-nn.func | 0 Pytorch/nn/viFunc/nn.Conv2d.md | 161 ++++++++ Pytorch/nn/viFunc/nn.Linear.md | 47 +++ Pytorch/nn/viFunc/readme.md | 101 +++++ 15 files changed, 2265 insertions(+) create mode 100644 Pytorch/nn/Functional/Functional.md create mode 100644 Pytorch/nn/Functional/OnlyCalculateNoRecordingPms-Use.nn.Func create mode 100644 Pytorch/nn/Module/List(Dict)AreUsedToStoreModule rename Pytorch/nn/{ => Module}/nn.Module.md (100%) create mode 100644 Pytorch/nn/Module/nn.ModuleDict.md create mode 100644 Pytorch/nn/Module/nn.ModuleList.md create mode 100644 Pytorch/nn/Parameter/List(Dict)AreUsedToStorePms create mode 100644 Pytorch/nn/Parameter/nn.Parameter.md create mode 100644 Pytorch/nn/Parameter/nn.ParameterDict.md create mode 100644 Pytorch/nn/Parameter/nn.ParameterList.md rename Pytorch/nn/{ => Sequential}/nn.Sequential.md (100%) create mode 100644 Pytorch/nn/viFunc/DirectlyUse-nn.func create mode 100644 Pytorch/nn/viFunc/nn.Conv2d.md create mode 100644 Pytorch/nn/viFunc/nn.Linear.md create mode 100644 Pytorch/nn/viFunc/readme.md diff --git a/Pytorch/nn/Functional/Functional.md b/Pytorch/nn/Functional/Functional.md new file mode 100644 index 0000000..f5bd9f3 --- /dev/null +++ b/Pytorch/nn/Functional/Functional.md @@ -0,0 +1,295 @@ +`torch.nn.functional` 是 PyTorch 中提供神经网络相关功能的模块,包含了大量的函数,用于实现卷积、池化、激活函数、损失函数、归一化等操作。这些函数是 `torch.nn` 模块的函数式接口,通常用于定义神经网络的 `forward` 方法中,尤其是当不需要管理参数(如权重和偏置)时。以下是对 `torch.nn.functional` 模块中主要方法的全面讲解,基于 PyTorch 2.8 官方文档()以及相关信息。由于方法数量庞大,我将按类别组织并简要讲解每个方法的功能、输入输出和典型用途,尽量清晰简洁。如果需要更详细的讲解或代码示例,请告诉我![](https://docs.pytorch.org/docs/2.8/nn.functional.html) + +--- + +### 1. 卷积函数 (Convolution Functions) +这些函数用于执行卷积操作,常用于处理图像、时间序列等数据。 + +- **`conv1d`**: 一维卷积,应用于序列数据(如时间序列)。 + - **输入**: input (N, C_in, L_in), weight (C_out, C_in, kernel_size) + - **输出**: (N, C_out, L_out) + - **用途**: 特征提取,如音频信号处理。 + - **参数**: stride, padding, dilation, groups 等控制卷积行为。 + +- **`conv2d`**: 二维卷积,适用于图像数据。 + - **输入**: input (N, C_in, H, W), weight (C_out, C_in, kH, kW) + - **输出**: (N, C_out, H_out, W_out) + - **用途**: 图像特征提取,如边缘检测。 + +- **`conv3d`**: 三维卷积,适用于视频或体视显微镜数据。 + - **输入**: input (N, C_in, D, H, W), weight (C_out, C_in, kD, kH, kW) + - **输出**: (N, C_out, D_out, H_out, W_out) + - **用途**: 视频处理或 3D 图像分析。 + +- **`conv_transpose1d` / `conv_transpose2d` / `conv_transpose3d`**: 转置卷积(有时称为“反卷积”),用于上采样。 + - **输入**: 类似普通卷积,但 weight 维度相反。 + - **输出**: 更大的特征图。 + - **用途**: 生成模型、图像分割中的上采样。 + +- **`unfold`**: 从输入张量中提取滑动局部块。 + - **输入**: input (N, C, *), kernel_size, stride, padding 等 + - **输出**: (N, C * prod(kernel_size), L) + - **用途**: 实现自定义卷积或池化操作。 + +- **`fold`**: 将滑动局部块组合成大张量,与 `unfold` 相反。 + - **输入**: input (N, C * prod(kernel_size), L), output_size, kernel_size + - **输出**: (N, C, output_size) + - **用途**: 重构特征图。 + +--- + +### 2. 池化函数 (Pooling Functions) +池化函数用于下采样,减少空间维度,增强模型的鲁棒性。 + +- **`avg_pool1d` / `avg_pool2d` / `avg_pool3d`**: 平均池化,计算区域内的平均值。 + - **输入**: input (N, C, *), kernel_size, stride + - **输出**: 降维后的张量 + - **用途**: 减少特征图尺寸,平滑特征。 + +- **`max_pool1d` / `max_pool2d` / `max_pool3d`**: 最大池化,提取区域内的最大值。 + - **输入**: input (N, C, *), kernel_size, stride, return_indices(可选) + - **输出**: 降维后的张量,可选返回最大值索引 + - **用途**: 提取显著特征,如边缘或纹理。 + +- **`max_unpool1d` / `max_unpool2d` / `max_unpool3d`**: 最大池化的逆操作,上采样。 + - **输入**: input, indices(来自 max_pool),output_size + - **输出**: 恢复的张量 + - **用途**: 解码器或生成模型中的上采样。 + +- **`lp_pool1d` / `lp_pool2d`**: Lp 范数池化,计算区域内的 p 次方均值。 + - **输入**: input, norm_type, kernel_size + - **输出**: 降维后的张量 + - **用途**: 更灵活的池化方式。 + +- **`adaptive_avg_pool1d` / `adaptive_avg_pool2d` / `adaptive_avg_pool3d`**: 自适应平均池化,输出固定大小。 + - **输入**: input, output_size + - **输出**: 指定大小的张量 + - **用途**: 适配不同输入尺寸的模型。 + +- **`adaptive_max_pool1d` / `adaptive_max_pool2d` / `adaptive_max_pool3d`**: 自适应最大池化。 + - **输入/输出**: 类似自适应平均池化 + - **用途**: 固定输出尺寸的特征提取。 + +--- + +### 3. 激活函数 (Non-linear Activations) +激活函数为神经网络引入非线性,增强表达能力。 + +- **`relu`**: ReLU 激活,f(x) = max(0, x)。 + - **输入**: 张量 + - **输出**: 相同形状的张量 + - **用途**: 常用激活函数,简单高效。 + +- **`relu6`**: ReLU 的变体,限制输出最大值为 6。 + - **用途**: 移动设备模型,控制数值范围。 + +- **`elu`**: 指数线性单元,f(x) = x if x > 0 else alpha * (exp(x) - 1)。 + - **用途**: 缓解梯度消失问题。 + +- **`selu`**: 缩放指数线性单元,需配合特定初始化。 + - **用途**: 自归一化网络。 + +- **`celu`**: 连续指数线性单元,平滑版 ELU。 + - **用途**: 更平滑的非线性。 + +- **`leaky_relu`**: Leaky ReLU,f(x) = x if x > 0 else negative_slope * x。 + - **用途**: 允许负值梯度,缓解“死亡 ReLU”问题。 + +- **`prelu`**: 参数化的 ReLU,negative_slope 可学习。 + - **用途**: 更灵活的激活。 + +- **`rrelu`**: 随机 ReLU,负斜率在训练时随机。 + - **用途**: 正则化,减少过拟合。 + +- **`glu`**: Gated Linear Unit,f(x) = x[:half] * sigmoid(x[half:])。 + - **用途**: 门控机制,语言模型常用。 + +- **`gelu`**: Gaussian Error Linear Unit,近似 ReLU 和 Dropout 的组合。 + - **用途**: Transformer 模型常用。 + +- **`sigmoid`**: Sigmoid 激活,f(x) = 1 / (1 + exp(-x))。 + - **用途**: 二分类输出。 + +- **`tanh`**: 双曲正切激活,f(x) = tanh(x)。 + - **用途**: 输出范围 [-1, 1] 的场景。 + +- **`softmax`**: Softmax 激活,归一化为概率分布。 + - **输入**: 张量,dim(归一化维度) + - **输出**: 概率分布 + - **用途**: 多分类任务。 + +- **`log_softmax`**: Log-Softmax,计算 softmax 的对数。 + - **用途**: 数值稳定性,配合 NLLLoss 使用。 + +- **`softplus`**: f(x) = log(1 + exp(x)),平滑近似 ReLU。 + - **用途**: 正输出场景。 + +- **`softsign`**: f(x) = x / (1 + |x|)。 + - **用途**: 输出范围 [-1, 1],平滑激活。 + +- **`silu`**: SiLU (Sigmoid Linear Unit),f(x) = x * sigmoid(x)。 + - **用途**: Transformer 模型。 + +- **`mish`**: f(x) = x * tanh(softplus(x))。 + - **用途**: 现代网络的平滑激活。 + +- **`hardswish` / `hardsigmoid` / `hardtanh`**: 硬性激活函数,计算效率高。 + - **用途**: 移动设备上的轻量模型。 + +- **`threshold`**: 阈值激活,小于阈值设为指定值。 + - **用途**: 稀疏激活。 + +--- + +### 4. 归一化函数 (Normalization Functions) +归一化函数用于稳定训练,加速收敛。 + +- **`batch_norm`**: 批归一化,基于 mini-batch 统计归一化。 + - **输入**: input, running_mean, running_var, weight, bias + - **输出**: 归一化后的张量 + - **用途**: 加速训练,减少内部协变量偏移。 + +- **`instance_norm`**: 实例归一化,基于单个样本归一化。 + - **用途**: 风格迁移、图像生成。 + +- **`layer_norm`**: 层归一化,基于特征维度归一化。 + - **用途**: Transformer 和 RNN。 + +- **`group_norm`**: 组归一化,将通道分组归一化。 + - **用途**: 小批量场景。 + +- **`local_response_norm`**: 局部响应归一化,基于邻域归一化。 + - **用途**: 早期卷积网络(如 AlexNet)。 + +--- + +### 5. 线性函数 (Linear Functions) +- **`linear`**: 线性变换,y = xW^T + b。 + - **输入**: input, weight, bias + - **输出**: 变换后的张量 + - **用途**: 全连接层。 + +- **`bilinear`**: 双线性变换,y = x1^T W x2 + b。 + - **用途**: 多输入特征交互。 + +--- + +### 6. 损失函数 (Loss Functions) +损失函数用于衡量模型预测与真实值之间的差异。 + +- **`mse_loss`**: 均方误差,适用于回归任务。 +- **`l1_loss`**: L1 损失,绝对值误差。 +- **`smooth_l1_loss`**: 平滑 L1 损失,结合 MSE 和 L1 的优点。 +- **`kl_div`**: KL 散度,衡量分布差异。 +- **`cross_entropy`**: 交叉熵损失,适用于分类任务。 +- **`nll_loss`**: 负对数似然损失,常与 log_softmax 配合。 +- **`hinge_loss`**: Hinge 损失,用于 SVM 式分类。 +- **`margin_ranking_loss`**: 排序损失,用于排序任务。 +- **`triplet_margin_loss`**: 三元组损失,用于嵌入学习。 +- **`ctc_loss`**: 连接主义时序分类损失,用于序列任务。 +- **`bce_loss` / `bce_with_logits_loss`**: 二元交叉熵,适用于二分类。 + +--- + +### 7. 注意力机制 (Attention Mechanisms) +- **`scaled_dot_product_attention`**: 缩放点积注意力,Transformer 的核心组件。 + - **输入**: query, key, value, attn_mask(可选) + - **输出**: 注意力加权后的值 + - **用途**: Transformer 模型()。[](https://docs.pytorch.org/tutorials/deep-dive.html) + +--- + +### 8. 其他函数 +- **`dropout` / `dropout2d` / `dropout3d`**: Dropout 正则化,随机置零。 +- **`embedding`**: 嵌入层,将索引映射为向量。 +- **`one_hot`**: 独热编码,整数转独热向量。 +- **`pad`**: 张量填充,用于调整尺寸。 +- **`interpolate`**: 插值上采样或下采样。 +- **`grid_sample`**: 网格采样,用于空间变换。 +- **`affine_grid`**: 生成仿射变换的网格。 + +--- + +### 注意事项 +1. **函数式 vs 模块化**: + - `torch.nn.functional` 提供无状态的函数式接口,适合在 `forward` 方法中调用。相比之下,`torch.nn` 的模块(如 `nn.Conv2d`)会管理参数(如权重和偏置),适合在 `__init__` 中定义()。[](https://discuss.pytorch.org/t/difference-of-methods-between-torch-nn-and-functional/1076) + - 例如,`F.relu` 不保存参数,而 `nn.ReLU` 是模块化的,性能上无明显差异()。[](https://discuss.pytorch.org/t/difference-of-methods-between-torch-nn-and-functional/1076) + +2. **使用场景**: + - 卷积、池化、线性变换等常用于卷积神经网络(CNN)。 + - 注意力机制和归一化常用于 Transformer 模型。 + - 损失函数根据任务类型(如分类、回归、排序)选择。 + +3. **文档更新**: + - 以上基于 PyTorch 2.8 文档(截至 2024 年 11 月,)。建议查看最新文档(https://pytorch.org/docs/stable/nn.functional.html)以获取新增功能或更新。[](https://docs.pytorch.org/docs/2.8/nn.functional.html) + +--- + +### 示例代码 +以下是一个简单的 CNN 前向传播示例,展示如何使用 `torch.nn.functional`: + +```python +import torch +import torch.nn.functional as F + +# 输入张量 (batch_size=1, channels=1, height=28, width=28) +x = torch.randn(1, 1, 28, 28) +# 卷积核 +weight = torch.randn(6, 1, 5, 5) +bias = torch.randn(6) + +# 卷积 + ReLU + 最大池化 +x = F.conv2d(x, weight, bias, stride=1, padding=2) +x = F.relu(x) +x = F.max_pool2d(x, kernel_size=2, stride=2) +print(x.shape) # 输出: torch.Size([1, 6, 14, 14]) +``` + +--- + +如果您需要某类函数的详细讲解、特定方法的代码示例,或想深入某个功能(如注意力机制或损失函数),请告诉我,我可以进一步展开! + +是的,你的理解非常正确!torch.nn.functional(通常简写为 F)中的方法是纯函数式接口,它们只进行计算,不管理或记录任何参数(如权重或偏置)。下面详细解答你的问题,并澄清其与神经网络的关系。 +1. torch.nn.functional 的本质 + +纯函数计算:torch.nn.functional 提供的是无状态的函数,输入张量后直接执行特定操作(如卷积、激活、池化等),并返回结果。这些函数不会保存任何内部状态或参数。 + +例如,F.conv2d(input, weight, bias) 需要显式传入 input、卷积核 weight 和偏置 bias(如果有),函数只负责计算卷积操作并返回结果。 + + +不记录参数:与 torch.nn 模块(如 nn.Conv2d)不同,F 中的函数不会自动管理权重或偏置参数。这些参数需要由用户手动提供或通过其他机制(如 nn.Parameter)管理。 +与神经网络的关系:虽然 torch.nn.functional 本身不直接构成神经网络,但它提供了构建神经网络所需的核心计算操作。神经网络的实现通常结合 torch.nn.Module(管理参数和层结构)与 F 的函数(执行具体计算)。 + +2. torch.nn.functional vs torch.nn +为了更好理解,我们对比一下 torch.nn.functional 和 torch.nn 模块: + + +特性torch.nn.functionaltorch.nn (如 nn.Conv2d, nn.ReLU)类型函数式接口,无状态模块化接口,有状态参数管理不管理参数,需手动传入权重、偏置等自动管理参数(如权重和偏置)典型用途在 forward 方法中实现具体计算在 __init__ 中定义网络层灵活性更灵活,适合自定义操作更封装,适合标准网络结构示例F.conv2d(x, weight, bias)self.conv = nn.Conv2d(1, 6, 3) + +例子: + +使用 torch.nn.Conv2d: +pythonimport torch +import torch.nn as nn + +conv = nn.Conv2d(1, 6, 3) # 定义卷积层,自动管理 weight 和 bias +x = torch.randn(1, 1, 28, 28) +y = conv(x) # 直接调用,参数由模块管理 + +使用 torch.nn.functional: +pythonimport torch.nn.functional as F + +x = torch.randn(1, 1, 28, 28) +weight = torch.randn(6, 1, 3, 3) # 手动定义权重 +bias = torch.randn(6) # 手动定义偏置 +y = F.conv2d(x, weight, bias) # 显式传入参数 + + + +1. 为什么使用 torch.nn.functional? +虽然 torch.nn 模块更方便(因为它封装了参数管理),但 F 的函数式接口在以下场景中更有优势: + +自定义操作:当需要自定义权重计算或动态调整参数时,F 提供更大灵活性。例如,可以在每次前向传播中修改权重。 +轻量级模型:在不需要持久化参数的场景(如某些实验性模型或推理阶段),直接使用 F 可以减少内存开销。 +函数式编程:适合函数式编程风格,便于将操作组合成复杂的计算流程。 +特殊场景:如实现自定义激活函数、池化操作,或在 Transformer 中实现注意力 \ No newline at end of file diff --git a/Pytorch/nn/Functional/OnlyCalculateNoRecordingPms-Use.nn.Func b/Pytorch/nn/Functional/OnlyCalculateNoRecordingPms-Use.nn.Func new file mode 100644 index 0000000..e69de29 diff --git a/Pytorch/nn/Module/List(Dict)AreUsedToStoreModule b/Pytorch/nn/Module/List(Dict)AreUsedToStoreModule new file mode 100644 index 0000000..e69de29 diff --git a/Pytorch/nn/nn.Module.md b/Pytorch/nn/Module/nn.Module.md similarity index 100% rename from Pytorch/nn/nn.Module.md rename to Pytorch/nn/Module/nn.Module.md diff --git a/Pytorch/nn/Module/nn.ModuleDict.md b/Pytorch/nn/Module/nn.ModuleDict.md new file mode 100644 index 0000000..4fadf44 --- /dev/null +++ b/Pytorch/nn/Module/nn.ModuleDict.md @@ -0,0 +1,359 @@ +根据 PyTorch 官方文档(`torch.nn.ModuleList` 和 `torch.nn.ModuleDict`,基于 PyTorch 2.8),以下是对这两个类的详细讲解,包括它们的定义、作用以及所有方法的全面说明。`torch.nn.ModuleList` 和 `torch.nn.ModuleDict` 是 PyTorch 中用于管理子模块(`nn.Module` 实例)的容器类,类似于 Python 的 `list` 和 `dict`,但专为 PyTorch 的模块化设计优化。它们的主要作用是方便在 `nn.Module` 中组织和管理多个子模块,确保这些子模块被正确注册并参与前向传播、参数管理和设备迁移等操作。以下内容基于官方文档和其他可靠来源(如 PyTorch Forums 和 Stack Overflow),确保准确且全面。 + +--- + +## 1. `torch.nn.ModuleList` + +### 1.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ModuleList(modules=None) +``` +- **作用**:`torch.nn.ModuleList` 是一个容器类,用于以列表形式存储多个 `nn.Module` 实例(子模块)。它类似于 Python 的内置 `list`,但专为 PyTorch 的模块管理设计,存储的子模块会自动注册到父模块中,参与 `parameters()`、`named_parameters()`、设备迁移(如 `to(device)`)和前向传播。 +- **特性**: + - **自动注册**:当 `nn.ModuleList` 作为 `nn.Module` 的属性时,其中的子模块会自动被 `model.modules()` 和 `model.parameters()` 识别,而普通 Python 列表中的模块不会。 + - **动态管理**:支持动态添加或移除子模块,适合需要变长模块列表的场景(如循环神经网络或变长层结构)。 + - **用途**:常用于需要动态或顺序管理多个子模块的模型,例如堆叠多个线性层或卷积层。 +- **参数**: + - `modules`:一个可选的可迭代对象,包含初始的 `nn.Module` 实例。 + +**示例**: +```python +import torch +import torch.nn as nn + +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.layers = nn.ModuleList([nn.Linear(10, 10) for _ in range(3)]) + + def forward(self, x): + for layer in self.layers: + x = layer(x) + return x + +model = MyModel() +print(list(model.modules())) # 输出模型及其子模块 +print(list(model.parameters())) # 输出所有线性层的参数 +``` + +### 1.2 方法讲解 + +`torch.nn.ModuleList` 支持以下方法,主要继承自 Python 的 `list`,并添加了 PyTorch 的模块管理特性。以下是所有方法的详细说明(基于官方文档和实际用法): + +1. **`append(module)`**: + - **作用**:向 `ModuleList` 末尾添加一个 `nn.Module` 实例。 + - **参数**: + - `module`:一个 `nn.Module` 实例。 + - **返回值**:`self`(`ModuleList` 本身,支持链式调用)。 + - **示例**: + ```python + module_list = nn.ModuleList() + module_list.append(nn.Linear(10, 10)) + print(len(module_list)) # 输出 1 + print(isinstance(module_list[0], nn.Linear)) # 输出 True + ``` + - **注意**:添加的模块会自动注册到父模块的参数和模块列表中。 + +2. **`extend(modules)`**: + - **作用**:将一个可迭代对象中的 `nn.Module` 实例追加到 `ModuleList` 末尾。 + - **参数**: + - `modules`:一个可迭代对象,包含 `nn.Module` 实例。 + - **返回值**:`self`。 + - **示例**: + ```python + module_list = nn.ModuleList() + module_list.extend([nn.Linear(10, 10), nn.Linear(10, 5)]) + print(len(module_list)) # 输出 2 + ``` + - **注意**:`extend` 比逐个 `append` 更高效,适合批量添加子模块。 + - **Stack Overflow 示例**:合并两个 `ModuleList`: + ```python + module_list = nn.ModuleList() + module_list.extend(sub_list_1) + module_list.extend(sub_list_2) + # 或者 + module_list = nn.ModuleList([*sub_list_1, *sub_list_2]) + ``` + +3. **索引操作(如 `__getitem__`, `__setitem__`)**: + - **作用**:支持像 Python 列表一样的索引访问和赋值操作。 + - **参数**: + - 索引(整数或切片)。 + - **返回值**:指定索引处的 `nn.Module`。 + - **示例**: + ```python + module_list = nn.ModuleList([nn.Linear(10, 10) for _ in range(3)]) + print(module_list[0]) # 访问第一个线性层 + module_list[0] = nn.Linear(10, 5) # 替换第一个模块 + ``` + - **注意**:赋值时,新值必须是 `nn.Module` 实例。 + +4. **迭代操作(如 `__iter__`)**: + - **作用**:支持迭代,允许遍历 `ModuleList` 中的所有子模块。 + - **返回值**:迭代器,逐个返回 `nn.Module`。 + - **示例**: + ```python + for module in module_list: + print(module) # 打印每个子模块 + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ModuleList` 中子模块的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(module_list)) # 输出子模块数量 + ``` + +6. **其他列表操作**: + - `ModuleList` 支持 Python 列表的常见方法,如 `pop()`, `clear()`, `insert()`, `remove()` 等,但这些方法在官方文档中未明确列出(基于 Python 的 `list` 实现)。 + - **示例**(`pop`): + ```python + module_list = nn.ModuleList([nn.Linear(10, 10) for _ in range(3)]) + removed_module = module_list.pop(0) # 移除并返回第一个模块 + print(len(module_list)) # 输出 2 + ``` + - **PyTorch Forums 讨论**:有用户询问如何动态移除 `ModuleList` 中的模块,可以使用 `pop(index)` 或重新构造列表: + ```python + module_list = nn.ModuleList(module_list[:index] + module_list[index+1:]) + ``` + +### 1.3 注意事项 + +- **与普通 Python 列表的区别**:普通 Python 列表中的 `nn.Module` 不会自动注册到父模块的参数或模块列表中,而 `ModuleList` 会。 +- **与 `nn.ParameterList` 的区别**:`ModuleList` 存储 `nn.Module`(子模块),而 `nn.ParameterList` 存储 `nn.Parameter`(参数)。 +- **动态性**:`ModuleList` 适合动态模型(如变长层结构),但频繁操作可能影响性能。 +- **优化器集成**:`ModuleList` 中的子模块的参数会自动被 `model.parameters()` 包含,优化器会更新这些参数。 + +--- + +## 2. `torch.nn.ModuleDict` + +### 2.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ModuleDict(modules=None) +``` +- **作用**:`torch.nn.ModuleDict` 是一个容器类,用于以字典形式存储多个 `nn.Module` 实例。类似于 Python 的内置 `dict`,但专为 PyTorch 的模块管理设计,存储的子模块会自动注册到父模块中。 +- **特性**: + - **键值存储**:使用字符串键索引子模块,便于按名称访问。 + - **自动注册**:子模块会自动被 `model.modules()` 和 `model.parameters()` 识别。 + - **用途**:适合需要按名称管理子模块的场景,例如多任务学习或具有语义化模块的复杂模型。 +- **参数**: + - `modules`:一个可选的可迭代对象,包含键值对(键为字符串,值为 `nn.Module` 实例)。 + +**示例**: +```python +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.layers = nn.ModuleDict({ + 'layer1': nn.Linear(10, 10), + 'layer2': nn.Linear(10, 5) + }) + + def forward(self, x): + x = self.layers['layer1'](x) + x = self.layers['layer2'](x) + return x + +model = MyModel() +print(list(model.modules())) # 输出模型及其子模块 +``` + +### 2.2 方法讲解 + +`torch.nn.ModuleDict` 支持以下方法,主要继承自 Python 的 `dict`,并添加了 PyTorch 的模块管理特性。以下是所有方法的详细说明: + +1. **`__setitem__(key, module)`**: + - **作用**:向 `ModuleDict` 添加或更新一个键值对。 + - **参数**: + - `key`:字符串,子模块的名称。 + - `module`:`nn.Module` 实例。 + - **示例**: + ```python + module_dict = nn.ModuleDict() + module_dict['layer1'] = nn.Linear(10, 10) + print(module_dict['layer1']) # 输出线性层 + ``` + +2. **`update([other])`**: + - **作用**:使用另一个字典或键值对更新 `ModuleDict`。 + - **参数**: + - `other`:一个字典或键值对的可迭代对象,值必须是 `nn.Module`。 + - **示例**: + ```python + module_dict = nn.ModuleDict() + module_dict.update({'layer1': nn.Linear(10, 10), 'layer2': nn.Linear(10, 5)}) + print(len(module_dict)) # 输出 2 + ``` + +3. **索引操作(如 `__getitem__`)**: + - **作用**:通过键访问 `ModuleDict` 中的子模块。 + - **参数**: + - 键(字符串)。 + - **返回值**:对应的 `nn.Module`。 + - **示例**: + ```python + print(module_dict['layer1']) # 访问 layer1 模块 + ``` + +4. **迭代操作(如 `__iter__`, `keys()`, `values()`, `items()`)**: + - **作用**:支持迭代键、值或键值对。 + - **返回值**: + - `keys()`:返回所有键的迭代器。 + - `values()`:返回所有 `nn.Module` 的迭代器。 + - `items()`:返回键值对的迭代器。 + - **示例**: + ```python + for key, module in module_dict.items(): + print(f"Key: {key}, Module: {module}") + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ModuleDict` 中子模块的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(module_dict)) # 输出子模块数量 + ``` + +6. **其他字典操作**: + - `ModuleDict` 支持 Python 字典的常见方法,如 `pop(key)`, `clear()`, `popitem()`, `get(key, default=None)` 等。 + - **示例**(`pop`): + ```python + module_dict = nn.ModuleDict({'layer1': nn.Linear(10, 10), 'layer2': nn.Linear(10, 5)}) + removed_module = module_dict.pop('layer1') # 移除并返回 layer1 + print(len(module_dict)) # 输出 1 + ``` + +### 2.3 注意事项 + +- **与普通 Python 字典的区别**:普通 Python 字典中的 `nn.Module` 不会自动注册到父模块,而 `ModuleDict` 会。 +- **与 `nn.ParameterDict` 的区别**:`ModuleDict` 存储 `nn.Module`,而 `nn.ParameterDict` 存储 `nn.Parameter`。 +- **键的唯一性**:`ModuleDict` 的键必须是字符串,且不能重复。 +- **优化器集成**:`ModuleDict` 中的子模块的参数会自动被 `model.parameters()` 包含。 + +--- + +## 3. 比较与使用场景 + +| 特性 | `ModuleList` | `ModuleDict` | +|---------------------|-------------------------------------------|-------------------------------------------| +| **存储方式** | 列表(按索引访问) | 字典(按键访问) | +| **访问方式** | 索引(`module_list[0]`) | 键(`module_dict['key']`) | +| **主要方法** | `append`, `extend`, `pop`, 索引操作 | `update`, `pop`, `keys`, `values`, `items` | +| **适用场景** | 顺序模块管理(如多层堆叠的神经网络) | 命名模块管理(如多任务模型中的模块) | +| **动态性** | 适合动态添加/移除模块 | 适合按名称管理模块 | + +**选择建议**: +- 如果子模块需要按顺序调用(如多层网络),使用 `ModuleList`。 +- 如果子模块需要按名称访问或具有明确语义(如多任务模型),使用 `ModuleDict`。 + +--- + +## 4. 综合示例 + +以下是一个结合 `ModuleList` 和 `ModuleDict` 的示例,展示它们在模型中的使用: + +```python +import torch +import torch.nn as nn + +class ComplexModel(nn.Module): + def __init__(self): + super().__init__() + # 使用 ModuleList 存储一组线性层 + self.list_layers = nn.ModuleList([nn.Linear(10, 10) for _ in range(2)]) + # 使用 ModuleDict 存储命名模块 + self.dict_layers = nn.ModuleDict({ + 'conv': nn.Conv2d(3, 64, kernel_size=3), + 'fc': nn.Linear(10, 5) + }) + + def forward(self, x): + # 使用 ModuleList + for layer in self.list_layers: + x = layer(x) + # 使用 ModuleDict + x = self.dict_layers['fc'](x) + return x + +model = ComplexModel() +optimizer = torch.optim.SGD(model.parameters(), lr=0.01) + +# 打印所有模块 +for name, module in model.named_modules(): + print(f"Module name: {name}, Module: {module}") + +# 动态修改 ModuleList +model.list_layers.append(nn.Linear(10, 10)) + +# 动态修改 ModuleDict +model.dict_layers['new_fc'] = nn.Linear(5, 2) +``` + +--- + +## 5. 常见问题与解答 + +1. **如何高效合并两个 `ModuleList`?** + - 使用 `extend` 方法或解包方式: + ```python + module_list = nn.ModuleList() + module_list.extend(sub_list_1) + module_list.extend(sub_list_2) + # 或者 + module_list = nn.ModuleList([*sub_list_1, *sub_list_2]) + ``` + +2. **如何从 `ModuleList` 删除模块?** + - 使用 `pop(index)` 或重新构造列表: + ```python + module_list.pop(0) # 移除第一个模块 + # 或者 + module_list = nn.ModuleList([module for i, module in enumerate(module_list) if i != 0]) + ``` + +3. **如何检查 `ModuleDict` 中的模块?** + - 使用 `keys()`, `values()`, 或 `items()` 遍历: + ```python + for key, module in module_dict.items(): + print(f"Key: {key}, Module: {module}") + ``` + +4. **如何初始化子模块的参数?** + - 使用 `nn.Module.apply` 或直接遍历: + ```python + def init_weights(m): + if isinstance(m, nn.Linear): + nn.init.xavier_uniform_(m.weight) + model.apply(init_weights) + # 或者 + for module in module_list: + if isinstance(module, nn.Linear): + nn.init.xavier_uniform_(module.weight) + ``` + +--- + +## 6. 总结 + +- **`torch.nn.ModuleList`**: + - 方法:`append`, `extend`, `pop`, 索引/迭代操作。 + - 特点:类似列表,适合顺序管理子模块,自动注册到父模块。 + - 场景:动态模型、多层堆叠网络。 +- **`torch.nn.ModuleDict`**: + - 方法:`update`, `pop`, `keys`, `values`, `items`, 索引/迭代操作。 + - 特点:类似字典,适合按名称管理子模块,自动注册。 + - 场景:多任务学习、需要语义化命名的模型。 + +**参考文献**: +- PyTorch 官方文档:`torch.nn.ModuleList` 和 `torch.nn.ModuleDict`(`docs.pytorch.org`) +- Stack Overflow:合并 `ModuleList` 的讨论 +- PyTorch Forums:`ModuleList` 和 `ModuleDict` 的动态操作 + +如果需要更详细的代码示例、特定方法的实现,或其他相关问题(如与优化器或设备迁移的集成),请告诉我! \ No newline at end of file diff --git a/Pytorch/nn/Module/nn.ModuleList.md b/Pytorch/nn/Module/nn.ModuleList.md new file mode 100644 index 0000000..4fadf44 --- /dev/null +++ b/Pytorch/nn/Module/nn.ModuleList.md @@ -0,0 +1,359 @@ +根据 PyTorch 官方文档(`torch.nn.ModuleList` 和 `torch.nn.ModuleDict`,基于 PyTorch 2.8),以下是对这两个类的详细讲解,包括它们的定义、作用以及所有方法的全面说明。`torch.nn.ModuleList` 和 `torch.nn.ModuleDict` 是 PyTorch 中用于管理子模块(`nn.Module` 实例)的容器类,类似于 Python 的 `list` 和 `dict`,但专为 PyTorch 的模块化设计优化。它们的主要作用是方便在 `nn.Module` 中组织和管理多个子模块,确保这些子模块被正确注册并参与前向传播、参数管理和设备迁移等操作。以下内容基于官方文档和其他可靠来源(如 PyTorch Forums 和 Stack Overflow),确保准确且全面。 + +--- + +## 1. `torch.nn.ModuleList` + +### 1.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ModuleList(modules=None) +``` +- **作用**:`torch.nn.ModuleList` 是一个容器类,用于以列表形式存储多个 `nn.Module` 实例(子模块)。它类似于 Python 的内置 `list`,但专为 PyTorch 的模块管理设计,存储的子模块会自动注册到父模块中,参与 `parameters()`、`named_parameters()`、设备迁移(如 `to(device)`)和前向传播。 +- **特性**: + - **自动注册**:当 `nn.ModuleList` 作为 `nn.Module` 的属性时,其中的子模块会自动被 `model.modules()` 和 `model.parameters()` 识别,而普通 Python 列表中的模块不会。 + - **动态管理**:支持动态添加或移除子模块,适合需要变长模块列表的场景(如循环神经网络或变长层结构)。 + - **用途**:常用于需要动态或顺序管理多个子模块的模型,例如堆叠多个线性层或卷积层。 +- **参数**: + - `modules`:一个可选的可迭代对象,包含初始的 `nn.Module` 实例。 + +**示例**: +```python +import torch +import torch.nn as nn + +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.layers = nn.ModuleList([nn.Linear(10, 10) for _ in range(3)]) + + def forward(self, x): + for layer in self.layers: + x = layer(x) + return x + +model = MyModel() +print(list(model.modules())) # 输出模型及其子模块 +print(list(model.parameters())) # 输出所有线性层的参数 +``` + +### 1.2 方法讲解 + +`torch.nn.ModuleList` 支持以下方法,主要继承自 Python 的 `list`,并添加了 PyTorch 的模块管理特性。以下是所有方法的详细说明(基于官方文档和实际用法): + +1. **`append(module)`**: + - **作用**:向 `ModuleList` 末尾添加一个 `nn.Module` 实例。 + - **参数**: + - `module`:一个 `nn.Module` 实例。 + - **返回值**:`self`(`ModuleList` 本身,支持链式调用)。 + - **示例**: + ```python + module_list = nn.ModuleList() + module_list.append(nn.Linear(10, 10)) + print(len(module_list)) # 输出 1 + print(isinstance(module_list[0], nn.Linear)) # 输出 True + ``` + - **注意**:添加的模块会自动注册到父模块的参数和模块列表中。 + +2. **`extend(modules)`**: + - **作用**:将一个可迭代对象中的 `nn.Module` 实例追加到 `ModuleList` 末尾。 + - **参数**: + - `modules`:一个可迭代对象,包含 `nn.Module` 实例。 + - **返回值**:`self`。 + - **示例**: + ```python + module_list = nn.ModuleList() + module_list.extend([nn.Linear(10, 10), nn.Linear(10, 5)]) + print(len(module_list)) # 输出 2 + ``` + - **注意**:`extend` 比逐个 `append` 更高效,适合批量添加子模块。 + - **Stack Overflow 示例**:合并两个 `ModuleList`: + ```python + module_list = nn.ModuleList() + module_list.extend(sub_list_1) + module_list.extend(sub_list_2) + # 或者 + module_list = nn.ModuleList([*sub_list_1, *sub_list_2]) + ``` + +3. **索引操作(如 `__getitem__`, `__setitem__`)**: + - **作用**:支持像 Python 列表一样的索引访问和赋值操作。 + - **参数**: + - 索引(整数或切片)。 + - **返回值**:指定索引处的 `nn.Module`。 + - **示例**: + ```python + module_list = nn.ModuleList([nn.Linear(10, 10) for _ in range(3)]) + print(module_list[0]) # 访问第一个线性层 + module_list[0] = nn.Linear(10, 5) # 替换第一个模块 + ``` + - **注意**:赋值时,新值必须是 `nn.Module` 实例。 + +4. **迭代操作(如 `__iter__`)**: + - **作用**:支持迭代,允许遍历 `ModuleList` 中的所有子模块。 + - **返回值**:迭代器,逐个返回 `nn.Module`。 + - **示例**: + ```python + for module in module_list: + print(module) # 打印每个子模块 + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ModuleList` 中子模块的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(module_list)) # 输出子模块数量 + ``` + +6. **其他列表操作**: + - `ModuleList` 支持 Python 列表的常见方法,如 `pop()`, `clear()`, `insert()`, `remove()` 等,但这些方法在官方文档中未明确列出(基于 Python 的 `list` 实现)。 + - **示例**(`pop`): + ```python + module_list = nn.ModuleList([nn.Linear(10, 10) for _ in range(3)]) + removed_module = module_list.pop(0) # 移除并返回第一个模块 + print(len(module_list)) # 输出 2 + ``` + - **PyTorch Forums 讨论**:有用户询问如何动态移除 `ModuleList` 中的模块,可以使用 `pop(index)` 或重新构造列表: + ```python + module_list = nn.ModuleList(module_list[:index] + module_list[index+1:]) + ``` + +### 1.3 注意事项 + +- **与普通 Python 列表的区别**:普通 Python 列表中的 `nn.Module` 不会自动注册到父模块的参数或模块列表中,而 `ModuleList` 会。 +- **与 `nn.ParameterList` 的区别**:`ModuleList` 存储 `nn.Module`(子模块),而 `nn.ParameterList` 存储 `nn.Parameter`(参数)。 +- **动态性**:`ModuleList` 适合动态模型(如变长层结构),但频繁操作可能影响性能。 +- **优化器集成**:`ModuleList` 中的子模块的参数会自动被 `model.parameters()` 包含,优化器会更新这些参数。 + +--- + +## 2. `torch.nn.ModuleDict` + +### 2.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ModuleDict(modules=None) +``` +- **作用**:`torch.nn.ModuleDict` 是一个容器类,用于以字典形式存储多个 `nn.Module` 实例。类似于 Python 的内置 `dict`,但专为 PyTorch 的模块管理设计,存储的子模块会自动注册到父模块中。 +- **特性**: + - **键值存储**:使用字符串键索引子模块,便于按名称访问。 + - **自动注册**:子模块会自动被 `model.modules()` 和 `model.parameters()` 识别。 + - **用途**:适合需要按名称管理子模块的场景,例如多任务学习或具有语义化模块的复杂模型。 +- **参数**: + - `modules`:一个可选的可迭代对象,包含键值对(键为字符串,值为 `nn.Module` 实例)。 + +**示例**: +```python +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.layers = nn.ModuleDict({ + 'layer1': nn.Linear(10, 10), + 'layer2': nn.Linear(10, 5) + }) + + def forward(self, x): + x = self.layers['layer1'](x) + x = self.layers['layer2'](x) + return x + +model = MyModel() +print(list(model.modules())) # 输出模型及其子模块 +``` + +### 2.2 方法讲解 + +`torch.nn.ModuleDict` 支持以下方法,主要继承自 Python 的 `dict`,并添加了 PyTorch 的模块管理特性。以下是所有方法的详细说明: + +1. **`__setitem__(key, module)`**: + - **作用**:向 `ModuleDict` 添加或更新一个键值对。 + - **参数**: + - `key`:字符串,子模块的名称。 + - `module`:`nn.Module` 实例。 + - **示例**: + ```python + module_dict = nn.ModuleDict() + module_dict['layer1'] = nn.Linear(10, 10) + print(module_dict['layer1']) # 输出线性层 + ``` + +2. **`update([other])`**: + - **作用**:使用另一个字典或键值对更新 `ModuleDict`。 + - **参数**: + - `other`:一个字典或键值对的可迭代对象,值必须是 `nn.Module`。 + - **示例**: + ```python + module_dict = nn.ModuleDict() + module_dict.update({'layer1': nn.Linear(10, 10), 'layer2': nn.Linear(10, 5)}) + print(len(module_dict)) # 输出 2 + ``` + +3. **索引操作(如 `__getitem__`)**: + - **作用**:通过键访问 `ModuleDict` 中的子模块。 + - **参数**: + - 键(字符串)。 + - **返回值**:对应的 `nn.Module`。 + - **示例**: + ```python + print(module_dict['layer1']) # 访问 layer1 模块 + ``` + +4. **迭代操作(如 `__iter__`, `keys()`, `values()`, `items()`)**: + - **作用**:支持迭代键、值或键值对。 + - **返回值**: + - `keys()`:返回所有键的迭代器。 + - `values()`:返回所有 `nn.Module` 的迭代器。 + - `items()`:返回键值对的迭代器。 + - **示例**: + ```python + for key, module in module_dict.items(): + print(f"Key: {key}, Module: {module}") + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ModuleDict` 中子模块的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(module_dict)) # 输出子模块数量 + ``` + +6. **其他字典操作**: + - `ModuleDict` 支持 Python 字典的常见方法,如 `pop(key)`, `clear()`, `popitem()`, `get(key, default=None)` 等。 + - **示例**(`pop`): + ```python + module_dict = nn.ModuleDict({'layer1': nn.Linear(10, 10), 'layer2': nn.Linear(10, 5)}) + removed_module = module_dict.pop('layer1') # 移除并返回 layer1 + print(len(module_dict)) # 输出 1 + ``` + +### 2.3 注意事项 + +- **与普通 Python 字典的区别**:普通 Python 字典中的 `nn.Module` 不会自动注册到父模块,而 `ModuleDict` 会。 +- **与 `nn.ParameterDict` 的区别**:`ModuleDict` 存储 `nn.Module`,而 `nn.ParameterDict` 存储 `nn.Parameter`。 +- **键的唯一性**:`ModuleDict` 的键必须是字符串,且不能重复。 +- **优化器集成**:`ModuleDict` 中的子模块的参数会自动被 `model.parameters()` 包含。 + +--- + +## 3. 比较与使用场景 + +| 特性 | `ModuleList` | `ModuleDict` | +|---------------------|-------------------------------------------|-------------------------------------------| +| **存储方式** | 列表(按索引访问) | 字典(按键访问) | +| **访问方式** | 索引(`module_list[0]`) | 键(`module_dict['key']`) | +| **主要方法** | `append`, `extend`, `pop`, 索引操作 | `update`, `pop`, `keys`, `values`, `items` | +| **适用场景** | 顺序模块管理(如多层堆叠的神经网络) | 命名模块管理(如多任务模型中的模块) | +| **动态性** | 适合动态添加/移除模块 | 适合按名称管理模块 | + +**选择建议**: +- 如果子模块需要按顺序调用(如多层网络),使用 `ModuleList`。 +- 如果子模块需要按名称访问或具有明确语义(如多任务模型),使用 `ModuleDict`。 + +--- + +## 4. 综合示例 + +以下是一个结合 `ModuleList` 和 `ModuleDict` 的示例,展示它们在模型中的使用: + +```python +import torch +import torch.nn as nn + +class ComplexModel(nn.Module): + def __init__(self): + super().__init__() + # 使用 ModuleList 存储一组线性层 + self.list_layers = nn.ModuleList([nn.Linear(10, 10) for _ in range(2)]) + # 使用 ModuleDict 存储命名模块 + self.dict_layers = nn.ModuleDict({ + 'conv': nn.Conv2d(3, 64, kernel_size=3), + 'fc': nn.Linear(10, 5) + }) + + def forward(self, x): + # 使用 ModuleList + for layer in self.list_layers: + x = layer(x) + # 使用 ModuleDict + x = self.dict_layers['fc'](x) + return x + +model = ComplexModel() +optimizer = torch.optim.SGD(model.parameters(), lr=0.01) + +# 打印所有模块 +for name, module in model.named_modules(): + print(f"Module name: {name}, Module: {module}") + +# 动态修改 ModuleList +model.list_layers.append(nn.Linear(10, 10)) + +# 动态修改 ModuleDict +model.dict_layers['new_fc'] = nn.Linear(5, 2) +``` + +--- + +## 5. 常见问题与解答 + +1. **如何高效合并两个 `ModuleList`?** + - 使用 `extend` 方法或解包方式: + ```python + module_list = nn.ModuleList() + module_list.extend(sub_list_1) + module_list.extend(sub_list_2) + # 或者 + module_list = nn.ModuleList([*sub_list_1, *sub_list_2]) + ``` + +2. **如何从 `ModuleList` 删除模块?** + - 使用 `pop(index)` 或重新构造列表: + ```python + module_list.pop(0) # 移除第一个模块 + # 或者 + module_list = nn.ModuleList([module for i, module in enumerate(module_list) if i != 0]) + ``` + +3. **如何检查 `ModuleDict` 中的模块?** + - 使用 `keys()`, `values()`, 或 `items()` 遍历: + ```python + for key, module in module_dict.items(): + print(f"Key: {key}, Module: {module}") + ``` + +4. **如何初始化子模块的参数?** + - 使用 `nn.Module.apply` 或直接遍历: + ```python + def init_weights(m): + if isinstance(m, nn.Linear): + nn.init.xavier_uniform_(m.weight) + model.apply(init_weights) + # 或者 + for module in module_list: + if isinstance(module, nn.Linear): + nn.init.xavier_uniform_(module.weight) + ``` + +--- + +## 6. 总结 + +- **`torch.nn.ModuleList`**: + - 方法:`append`, `extend`, `pop`, 索引/迭代操作。 + - 特点:类似列表,适合顺序管理子模块,自动注册到父模块。 + - 场景:动态模型、多层堆叠网络。 +- **`torch.nn.ModuleDict`**: + - 方法:`update`, `pop`, `keys`, `values`, `items`, 索引/迭代操作。 + - 特点:类似字典,适合按名称管理子模块,自动注册。 + - 场景:多任务学习、需要语义化命名的模型。 + +**参考文献**: +- PyTorch 官方文档:`torch.nn.ModuleList` 和 `torch.nn.ModuleDict`(`docs.pytorch.org`) +- Stack Overflow:合并 `ModuleList` 的讨论 +- PyTorch Forums:`ModuleList` 和 `ModuleDict` 的动态操作 + +如果需要更详细的代码示例、特定方法的实现,或其他相关问题(如与优化器或设备迁移的集成),请告诉我! \ No newline at end of file diff --git a/Pytorch/nn/Parameter/List(Dict)AreUsedToStorePms b/Pytorch/nn/Parameter/List(Dict)AreUsedToStorePms new file mode 100644 index 0000000..e69de29 diff --git a/Pytorch/nn/Parameter/nn.Parameter.md b/Pytorch/nn/Parameter/nn.Parameter.md new file mode 100644 index 0000000..399dba2 --- /dev/null +++ b/Pytorch/nn/Parameter/nn.Parameter.md @@ -0,0 +1,225 @@ +根据 PyTorch 官方文档,`torch.nn.Parameter` 是一个类,继承自 `torch.Tensor`,主要用于表示神经网络模型中的可训练参数。它本身并没有定义许多独立的方法,而是继承了 `torch.Tensor` 的大部分方法,同时具备一些特殊属性,用于与 `torch.nn.Module` 配合管理模型参数。以下是对 `torch.nn.Parameter` 的详细讲解,包括其作用、特性以及与参数管理相关的方法,基于官方文档和其他可靠来源。 + +--- + +### 1. `torch.nn.Parameter` 的定义与作用 + +**官方定义**: +```python +class torch.nn.parameter.Parameter(data=None, requires_grad=True) +``` +- **作用**:`torch.nn.Parameter` 是一种特殊的 `torch.Tensor`,用于表示神经网络模型的可训练参数。当它被赋值给 `torch.nn.Module` 的属性时,会自动注册到模块的参数列表中(通过 `parameters()` 或 `named_parameters()` 方法访问),并参与梯度计算和优化。 +- **特性**: + - **自动注册**:当 `nn.Parameter` 实例被赋值给 `nn.Module` 的属性时,它会自动添加到模块的 `parameters()` 迭代器中,而普通 `torch.Tensor` 不会。 + - **默认梯度**:`requires_grad` 默认值为 `True`,表示参数需要计算梯度,即使在 `torch.no_grad()` 上下文中也是如此。 + - **用途**:常用于定义模型的可训练权重、偏置,或其他需要优化的参数(如 Vision Transformer 中的 positional embedding 或 class token)。 + +**参数说明**: +- `data`:一个 `torch.Tensor`,表示参数的初始值。 +- `requires_grad`:布尔值,指示是否需要计算梯度,默认 `True`。 + +**示例**: +```python +import torch +import torch.nn as nn + +# 创建一个 Parameter +param = nn.Parameter(torch.randn(3, 3)) +print(param) # 输出 Parameter 类型的张量,requires_grad=True + +# 定义一个简单的模型 +class MyModel(nn.Module): + def __init__(self): + super(MyModel, self).__init__() + self.weight = nn.Parameter(torch.randn(3, 3)) + + def forward(self, x): + return torch.matmul(x, self.weight) + +model = MyModel() +print(list(model.parameters())) # 包含 self.weight +``` + +--- + +### 2. `torch.nn.Parameter` 的方法 + +`torch.nn.Parameter` 本身没有定义额外的方法,它继承了 `torch.Tensor` 的所有方法,并通过与 `nn.Module` 的交互提供参数管理的功能。以下是与 `nn.Parameter` 相关的核心方法(主要通过 `nn.Module` 访问)以及 `torch.Tensor` 的常用方法在 `nn.Parameter` 上的应用: + +#### 2.1 通过 `nn.Module` 访问 `nn.Parameter` 的方法 + +这些方法是 `torch.nn.Module` 提供的,用于管理 `nn.Parameter` 实例: + +1. **`parameters()`**: + - **作用**:返回模型中所有 `nn.Parameter` 实例的迭代器。 + - **返回值**:`Iterator[Parameter]`,包含所有参数的张量。 + - **示例**: + ```python + for param in model.parameters(): + print(param.shape) # 打印每个参数的形状 + ``` + +2. **`named_parameters()`**: + - **作用**:返回一个迭代器,包含模型中所有 `nn.Parameter` 的名称和对应的参数张量。 + - **返回值**:`Iterator[Tuple[str, Parameter]]`,每个元素是参数名称和参数的元组。 + - **示例**: + ```python + for name, param in model.named_parameters(): + print(f"Parameter name: {name}, Shape: {param.shape}") + ``` + +3. **`_parameters`**: + - **作用**:`nn.Module` 的属性,是一个 `OrderedDict`,存储模块中直接定义的 `nn.Parameter` 实例。 + - **示例**: + ```python + print(model._parameters) # 输出 OrderedDict,包含 weight 参数 + ``` + +4. **`apply(fn)`**: + - **作用**:递归地将函数 `fn` 应用于模块及其子模块的所有参数,常用于参数初始化。 + - **示例**: + ```python + def init_weights(m): + if isinstance(m, nn.Linear): + m.weight.data.fill_(1.0) + model.apply(init_weights) # 初始化所有参数 + ``` + +5. **`cpu()` / `cuda(device_id=None)`**: + - **作用**:将所有参数(包括 `nn.Parameter`)移动到 CPU 或指定的 GPU 设备。 + - **示例**: + ```python + model.cuda() # 将模型参数移动到 GPU + ``` + +6. **`to(device)`**: + - **作用**:将参数移动到指定设备(CPU 或 GPU),支持更灵活的设备管理。 + - **示例**: + ```python + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + model.to(device) + ``` + +7. **`double()` / `float()` / `half()`**: + - **作用**:将所有参数转换为指定的数据类型(如双精度、单精度或半精度)。 + - **示例**: + ```python + model.double() # 转换为双精度 + ``` + +#### 2.2 继承自 `torch.Tensor` 的方法 + +`nn.Parameter` 是 `torch.Tensor` 的子类,因此可以使用 `torch.Tensor` 的所有方法。以下是一些常用的方法,特别适用于参数操作: + +1. **张量操作**: + - `add_()`, `mul_()`, `div_()` 等:原地修改参数值。 + - `zero_()`:将参数值置零,常用于重置梯度或参数。 + - **示例**: + ```python + param = nn.Parameter(torch.randn(3, 3)) + param.zero_() # 将参数置零 + ``` + +2. **梯度相关**: + - `grad`:访问参数的梯度(一个 `torch.Tensor`)。 + - `zero_grad()`:通过优化器调用,清除参数的梯度。 + - **示例**: + ```python + optimizer = torch.optim.SGD(model.parameters(), lr=0.01) + optimizer.zero_grad() # 清除所有参数的梯度 + ``` + +3. **形状操作**: + - `view()`, `reshape()`:改变参数的形状。 + - **示例**: + ```python + param = nn.Parameter(torch.randn(3, 3)) + reshaped_param = param.view(9) # 展平为 1D 张量 + ``` + +4. **数学运算**: + - `sum()`, `mean()`, `std()` 等:对参数值进行统计计算。 + - **示例**: + ```python + print(param.mean()) # 计算参数的均值 + ``` + +5. **克隆与分离**: + - `clone()`:创建参数的副本。 + - `detach()`:分离参数,创建一个不需要梯度的新张量。 + - **示例**: + ```python + param_clone = param.clone() # 复制参数 + param_detached = param.detach() # 分离,requires_grad=False + ``` + +#### 2.3 与优化器交互 + +`nn.Parameter` 的主要用途是与优化器(如 `torch.optim.SGD` 或 `Adam`)一起使用。优化器通过 `model.parameters()` 获取所有 `nn.Parameter` 实例,并更新它们的值。 + +**示例**: +```python +import torch.optim as optim + +model = MyModel() +optimizer = optim.SGD(model.parameters(), lr=0.01) +loss_fn = nn.MSELoss() + +# 前向传播 +x = torch.randn(1, 3) +y = torch.randn(1, 3) +out = model(x) +loss = loss_fn(out, y) + +# 反向传播与优化 +optimizer.zero_grad() +loss.backward() +optimizer.step() # 更新所有 nn.Parameter +``` + +--- + +### 3. 注意事项与常见问题 + +1. **与普通 Tensor 的区别**: + - 普通 `torch.Tensor` 即使设置 `requires_grad=True`,也不会自动添加到 `nn.Module` 的参数列表中。 + - `nn.Parameter` 默认 `requires_grad=True`,且会自动注册为模型参数。 + +2. **初始化参数**: + - 可以使用 `torch.nn.init` 模块初始化 `nn.Parameter`。 + - **示例**: + ```python + import torch.nn.init as init + param = nn.Parameter(torch.randn(3, 3)) + init.xavier_uniform_(param) # 使用 Xavier 初始化 + ``` + +3. **临时状态 vs 参数**: + - 如果需要在模型中存储临时状态(如 RNN 的隐藏状态),应使用普通 `torch.Tensor` 或 `nn.Module.register_buffer()`,避免注册为可训练参数。 + +4. **Vision Transformer 示例**: + - 在 Vision Transformer 中,`nn.Parameter` 常用于定义可学习的 `cls_token` 和 `pos_embedding`: + ```python + class ViT(nn.Module): + def __init__(self, num_patches, dim): + super(ViT, self).__init__() + self.cls_token = nn.Parameter(torch.randn(1, 1, dim)) + self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, dim)) + ``` + +--- + +### 4. 总结 + +`torch.nn.Parameter` 本身没有定义独特的方法,但通过继承 `torch.Tensor` 和与 `nn.Module` 的交互,提供了强大的参数管理功能。核心方法(如 `parameters()`、`named_parameters()`)通过 `nn.Module` 访问,而 `torch.Tensor` 的方法(如 `zero_()`、`view()`)直接应用于 `nn.Parameter` 实例。以下是关键点: + +- **自动注册**:赋值给 `nn.Module` 属性时,自动加入参数列表。 +- **梯度计算**:默认 `requires_grad=True`,支持优化。 +- **灵活操作**:继承 `torch.Tensor` 的所有方法,适用于张量操作。 + +**参考文献**: +- PyTorch 官方文档:`torch.nn.Parameter`[](https://docs.pytorch.org/docs/stable/generated/torch.nn.parameter.Parameter.html)[](https://docs.pytorch.ac.cn/docs/stable/generated/torch.nn.parameter.Parameter.html) +- 极客教程:理解 `torch.nn.Parameter`[](https://geek-docs.com/pytorch/pytorch-questions/21_pytorch_understanding_torchnnparameter.html) +- CSDN 博客:`torch.nn.Parameter` 讲解[](https://blog.csdn.net/weixin_44878336/article/details/124733598)[](https://blog.csdn.net/weixin_44966641/article/details/118730730) + +如果需要更详细的代码示例或特定方法的应用场景,请告诉我! \ No newline at end of file diff --git a/Pytorch/nn/Parameter/nn.ParameterDict.md b/Pytorch/nn/Parameter/nn.ParameterDict.md new file mode 100644 index 0000000..aa3722c --- /dev/null +++ b/Pytorch/nn/Parameter/nn.ParameterDict.md @@ -0,0 +1,359 @@ +根据 PyTorch 官方文档(`torch.nn.ParameterList` 和 `torch.nn.ParameterDict` 的相关内容),以下是对这两个类的详细讲解,包括它们的定义、作用以及所有方法的全面说明。由于 `torch.nn.ParameterList` 和 `torch.nn.ParameterDict` 是专门用于管理 `torch.nn.Parameter` 的容器类,它们的方法相对较少,主要继承自 Python 的列表和字典操作,并与 PyTorch 的模块机制结合使用。以下内容基于官方文档(`PyTorch 2.8`)和其他可靠来源(如 PyTorch Forums 和 Stack Overflow),确保准确且全面。 + +--- + +## 1. `torch.nn.ParameterList` + +### 1.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ParameterList(values=None) +``` +- **作用**:`torch.nn.ParameterList` 是一个容器类,用于以列表的形式存储 `torch.nn.Parameter` 实例。它类似于 Python 的内置 `list`,但专为 PyTorch 的参数管理设计,存储的 `nn.Parameter` 会被自动注册到 `nn.Module` 的参数列表中,参与梯度计算和优化。 +- **特性**: + - **自动注册**:当 `nn.ParameterList` 作为 `nn.Module` 的属性时,其中的所有 `nn.Parameter` 会自动被 `model.parameters()` 识别。 + - **Tensor 自动转换**:在构造、赋值、`append()` 或 `extend()` 时,传入的普通 `torch.Tensor` 会自动转换为 `nn.Parameter`。 + - **用途**:适用于需要动态管理一组参数的场景,例如在循环网络或变长模型中存储多个权重矩阵。 +- **参数**: + - `values`:一个可选的可迭代对象,包含初始的 `nn.Parameter` 或 `torch.Tensor`。 + +**示例**: +```python +import torch +import torch.nn as nn + +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.params = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(3)]) + + def forward(self, x): + for param in self.params: + x = x @ param # 矩阵乘法 + return x + +model = MyModel() +print(list(model.parameters())) # 输出 3 个 (2, 2) 的参数张量 +``` + +### 1.2 方法讲解 + +`torch.nn.ParameterList` 支持以下方法,主要继承自 Python 的 `list`,并添加了 PyTorch 的参数管理特性。以下是所有方法的详细说明(基于官方文档和实际用法): + +1. **`append(value)`**: + - **作用**:向 `ParameterList` 末尾添加一个值。如果 `value` 是 `torch.Tensor`,会自动转换为 `nn.Parameter`。 + - **参数**: + - `value`:要添加的元素(可以是 `nn.Parameter` 或 `torch.Tensor`)。 + - **返回值**:`self`(`ParameterList` 本身,支持链式调用)。 + - **示例**: + ```python + param_list = nn.ParameterList() + param_list.append(torch.randn(2, 2)) # 自动转换为 nn.Parameter + print(len(param_list)) # 输出 1 + print(isinstance(param_list[0], nn.Parameter)) # 输出 True + ``` + - **注意**:添加的 `nn.Parameter` 会自动注册到模块的参数列表中。 + +2. **`extend(values)`**: + - **作用**:将一个可迭代对象中的值追加到 `ParameterList` 末尾。所有 `torch.Tensor` 会被转换为 `nn.Parameter`。 + - **参数**: + - `values`:一个可迭代对象,包含 `nn.Parameter` 或 `torch.Tensor`。 + - **返回值**:`self`。 + - **示例**: + ```python + param_list = nn.ParameterList() + param_list.extend([torch.randn(2, 2), torch.randn(2, 2)]) + print(len(param_list)) # 输出 2 + ``` + - **注意**:`extend` 比逐个 `append` 更高效,适合批量添加参数。 + - **Stack Overflow 示例**:可以使用 `extend` 合并两个 `ParameterList`: + ```python + plist = nn.ParameterList() + plist.extend(sub_list_1) + plist.extend(sub_list_2) + ``` + 或者使用解包方式: + ```python + param_list = nn.ParameterList([*sub_list_1, *sub_list_2]) + ``` + +3. **索引操作(如 `__getitem__`, `__setitem__`)**: + - **作用**:支持像 Python 列表一样的索引访问和赋值操作。 + - **参数**: + - 索引(整数或切片)。 + - **返回值**:指定索引处的 `nn.Parameter`。 + - **示例**: + ```python + param_list = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(3)]) + print(param_list[0]) # 访问第一个参数 + param_list[0] = nn.Parameter(torch.ones(2, 2)) # 替换第一个参数 + ``` + - **注意**:赋值时,新值必须是 `nn.Parameter` 或 `torch.Tensor`(后者会自动转换为 `nn.Parameter`)。 + +4. **迭代操作(如 `__iter__`)**: + - **作用**:支持迭代,允许遍历 `ParameterList` 中的所有参数。 + - **返回值**:迭代器,逐个返回 `nn.Parameter`。 + - **示例**: + ```python + for param in param_list: + print(param.shape) # 打印每个参数的形状 + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ParameterList` 中参数的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(param_list)) # 输出参数数量 + ``` + +6. **其他列表操作**: + - `ParameterList` 支持 Python 列表的常见方法,如 `pop()`, `clear()`, `insert()`, `remove()` 等,但这些方法在官方文档中未明确列出(基于 Python 的 `list` 实现)。 + - **示例**(`pop`): + ```python + param_list = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(3)]) + removed_param = param_list.pop(0) # 移除并返回第一个参数 + print(len(param_list)) # 输出 2 + ``` + - **PyTorch Forums 讨论**:有用户询问如何在运行时移除 `ParameterList` 中的元素,可以使用 `pop(index)` 或重新构造列表: + ```python + param_list = nn.ParameterList(param_list[:index] + param_list[index+1:]) + ``` + +### 1.3 注意事项 + +- **与 `nn.ModuleList` 的区别**:`ParameterList` 存储 `nn.Parameter`,用于参数管理;`nn.ModuleList` 存储 `nn.Module`,用于子模块管理。 +- **自动转换**:任何添加到 `ParameterList` 的 `torch.Tensor` 都会被转换为 `nn.Parameter`,确保参数可被优化器识别。 +- **动态性**:`ParameterList` 适合动态模型(如变长序列模型),但操作频繁可能影响性能。 +- **优化器集成**:`ParameterList` 中的参数会自动被 `model.parameters()` 包含,优化器会更新这些参数。 + +--- + +## 2. `torch.nn.ParameterDict` + +### 2.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ParameterDict(parameters=None) +``` +- **作用**:`torch.nn.ParameterDict` 是一个容器类,用于以字典的形式存储 `torch.nn.Parameter` 实例。它类似于 Python 的内置 `dict`,但专为 PyTorch 参数管理设计,存储的 `nn.Parameter` 会自动注册到 `nn.Module` 的参数列表中。 +- **特性**: + - **键值存储**:使用字符串键来索引参数,便于按名称访问。 + - **自动注册**:与 `ParameterList` 类似,`ParameterDict` 中的参数会被 `model.parameters()` 识别。 + - **Tensor 自动转换**:赋值时,`torch.Tensor` 会被转换为 `nn.Parameter`。 + - **用途**:适用于需要按名称管理参数的场景,例如在多任务学习或复杂模型中。 +- **参数**: + - `parameters`:一个可选的可迭代对象,包含键值对(键为字符串,值为 `nn.Parameter` 或 `torch.Tensor`)。 + +**示例**: +```python +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.params = nn.ParameterDict({ + 'weight1': nn.Parameter(torch.randn(2, 2)), + 'weight2': nn.Parameter(torch.randn(2, 2)) + }) + + def forward(self, x): + x = x @ self.params['weight1'] + x = x @ self.params['weight2'] + return x + +model = MyModel() +print(list(model.parameters())) # 输出 2 个 (2, 2) 的参数张量 +``` + +### 2.2 方法讲解 + +`torch.nn.ParameterDict` 支持以下方法,主要继承自 Python 的 `dict`,并添加了 PyTorch 的参数管理特性。以下是所有方法的详细说明: + +1. **`__setitem__(key, value)`**: + - **作用**:向 `ParameterDict` 添加或更新一个键值对。如果 `value` 是 `torch.Tensor`,会自动转换为 `nn.Parameter`。 + - **参数**: + - `key`:字符串,参数的名称。 + - `value`:`nn.Parameter` 或 `torch.Tensor`。 + - **示例**: + ```python + param_dict = nn.ParameterDict() + param_dict['weight'] = torch.randn(2, 2) # 自动转换为 nn.Parameter + print(param_dict['weight']) # 输出 nn.Parameter + ``` + +2. **`update([other])`**: + - **作用**:使用另一个字典或键值对更新 `ParameterDict`。输入的 `torch.Tensor` 会被转换为 `nn.Parameter`。 + - **参数**: + - `other`:一个字典或键值对的可迭代对象。 + - **示例**: + ```python + param_dict = nn.ParameterDict() + param_dict.update({'weight1': torch.randn(2, 2), 'weight2': torch.randn(2, 2)}) + print(len(param_dict)) # 输出 2 + ``` + +3. **索引操作(如 `__getitem__`)**: + - **作用**:通过键访问 `ParameterDict` 中的 `nn.Parameter`。 + - **参数**: + - 键(字符串)。 + - **返回值**:对应的 `nn.Parameter`。 + - **示例**: + ```python + print(param_dict['weight1']) # 访问 weight1 参数 + ``` + +4. **迭代操作(如 `__iter__`, `keys()`, `values()`, `items()`)**: + - **作用**:支持迭代键、值或键值对。 + - **返回值**: + - `keys()`:返回所有键的迭代器。 + - `values()`:返回所有 `nn.Parameter` 的迭代器。 + - `items()`:返回键值对的迭代器。 + - **示例**: + ```python + for key, param in param_dict.items(): + print(f"Key: {key}, Shape: {param.shape}") + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ParameterDict` 中参数的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(param_dict)) # 输出参数数量 + ``` + +6. **其他字典操作**: + - `ParameterDict` 支持 Python 字典的常见方法,如 `pop(key)`, `clear()`, `popitem()`, `get(key, default=None)` 等。 + - **示例**(`pop`): + ```python + param_dict = nn.ParameterDict({'weight1': torch.randn(2, 2), 'weight2': torch.randn(2, 2)}) + removed_param = param_dict.pop('weight1') # 移除并返回 weight1 + print(len(param_dict)) # 输出 1 + ``` + +### 2.3 注意事项 + +- **与 `nn.ModuleDict` 的区别**:`ParameterDict` 存储 `nn.Parameter`,用于参数管理;`nn.ModuleDict` 存储 `nn.Module`,用于子模块管理。 +- **键的唯一性**:`ParameterDict` 的键必须是字符串,且不能重复。 +- **动态管理**:适合需要按名称访问参数的场景,但操作复杂模型时需注意性能开销。 +- **优化器集成**:`ParameterDict` 中的参数也会被 `model.parameters()` 包含,优化器会自动更新。 + +--- + +## 3. 比较与使用场景 + +| 特性 | `ParameterList` | `ParameterDict` | +|---------------------|--------------------------------------------|--------------------------------------------| +| **存储方式** | 列表(按索引访问) | 字典(按键访问) | +| **访问方式** | 索引(`param_list[0]`) | 键(`param_dict['key']`) | +| **主要方法** | `append`, `extend`, `pop`, 索引操作 | `update`, `pop`, `keys`, `values`, `items` | +| **适用场景** | 顺序参数管理(如循环网络中的多层权重) | 命名参数管理(如多任务模型中的权重) | +| **动态性** | 适合动态添加/移除参数 | 适合按名称管理参数 | + +**选择建议**: +- 如果参数需要按顺序访问或动态增减,使用 `ParameterList`。 +- 如果需要按名称管理参数或参数具有明确语义,使用 `ParameterDict`。 + +--- + +## 4. 综合示例 + +以下是一个结合 `ParameterList` 和 `ParameterDict` 的示例,展示它们在模型中的使用: + +```python +import torch +import torch.nn as nn + +class ComplexModel(nn.Module): + def __init__(self): + super().__init__() + # 使用 ParameterList 存储一组权重 + self.list_params = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(2)]) + # 使用 ParameterDict 存储命名参数 + self.dict_params = nn.ParameterDict({ + 'conv_weight': nn.Parameter(torch.randn(3, 3)), + 'fc_weight': nn.Parameter(torch.randn(4, 4)) + }) + + def forward(self, x): + # 使用 ParameterList + for param in self.list_params: + x = x @ param + # 使用 ParameterDict + x = x @ self.dict_params['conv_weight'] + x = x @ self.dict_params['fc_weight'] + return x + +model = ComplexModel() +optimizer = torch.optim.SGD(model.parameters(), lr=0.01) + +# 打印所有参数 +for name, param in model.named_parameters(): + print(f"Parameter name: {name}, Shape: {param.shape}") + +# 动态修改 ParameterList +model.list_params.append(nn.Parameter(torch.ones(2, 2))) + +# 动态修改 ParameterDict +model.dict_params['new_weight'] = nn.Parameter(torch.zeros(4, 4)) +``` + +--- + +## 5. 常见问题与解答 + +1. **如何高效合并两个 `ParameterList`?** + - 使用 `extend` 方法或解包方式: + ```python + param_list = nn.ParameterList() + param_list.extend(sub_list_1) + param_list.extend(sub_list_2) + # 或者 + param_list = nn.ParameterList([*sub_list_1, *sub_list_2]) + ``` + +2. **如何从 `ParameterList` 删除元素?** + - 使用 `pop(index)` 或重新构造列表: + ```python + param_list.pop(0) # 移除第一个参数 + # 或者 + param_list = nn.ParameterList([param for i, param in enumerate(param_list) if i != 0]) + ``` + +3. **如何检查 `ParameterDict` 中的参数?** + - 使用 `keys()`, `values()`, 或 `items()` 遍历: + ```python + for key, param in param_dict.items(): + print(f"Key: {key}, Parameter: {param}") + ``` + +4. **如何初始化参数?** + - 使用 `torch.nn.init` 或通过 `nn.Module.apply`: + ```python + import torch.nn.init as init + for param in param_list: + init.xavier_uniform_(param) + for param in param_dict.values(): + init.xavier_uniform_(param) + ``` + +--- + +## 6. 总结 + +- **`torch.nn.ParameterList`**: + - 方法:`append`, `extend`, `pop`, 索引/迭代操作。 + - 特点:类似列表,适合顺序管理参数,自动将 `torch.Tensor` 转换为 `nn.Parameter`。 + - 场景:动态模型、变长参数列表。 +- **`torch.nn.ParameterDict`**: + - 方法:`update`, `pop`, `keys`, `values`, `items`, 索引/迭代操作。 + - 特点:类似字典,适合按名称管理参数,自动转换 `torch.Tensor`。 + - 场景:多任务学习、需要语义化命名的模型。 + +**参考文献**: +- PyTorch 官方文档:`torch.nn.ParameterList` 和 `torch.nn.ParameterDict`(`docs.pytorch.org`)[](https://docs.pytorch.org/docs/stable/generated/torch.nn.ParameterList.html)[](https://docs.pytorch.org/docs/stable/nn.html) +- Stack Overflow:合并 `ParameterList` 的讨论[](https://stackoverflow.com/questions/70779631/combining-parameterlist-in-pytorch) +- PyTorch Forums:`ParameterList` 的使用和动态操作[](https://discuss.pytorch.org/t/using-nn-parameterlist/86742) + +如果需要更详细的代码示例、特定方法的实现,或其他相关问题(如与优化器的集成),请告诉我! \ No newline at end of file diff --git a/Pytorch/nn/Parameter/nn.ParameterList.md b/Pytorch/nn/Parameter/nn.ParameterList.md new file mode 100644 index 0000000..aa3722c --- /dev/null +++ b/Pytorch/nn/Parameter/nn.ParameterList.md @@ -0,0 +1,359 @@ +根据 PyTorch 官方文档(`torch.nn.ParameterList` 和 `torch.nn.ParameterDict` 的相关内容),以下是对这两个类的详细讲解,包括它们的定义、作用以及所有方法的全面说明。由于 `torch.nn.ParameterList` 和 `torch.nn.ParameterDict` 是专门用于管理 `torch.nn.Parameter` 的容器类,它们的方法相对较少,主要继承自 Python 的列表和字典操作,并与 PyTorch 的模块机制结合使用。以下内容基于官方文档(`PyTorch 2.8`)和其他可靠来源(如 PyTorch Forums 和 Stack Overflow),确保准确且全面。 + +--- + +## 1. `torch.nn.ParameterList` + +### 1.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ParameterList(values=None) +``` +- **作用**:`torch.nn.ParameterList` 是一个容器类,用于以列表的形式存储 `torch.nn.Parameter` 实例。它类似于 Python 的内置 `list`,但专为 PyTorch 的参数管理设计,存储的 `nn.Parameter` 会被自动注册到 `nn.Module` 的参数列表中,参与梯度计算和优化。 +- **特性**: + - **自动注册**:当 `nn.ParameterList` 作为 `nn.Module` 的属性时,其中的所有 `nn.Parameter` 会自动被 `model.parameters()` 识别。 + - **Tensor 自动转换**:在构造、赋值、`append()` 或 `extend()` 时,传入的普通 `torch.Tensor` 会自动转换为 `nn.Parameter`。 + - **用途**:适用于需要动态管理一组参数的场景,例如在循环网络或变长模型中存储多个权重矩阵。 +- **参数**: + - `values`:一个可选的可迭代对象,包含初始的 `nn.Parameter` 或 `torch.Tensor`。 + +**示例**: +```python +import torch +import torch.nn as nn + +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.params = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(3)]) + + def forward(self, x): + for param in self.params: + x = x @ param # 矩阵乘法 + return x + +model = MyModel() +print(list(model.parameters())) # 输出 3 个 (2, 2) 的参数张量 +``` + +### 1.2 方法讲解 + +`torch.nn.ParameterList` 支持以下方法,主要继承自 Python 的 `list`,并添加了 PyTorch 的参数管理特性。以下是所有方法的详细说明(基于官方文档和实际用法): + +1. **`append(value)`**: + - **作用**:向 `ParameterList` 末尾添加一个值。如果 `value` 是 `torch.Tensor`,会自动转换为 `nn.Parameter`。 + - **参数**: + - `value`:要添加的元素(可以是 `nn.Parameter` 或 `torch.Tensor`)。 + - **返回值**:`self`(`ParameterList` 本身,支持链式调用)。 + - **示例**: + ```python + param_list = nn.ParameterList() + param_list.append(torch.randn(2, 2)) # 自动转换为 nn.Parameter + print(len(param_list)) # 输出 1 + print(isinstance(param_list[0], nn.Parameter)) # 输出 True + ``` + - **注意**:添加的 `nn.Parameter` 会自动注册到模块的参数列表中。 + +2. **`extend(values)`**: + - **作用**:将一个可迭代对象中的值追加到 `ParameterList` 末尾。所有 `torch.Tensor` 会被转换为 `nn.Parameter`。 + - **参数**: + - `values`:一个可迭代对象,包含 `nn.Parameter` 或 `torch.Tensor`。 + - **返回值**:`self`。 + - **示例**: + ```python + param_list = nn.ParameterList() + param_list.extend([torch.randn(2, 2), torch.randn(2, 2)]) + print(len(param_list)) # 输出 2 + ``` + - **注意**:`extend` 比逐个 `append` 更高效,适合批量添加参数。 + - **Stack Overflow 示例**:可以使用 `extend` 合并两个 `ParameterList`: + ```python + plist = nn.ParameterList() + plist.extend(sub_list_1) + plist.extend(sub_list_2) + ``` + 或者使用解包方式: + ```python + param_list = nn.ParameterList([*sub_list_1, *sub_list_2]) + ``` + +3. **索引操作(如 `__getitem__`, `__setitem__`)**: + - **作用**:支持像 Python 列表一样的索引访问和赋值操作。 + - **参数**: + - 索引(整数或切片)。 + - **返回值**:指定索引处的 `nn.Parameter`。 + - **示例**: + ```python + param_list = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(3)]) + print(param_list[0]) # 访问第一个参数 + param_list[0] = nn.Parameter(torch.ones(2, 2)) # 替换第一个参数 + ``` + - **注意**:赋值时,新值必须是 `nn.Parameter` 或 `torch.Tensor`(后者会自动转换为 `nn.Parameter`)。 + +4. **迭代操作(如 `__iter__`)**: + - **作用**:支持迭代,允许遍历 `ParameterList` 中的所有参数。 + - **返回值**:迭代器,逐个返回 `nn.Parameter`。 + - **示例**: + ```python + for param in param_list: + print(param.shape) # 打印每个参数的形状 + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ParameterList` 中参数的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(param_list)) # 输出参数数量 + ``` + +6. **其他列表操作**: + - `ParameterList` 支持 Python 列表的常见方法,如 `pop()`, `clear()`, `insert()`, `remove()` 等,但这些方法在官方文档中未明确列出(基于 Python 的 `list` 实现)。 + - **示例**(`pop`): + ```python + param_list = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(3)]) + removed_param = param_list.pop(0) # 移除并返回第一个参数 + print(len(param_list)) # 输出 2 + ``` + - **PyTorch Forums 讨论**:有用户询问如何在运行时移除 `ParameterList` 中的元素,可以使用 `pop(index)` 或重新构造列表: + ```python + param_list = nn.ParameterList(param_list[:index] + param_list[index+1:]) + ``` + +### 1.3 注意事项 + +- **与 `nn.ModuleList` 的区别**:`ParameterList` 存储 `nn.Parameter`,用于参数管理;`nn.ModuleList` 存储 `nn.Module`,用于子模块管理。 +- **自动转换**:任何添加到 `ParameterList` 的 `torch.Tensor` 都会被转换为 `nn.Parameter`,确保参数可被优化器识别。 +- **动态性**:`ParameterList` 适合动态模型(如变长序列模型),但操作频繁可能影响性能。 +- **优化器集成**:`ParameterList` 中的参数会自动被 `model.parameters()` 包含,优化器会更新这些参数。 + +--- + +## 2. `torch.nn.ParameterDict` + +### 2.1 定义与作用 + +**官方定义**: +```python +class torch.nn.ParameterDict(parameters=None) +``` +- **作用**:`torch.nn.ParameterDict` 是一个容器类,用于以字典的形式存储 `torch.nn.Parameter` 实例。它类似于 Python 的内置 `dict`,但专为 PyTorch 参数管理设计,存储的 `nn.Parameter` 会自动注册到 `nn.Module` 的参数列表中。 +- **特性**: + - **键值存储**:使用字符串键来索引参数,便于按名称访问。 + - **自动注册**:与 `ParameterList` 类似,`ParameterDict` 中的参数会被 `model.parameters()` 识别。 + - **Tensor 自动转换**:赋值时,`torch.Tensor` 会被转换为 `nn.Parameter`。 + - **用途**:适用于需要按名称管理参数的场景,例如在多任务学习或复杂模型中。 +- **参数**: + - `parameters`:一个可选的可迭代对象,包含键值对(键为字符串,值为 `nn.Parameter` 或 `torch.Tensor`)。 + +**示例**: +```python +class MyModel(nn.Module): + def __init__(self): + super().__init__() + self.params = nn.ParameterDict({ + 'weight1': nn.Parameter(torch.randn(2, 2)), + 'weight2': nn.Parameter(torch.randn(2, 2)) + }) + + def forward(self, x): + x = x @ self.params['weight1'] + x = x @ self.params['weight2'] + return x + +model = MyModel() +print(list(model.parameters())) # 输出 2 个 (2, 2) 的参数张量 +``` + +### 2.2 方法讲解 + +`torch.nn.ParameterDict` 支持以下方法,主要继承自 Python 的 `dict`,并添加了 PyTorch 的参数管理特性。以下是所有方法的详细说明: + +1. **`__setitem__(key, value)`**: + - **作用**:向 `ParameterDict` 添加或更新一个键值对。如果 `value` 是 `torch.Tensor`,会自动转换为 `nn.Parameter`。 + - **参数**: + - `key`:字符串,参数的名称。 + - `value`:`nn.Parameter` 或 `torch.Tensor`。 + - **示例**: + ```python + param_dict = nn.ParameterDict() + param_dict['weight'] = torch.randn(2, 2) # 自动转换为 nn.Parameter + print(param_dict['weight']) # 输出 nn.Parameter + ``` + +2. **`update([other])`**: + - **作用**:使用另一个字典或键值对更新 `ParameterDict`。输入的 `torch.Tensor` 会被转换为 `nn.Parameter`。 + - **参数**: + - `other`:一个字典或键值对的可迭代对象。 + - **示例**: + ```python + param_dict = nn.ParameterDict() + param_dict.update({'weight1': torch.randn(2, 2), 'weight2': torch.randn(2, 2)}) + print(len(param_dict)) # 输出 2 + ``` + +3. **索引操作(如 `__getitem__`)**: + - **作用**:通过键访问 `ParameterDict` 中的 `nn.Parameter`。 + - **参数**: + - 键(字符串)。 + - **返回值**:对应的 `nn.Parameter`。 + - **示例**: + ```python + print(param_dict['weight1']) # 访问 weight1 参数 + ``` + +4. **迭代操作(如 `__iter__`, `keys()`, `values()`, `items()`)**: + - **作用**:支持迭代键、值或键值对。 + - **返回值**: + - `keys()`:返回所有键的迭代器。 + - `values()`:返回所有 `nn.Parameter` 的迭代器。 + - `items()`:返回键值对的迭代器。 + - **示例**: + ```python + for key, param in param_dict.items(): + print(f"Key: {key}, Shape: {param.shape}") + ``` + +5. **长度查询(如 `__len__`)**: + - **作用**:返回 `ParameterDict` 中参数的数量。 + - **返回值**:整数。 + - **示例**: + ```python + print(len(param_dict)) # 输出参数数量 + ``` + +6. **其他字典操作**: + - `ParameterDict` 支持 Python 字典的常见方法,如 `pop(key)`, `clear()`, `popitem()`, `get(key, default=None)` 等。 + - **示例**(`pop`): + ```python + param_dict = nn.ParameterDict({'weight1': torch.randn(2, 2), 'weight2': torch.randn(2, 2)}) + removed_param = param_dict.pop('weight1') # 移除并返回 weight1 + print(len(param_dict)) # 输出 1 + ``` + +### 2.3 注意事项 + +- **与 `nn.ModuleDict` 的区别**:`ParameterDict` 存储 `nn.Parameter`,用于参数管理;`nn.ModuleDict` 存储 `nn.Module`,用于子模块管理。 +- **键的唯一性**:`ParameterDict` 的键必须是字符串,且不能重复。 +- **动态管理**:适合需要按名称访问参数的场景,但操作复杂模型时需注意性能开销。 +- **优化器集成**:`ParameterDict` 中的参数也会被 `model.parameters()` 包含,优化器会自动更新。 + +--- + +## 3. 比较与使用场景 + +| 特性 | `ParameterList` | `ParameterDict` | +|---------------------|--------------------------------------------|--------------------------------------------| +| **存储方式** | 列表(按索引访问) | 字典(按键访问) | +| **访问方式** | 索引(`param_list[0]`) | 键(`param_dict['key']`) | +| **主要方法** | `append`, `extend`, `pop`, 索引操作 | `update`, `pop`, `keys`, `values`, `items` | +| **适用场景** | 顺序参数管理(如循环网络中的多层权重) | 命名参数管理(如多任务模型中的权重) | +| **动态性** | 适合动态添加/移除参数 | 适合按名称管理参数 | + +**选择建议**: +- 如果参数需要按顺序访问或动态增减,使用 `ParameterList`。 +- 如果需要按名称管理参数或参数具有明确语义,使用 `ParameterDict`。 + +--- + +## 4. 综合示例 + +以下是一个结合 `ParameterList` 和 `ParameterDict` 的示例,展示它们在模型中的使用: + +```python +import torch +import torch.nn as nn + +class ComplexModel(nn.Module): + def __init__(self): + super().__init__() + # 使用 ParameterList 存储一组权重 + self.list_params = nn.ParameterList([nn.Parameter(torch.randn(2, 2)) for _ in range(2)]) + # 使用 ParameterDict 存储命名参数 + self.dict_params = nn.ParameterDict({ + 'conv_weight': nn.Parameter(torch.randn(3, 3)), + 'fc_weight': nn.Parameter(torch.randn(4, 4)) + }) + + def forward(self, x): + # 使用 ParameterList + for param in self.list_params: + x = x @ param + # 使用 ParameterDict + x = x @ self.dict_params['conv_weight'] + x = x @ self.dict_params['fc_weight'] + return x + +model = ComplexModel() +optimizer = torch.optim.SGD(model.parameters(), lr=0.01) + +# 打印所有参数 +for name, param in model.named_parameters(): + print(f"Parameter name: {name}, Shape: {param.shape}") + +# 动态修改 ParameterList +model.list_params.append(nn.Parameter(torch.ones(2, 2))) + +# 动态修改 ParameterDict +model.dict_params['new_weight'] = nn.Parameter(torch.zeros(4, 4)) +``` + +--- + +## 5. 常见问题与解答 + +1. **如何高效合并两个 `ParameterList`?** + - 使用 `extend` 方法或解包方式: + ```python + param_list = nn.ParameterList() + param_list.extend(sub_list_1) + param_list.extend(sub_list_2) + # 或者 + param_list = nn.ParameterList([*sub_list_1, *sub_list_2]) + ``` + +2. **如何从 `ParameterList` 删除元素?** + - 使用 `pop(index)` 或重新构造列表: + ```python + param_list.pop(0) # 移除第一个参数 + # 或者 + param_list = nn.ParameterList([param for i, param in enumerate(param_list) if i != 0]) + ``` + +3. **如何检查 `ParameterDict` 中的参数?** + - 使用 `keys()`, `values()`, 或 `items()` 遍历: + ```python + for key, param in param_dict.items(): + print(f"Key: {key}, Parameter: {param}") + ``` + +4. **如何初始化参数?** + - 使用 `torch.nn.init` 或通过 `nn.Module.apply`: + ```python + import torch.nn.init as init + for param in param_list: + init.xavier_uniform_(param) + for param in param_dict.values(): + init.xavier_uniform_(param) + ``` + +--- + +## 6. 总结 + +- **`torch.nn.ParameterList`**: + - 方法:`append`, `extend`, `pop`, 索引/迭代操作。 + - 特点:类似列表,适合顺序管理参数,自动将 `torch.Tensor` 转换为 `nn.Parameter`。 + - 场景:动态模型、变长参数列表。 +- **`torch.nn.ParameterDict`**: + - 方法:`update`, `pop`, `keys`, `values`, `items`, 索引/迭代操作。 + - 特点:类似字典,适合按名称管理参数,自动转换 `torch.Tensor`。 + - 场景:多任务学习、需要语义化命名的模型。 + +**参考文献**: +- PyTorch 官方文档:`torch.nn.ParameterList` 和 `torch.nn.ParameterDict`(`docs.pytorch.org`)[](https://docs.pytorch.org/docs/stable/generated/torch.nn.ParameterList.html)[](https://docs.pytorch.org/docs/stable/nn.html) +- Stack Overflow:合并 `ParameterList` 的讨论[](https://stackoverflow.com/questions/70779631/combining-parameterlist-in-pytorch) +- PyTorch Forums:`ParameterList` 的使用和动态操作[](https://discuss.pytorch.org/t/using-nn-parameterlist/86742) + +如果需要更详细的代码示例、特定方法的实现,或其他相关问题(如与优化器的集成),请告诉我! \ No newline at end of file diff --git a/Pytorch/nn/nn.Sequential.md b/Pytorch/nn/Sequential/nn.Sequential.md similarity index 100% rename from Pytorch/nn/nn.Sequential.md rename to Pytorch/nn/Sequential/nn.Sequential.md diff --git a/Pytorch/nn/viFunc/DirectlyUse-nn.func b/Pytorch/nn/viFunc/DirectlyUse-nn.func new file mode 100644 index 0000000..e69de29 diff --git a/Pytorch/nn/viFunc/nn.Conv2d.md b/Pytorch/nn/viFunc/nn.Conv2d.md new file mode 100644 index 0000000..e0054c4 --- /dev/null +++ b/Pytorch/nn/viFunc/nn.Conv2d.md @@ -0,0 +1,161 @@ +### `torch.nn.Conv2d` 类的方法详解 + +根据 PyTorch 官方文档(`torch.nn.Conv2d`),这是一个实现二维卷积的模块,广泛用于处理图像数据,执行卷积操作 \( y = W * x + b \),其中 \( * \) 表示卷积操作,\( W \) 是卷积核(权重),\( b \) 是偏置(如果启用)。该类继承自 `nn.Module`,因此除了特定方法外,还支持 `nn.Module` 的通用方法(如 `train()`、`eval()` 等)。文档中明确提到了一些方法,主要包括 `__init__`、`forward` 和 `extra_repr`,此外还涉及权重初始化和一些内部方法(如 `_conv_forward`)。以下详细讲解所有相关方法,基于官方文档和实现逻辑。 + +以下是每个方法的签名、参数、返回值和详细解释。参数类型基于 Python 标准类型和 PyTorch 张量规范。 + +--- + +#### 1. `__init__` 方法(初始化方法) +- **签名**: + ```python + torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None) + ``` +- **参数**: + - `in_channels`(int):输入张量的通道数(如 RGB 图像为 3)。 + - `out_channels`(int):输出张量的通道数(卷积核数量)。 + - `kernel_size`(int 或 tuple):卷积核大小,单个数(如 3 表示 3x3)或元组(如 (3, 3))。 + - `stride`(int 或 tuple,默认 1):卷积步幅,控制卷积核移动的步长。 + - `padding`(int、tuple 或 str,默认 0):输入的填充量,可为单个数、元组或字符串(如 'valid' 或 'same',但 'same' 需手动计算)。 + - `dilation`(int 或 tuple,默认 1):卷积核元素间距(膨胀卷积),用于增大感受野。 + - `groups`(int,默认 1):分组卷积设置,控制输入和输出通道的分组连接。 + - `bias`(bool,默认 True):是否添加可学习的偏置。 + - `padding_mode`(str,默认 'zeros'):填充模式,支持 'zeros'、'reflect'、'replicate' 或 'circular'。 + - `device`(torch.device 或 None,默认 None):模块的设备(CPU 或 GPU)。 + - `dtype`(torch.dtype 或 None,默认 None):模块的数据类型。 +- **返回值**:无(构造函数,初始化模块)。 +- **解释**: + 初始化二维卷积层,创建权重张量(形状为 `(out_channels, in_channels/groups, kernel_height, kernel_width)`)和可选的偏置张量(形状为 `(out_channels,)`)。权重使用均匀分布 \(\mathcal{U}(-\sqrt{k}, \sqrt{k})\) 初始化,其中 \( k = \frac{\text{groups}}{\text{in_channels} \cdot \prod \text{kernel_size}} \)。该方法定义了卷积操作的参数,是构建 CNN 的核心。例如,`nn.Conv2d(3, 64, 3)` 创建一个从 3 通道输入到 64 通道输出的 3x3 卷积层。 +- **注意**: + - 分组卷积(`groups > 1`)将输入和输出通道分组,降低计算量。 + - `padding_mode` 影响边界处理,'zeros' 是最常用的。 + - 支持 TensorFloat32 加速(在支持的硬件上),float16 输入可能在某些设备上转为 float32。 + +--- + +#### 2. `forward` 方法(前向传播方法) +- **签名**: + ```python + forward(input) + ``` +- **参数**: + - `input`(torch.Tensor):输入张量,形状为 `(N, C_in, H_in, W_in)`,其中 \( N \) 是批量大小,\( C_in \) 是输入通道数,\( H_in, W_in \) 是输入的高度和宽度。 +- **返回值**: + torch.Tensor,形状为 `(N, C_out, H_out, W_out)`,其中 \( C_out = \text{out_channels} \),输出尺寸 \( H_out, W_out \) 由公式计算: + \[ + H_out = \left\lfloor \frac{H_in + 2 \cdot \text{padding}[0] - \text{dilation}[0] \cdot (\text{kernel_size}[0] - 1) - 1}{\text{stride}[0]} \right\rfloor + 1 + \] + \[ + W_out = \left\lfloor \frac{W_in + 2 \cdot \text{padding}[1] - \text{dilation}[1] \cdot (\text{kernel_size}[1] - 1) - 1}{\text{stride}[1]} \right\rfloor + 1 + \] +- **解释**: + 执行二维卷积操作,对输入张量应用卷积核和偏置(如果启用)。内部调用 F.conv2d(PyTorch 的函数式卷积接口),结合权重、偏置和初始化时指定的参数(如步幅、填充等)。这是模型前向传播的核心,隐式调用如 `output = layer(input)`。 + **示例**(来自文档): + ```python + import torch + import torch.nn as nn + m = nn.Conv2d(16, 33, 3, stride=2) # 16 通道输入,33 通道输出,3x3 核,步幅 2 + input = torch.randn(20, 16, 50, 100) # 批量 20,16 通道,50x100 尺寸 + output = m(input) # 输出形状: (20, 33, 24, 49)(根据公式计算) + ``` +- **注意**: + 输入的通道数必须等于 `in_channels`,否则会报错。输出尺寸由卷积参数决定,需仔细检查以避免维度不匹配。 + +--- + +#### 3. `extra_repr` 方法(额外字符串表示方法) +- **签名**: + ```python + extra_repr() + ``` +- **参数**:无。 +- **返回值**:str,描述模块参数的字符串。 +- **解释**: + 返回一个字符串,表示模块的关键参数,用于增强模块的打印表示。例如,打印 `Conv2d` 层时会显示类似: + ```python + Conv2d(16, 33, kernel_size=(3, 3), stride=(2, 2), padding=(0, 0), bias=True) + ``` + 包括 `in_channels`、`out_channels`、`kernel_size`、`stride`、`padding` 等信息。用于调试和模型结构可视化,继承自 `nn.Module` 并在 `Conv2d` 中覆盖以显示特定参数。 +- **注意**:此方法不影响计算,仅用于信息展示。 + +--- + +#### 4. `_conv_forward` 方法(内部前向传播方法) +- **签名**(推测,文档未明确列出签名): + ```python + _conv_forward(input, weight, bias) + ``` +- **参数**: + - `input`(torch.Tensor):输入张量,形状同 `forward` 的输入。 + - `weight`(torch.Tensor):卷积核权重,形状为 `(out_channels, in_channels/groups, kernel_height, kernel_width)`。 + - `bias`(torch.Tensor 或 None):偏置张量,形状为 `(out_channels,)` 或 None(若 `bias=False`)。 +- **返回值**: + torch.Tensor,卷积操作的结果,形状同 `forward` 的输出。 +- **解释**: + 这是 `forward` 方法的内部实现,调用 `torch.nn.functional.conv2d` 执行实际的卷积计算。参数包括输入、权重、偏置,以及初始化时设置的 `stride`、`padding`、`dilation`、`groups` 和 `padding_mode`。文档中未直接列出此方法为公共接口,但它是 `forward` 的核心逻辑,公开在实现中以支持自定义扩展。 +- **注意**: + 通常用户无需直接调用此方法,除非需要自定义卷积逻辑(如修改权重或偏置的处理方式)。 + +--- + +#### 5. `reset_parameters` 方法(重置参数方法) +- **签名**: + ```python + reset_parameters() + ``` +- **参数**:无。 +- **返回值**:无。 +- **解释**: + 重置模块的权重和偏置(如果启用)。权重使用均匀分布 \(\mathcal{U}(-\sqrt{k}, \sqrt{k})\) 初始化,其中 \( k = \frac{\text{groups}}{\text{in_channels} \cdot \prod \text{kernel_size}} \)。偏置(若存在)也使用相同分布初始化。此方法在需要重新初始化模型参数时调用,例如在训练实验中重置网络。 +- **注意**: + 调用此方法会覆盖现有参数,需谨慎使用。 + +--- + +### 附加说明 +- **继承方法**: + 作为 `nn.Module` 的子类,`Conv2d` 支持所有通用方法,例如: + - `parameters()`:返回可训练参数(权重和偏置)。 + - `named_parameters()`:返回带名称的参数。 + - `zero_grad()`:清零梯度。 + - `to(device)`:移动模块到指定设备。 + 这些方法非 `Conv2d` 独有,但常用于模型训练和调试。 +- **属性**: + - `weight`(nn.Parameter):卷积核权重张量。 + - `bias`(nn.Parameter 或 None):偏置张量(若 `bias=True`)。 + - 其他属性(如 `stride`、`padding`)存储初始化时的参数。 +- **使用提示**: + - 输入张量必须是 4D(批量、通道、高、宽),否则会报错。 + - 输出尺寸需根据公式计算,调试时可用 `torch.nn.functional.conv2d` 的文档验证。 + - 分组卷积和膨胀卷积是高级特性,需理解其对计算量和感受野的影响。 + - `padding_mode` 影响边界处理,'circular' 等模式在特定任务(如周期性数据)中有用。 +- **版本相关**: + 文档未提及特定版本差异,但 PyTorch 2.x 系列优化了卷积性能(如 TensorFloat32 支持)。float16 在某些设备(如 ROCm)上会转为 float32 计算。 + +--- + +### 示例代码(综合应用) +```python +import torch +import torch.nn as nn + +# 初始化 Conv2d 层 +conv = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1, bias=True) + +# 创建输入张量 (批量=1, 通道=3, 高=32, 宽=32) +input = torch.randn(1, 3, 32, 32) + +# 前向传播 +output = conv(input) +print(output.shape) # 输出: torch.Size([1, 64, 32, 32])(因 padding=1 保持尺寸) + +# 查看模块信息 +print(conv) # 调用 extra_repr,显示参数 + +# 重置参数 +conv.reset_parameters() +``` + +--- + +如果需要更详细的数学推导、特定参数组合的示例,或其他 `nn.Module` 方法的讲解,请告诉我! \ No newline at end of file diff --git a/Pytorch/nn/viFunc/nn.Linear.md b/Pytorch/nn/viFunc/nn.Linear.md new file mode 100644 index 0000000..69f9d7f --- /dev/null +++ b/Pytorch/nn/viFunc/nn.Linear.md @@ -0,0 +1,47 @@ +### torch.nn.Linear 类的方法详解 + +根据 PyTorch 官方文档(torch.nn.Linear),这是一个实现线性变换(全连接层)的模块,数学公式为 \( y = xA^T + b \),其中 \( A \) 是权重矩阵,\( b \) 是偏置(如果启用)。该类继承自 `nn.Module`,因此除了特定方法外,还支持 `nn.Module` 的通用方法(如 `train()`、`eval()` 等),但这里重点讲解文档中明确提到的所有方法,包括 `__init__`、`forward` 和 `extra_repr`。文档中未提及其他特定方法。 + +以下是每个方法的详细讲解,包括方法签名、参数、返回值和解释。参数类型基于 Python 标准类型和 PyTorch 张量规范。 + +#### 1. `__init__` 方法(初始化方法) +- **签名**:`torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None)` +- **参数**: + - `in_features`(int):每个输入样本的大小(输入特征维度)。 + - `out_features`(int):每个输出样本的大小(输出特征维度)。 + - `bias`(bool,默认 True):如果为 `False`,则不学习可加偏置项。 + - `device`(torch.device 或 None,默认 None):指定模块的设备(如 CPU 或 GPU)。 + - `dtype`(torch.dtype 或 None,默认 None):指定模块的数据类型。 +- **返回值**:无(这是构造函数,用于初始化模块)。 +- **解释**:该方法初始化线性变换模块。它会创建权重矩阵 \( A \)(形状为 `(out_features, in_features)`)和可选的偏置 \( b \)(形状为 `(out_features,)`)。权重和偏置使用均匀分布 \(\mathcal{U}(-\sqrt{k}, \sqrt{k})\) 初始化,其中 \( k = \frac{1}{\text{in_features}} \)。这是一个核心方法,用于构建层,例如 `nn.Linear(20, 30)` 创建一个从 20 维输入到 30 维输出的层。 +- **注意**:模块支持 TensorFloat32(在支持的硬件上加速),并且在某些 ROCm 设备上,float16 输入会转换为 float32 进行计算。 + +#### 2. `forward` 方法(前向传播方法) +- **签名**:`forward(input)`(输入参数名为 `input`,但文档中未显式列出签名,通常推断自描述)。 +- **参数**: + - `input`(torch.Tensor):输入张量,形状为 `(*, H_in)`,其中 `*` 表示任意数量的维度(包括无维度),`H_in = in_features`(最后一个维度必须匹配 `in_features`)。 +- **返回值**:torch.Tensor,形状为 `(*, H_out)`,其中前面的维度与输入相同,`H_out = out_features`。 +- **解释**:这是模块的核心前向传播方法。它对输入应用线性变换 \( y = xA^T + b \)(如果 `bias=True`)。权重 \( A \) 和偏置 \( b \) 是可学习的参数,通过反向传播更新。该方法是 PyTorch 模块的标准接口,在模型构建中调用如 `output = layer(input)` 时隐式执行。 +- **示例**(来自官方文档): + ```python + import torch.nn as nn + m = nn.Linear(20, 30) # 初始化层 + input = torch.randn(128, 20) # 批量大小 128,特征 20 + output = m(input) # 前向传播 + print(output.size()) # 输出: torch.Size([128, 30]) + ``` + 这展示了批量输入如何转换为输出形状。 + +#### 3. `extra_repr` 方法(额外字符串表示方法) +- **签名**:`extra_repr()`(无参数,继承自 `nn.Module`)。 +- **参数**:无。 +- **返回值**:str,一个字符串,总结模块的参数。 +- **解释**:该方法返回一个字符串,用于增强模块的打印表示(例如,当你 `print(layer)` 时)。它通常包括 `in_features`、`out_features` 和偏置是否启用(如 "Linear(in_features=20, out_features=30, bias=True)")。这是一个辅助方法,帮助调试和可视化模型结构,不是计算核心。 +- **注意**:这是 `nn.Module` 的标准方法,在 `Linear` 中被覆盖以包含特定参数。没有额外示例,但打印模块时会自动调用。 + +### 附加说明 +- **继承方法**:`torch.nn.Linear` 继承自 `nn.Module`,因此支持所有 `nn.Module` 方法,如 `parameters()`(获取可训练参数)、`named_parameters()`(命名参数迭代)、`zero_grad()`(梯度清零)等。这些不是 `Linear` 特有,而是通用方法。如果需要讲解整个 `nn.Module`,可以进一步查询。 +- **属性**:模块有 `weight`(权重张量)和 `bias`(偏置张量,如果启用),这些是 `nn.Parameter` 类型,可通过优化器更新。 +- **使用提示**:在构建神经网络时,`Linear` 常用于 MLP 等。确保输入的最后一个维度匹配 `in_features`,否则会报错。文档强调该模块在 float16 输入时的特殊行为(在 ROCm 上转换为 float32)以避免精度问题。 + +如果需要代码示例、数学推导或特定版本的差异,请提供更多细节! \ No newline at end of file diff --git a/Pytorch/nn/viFunc/readme.md b/Pytorch/nn/viFunc/readme.md new file mode 100644 index 0000000..0b05ccc --- /dev/null +++ b/Pytorch/nn/viFunc/readme.md @@ -0,0 +1,101 @@ +好的 👍 +`torch.nn` 里面确实包含了很多常用的神经网络模块,你可以把它们理解为深度学习中各种“积木”,主要分为 **层(layers)**、**容器(containers)** 和 **正则化/损失函数** 等几个类别。 + +下面我给你整理一份 **值得学习的网络层/模块清单**(重点是 `nn` 里面和建模相关的): + +--- + +### 🔹 1. 基础层(Linear & Embedding) + +* `nn.Linear` —— 全连接层(MLP 基础积木) +* `nn.Bilinear` —— 双线性层 +* `nn.Embedding` —— 词嵌入层 +* `nn.EmbeddingBag` —— 变体,适合处理词袋模型 + +--- + +### 🔹 2. 卷积层(Convolution Layers) + +* `nn.Conv1d` —— 一维卷积(常用于 NLP、语音) +* `nn.Conv2d` —— 二维卷积(图像处理最常用) +* `nn.Conv3d` —— 三维卷积(视频、体数据) +* `nn.ConvTranspose1d/2d/3d` —— 反卷积(上采样/生成模型常用) + +--- + +### 🔹 3. 池化层(Pooling) + +* `nn.MaxPool1d/2d/3d` —— 最大池化 +* `nn.AvgPool1d/2d/3d` —— 平均池化 +* `nn.AdaptiveMaxPool1d/2d/3d` —— 自适应池化(固定输出大小) +* `nn.AdaptiveAvgPool1d/2d/3d` —— 自适应平均池化 + +--- + +### 🔹 4. 循环神经网络层(RNN 系列) + +* `nn.RNN` —— 基础循环网络 +* `nn.LSTM` —— 长短期记忆网络 +* `nn.GRU` —— 门控循环单元 + +--- + +### 🔹 5. Transformer 相关 + +* `nn.MultiheadAttention` —— 多头注意力机制 +* `nn.Transformer` —— 整个 Transformer 模型(包含编码器+解码器) +* `nn.TransformerEncoder` / `nn.TransformerDecoder` +* `nn.TransformerEncoderLayer` / `nn.TransformerDecoderLayer` + +--- + +### 🔹 6. 归一化(Normalization) + +* `nn.BatchNorm1d/2d/3d` —— 批量归一化 +* `nn.LayerNorm` —— 层归一化(Transformer 常用) +* `nn.GroupNorm` —— 分组归一化 +* `nn.InstanceNorm1d/2d/3d` —— 实例归一化(风格迁移常用) +* `nn.LocalResponseNorm` —— 局部响应归一化(早期 CNN) + +--- + +### 🔹 7. Dropout & 正则化 + +* `nn.Dropout` —— 全连接层 Dropout +* `nn.Dropout2d/3d` —— 用于卷积层的 Dropout +* `nn.AlphaDropout` —— 用于 SELU 激活的变体 + +--- + +### 🔹 8. 激活函数(很多都在 `torch.nn.functional`,但也有类) + +* `nn.ReLU`, `nn.LeakyReLU`, `nn.PReLU`, `nn.RReLU` +* `nn.Sigmoid`, `nn.Tanh`, `nn.ELU`, `nn.CELU` +* `nn.SELU`, `nn.GELU`, `nn.SiLU`(=Swish) +* `nn.Softmax`, `nn.LogSoftmax` +* `nn.Softplus`, `nn.Softsign` + +--- + +### 🔹 9. 稀疏与其他层 + +* `nn.SparseLinear`(PyTorch 2.5+ 才有) +* `nn.PixelShuffle` —— 超分辨率常用(上采样) +* `nn.Upsample` —— 上采样 +* `nn.Unfold / nn.Fold` —— 图像 Patch 提取和恢复 + +--- + +### 🔹 10. 容器(搭建网络时用) + +* `nn.Sequential` —— 顺序容器 +* `nn.ModuleList` —— 模块列表 +* `nn.ModuleDict` —— 模块字典 +* `nn.ParameterList / ParameterDict` —— 参数容器 + +--- + +👉 如果你是初学者,推荐学习路径大概是: +`Linear → Conv → Pool → BatchNorm/LayerNorm → Dropout → RNN/LSTM/GRU → Transformer → MultiheadAttention` + +要不要我帮你整理一份 **按“难度/应用领域”分层的学习路线图**(比如入门 → 图像 → NLP → 高级网络)?