当前位置: 首页 > news >正文

PyTorch:神经网络模块

PyTorch 的 torch.nn 模块,是构建神经网络最核心的模块。它提供了模型基类、常用网络层、激活函数、损失函数、容器结构、参数管理和训练状态控制等能力。

简单地说,torch.nn 模块回答的是:神经网络在 PyTorch 中如何表示、如何组织、如何完成前向计算,以及模型参数如何被自动管理。

如果说 torch 模块负责张量与基础计算,那么 torch.nn 模块就负责把这些张量计算组织成“模型”。在实际深度学习项目中,我们很少只写零散的矩阵乘法,而是会把线性层、卷积层、激活函数、归一化层、Dropout 层和损失函数组合成一个完整的神经网络。

一、认识 torch.nn 模块

torch.nn 是 PyTorch 中专门用于神经网络建模的模块。它并不是只提供几个网络层,而是围绕模型构建提供了一套完整机制。

图 1:torch.nn 模块在 PyTorch 训练流程中的位置

在 PyTorch 中,一个神经网络通常由以下部分组成:

• 模型基类:nn.Module

• 网络层:如 nn.Linear、nn.Conv2d、nn.Embedding

• 激活函数:如 nn.ReLU、nn.Sigmoid、nn.GELU

• 损失函数:如 nn.CrossEntropyLoss、nn.MSELoss

• 容器结构:如 nn.Sequential、nn.ModuleList

• 参数管理:如 parameters()、state_dict()

• 训练与推理状态:如 train()、eval()

一个最简单的使用方式如下:

import torchimport torch.nn as nn # 定义一个线性层:输入特征数为 4,输出特征数为 3layer = nn.Linear(4, 3) # 构造 2 个样本,每个样本有 4 个特征x = torch.randn(2, 4) # 前向计算,得到 2 个样本在 3 个输出维度上的结果y = layer(x) print(y.shape)

输出形状为:

torch.Size([2, 3])

这里可以看出,nn.Linear 不只是一个普通函数,而是一个带有可学习参数的模块。它内部保存了权重和偏置,并会在训练过程中被更新。

二、nn.Module:所有神经网络模块的基础

在 PyTorch 中,大多数神经网络模型都会继承 nn.Module。它是模型组织的基础。

图 2:nn.Module 的基本结构

一个典型模型通常包含两个部分:

• __init__():定义模型中需要用到的层

• forward():定义数据如何从输入流向输出

例如:

import torchimport torch.nn as nn class SimpleNet(nn.Module): def __init__(self): super().__init__() # 定义第一层:4 个输入特征映射到 16 个隐藏特征 self.fc1 = nn.Linear(4, 16) # 定义激活函数 self.relu = nn.ReLU() # 定义第二层:16 个隐藏特征映射到 3 个输出类别 self.fc2 = nn.Linear(16, 3) def forward(self, x): # 输入先经过第一层 x = self.fc1(x) # 再经过非线性激活 x = self.relu(x) # 最后得到输出结果 x = self.fc2(x) return x model = SimpleNet() x = torch.randn(8, 4)y = model(x) print(y.shape) # torch.Size([8, 3])

这里最重要的不是代码长度,而是理解模型的组织方式:

• __init__() 负责“有哪些层”

• forward() 负责“数据怎么流动”

• model(x) 会自动调用 forward(x)

• 模型中的层会被自动注册,参数也会被自动管理

这就是 PyTorch 模型定义的基本范式。

三、forward():定义前向传播逻辑

forward() 方法决定输入张量如何一步步变成输出张量。它体现的是模型的计算路径。

例如,一个两层神经网络可以理解为:

输入 x→ 线性层 fc1→ 激活函数 ReLU→ 线性层 fc2→ 输出 logits

对应代码是:

def forward(self, x): x = self.fc1(x) x = self.relu(x) x = self.fc2(x) return x

在分类任务中,模型最后输出的通常不是直接类别,而是一组分数,常称为 logits。

例如:

logits = model(x)print(logits.shape)

如果 logits.shape 是 (8, 3),可以理解为:

• 有 8 个样本

• 每个样本对应 3 个类别分数

• 分数越大,模型越倾向于该类别

需要注意的是,很多分类模型的最后一层不需要手动加 Softmax。如果后面使用 nn.CrossEntropyLoss(),它会在内部处理与分类概率相关的计算。因此,模型通常直接输出原始分数即可。

四、nn.Linear:全连接层

nn.Linear 是最基础、最常用的神经网络层之一。它常用于多层感知机、分类头、回归头和 Transformer 中的前馈网络部分。

全连接层(也称为“线性层”)的核心计算可以理解为:

其中:

• X 表示输入张量

• W 表示权重矩阵

• b 表示偏置

• Y 表示输出张量

代码示例:

import torchimport torch.nn as nn # 输入特征数为 4,输出特征数为 2linear = nn.Linear(4, 2) # 5 个样本,每个样本 4 个特征x = torch.randn(5, 4) # 输出形状为 (5, 2)y = linear(x) print(y.shape)print(linear.weight.shape)print(linear.bias.shape)

需要注意的是,nn.Linear(4, 2) 中的 4 和 2 分别表示:

• in_features=4:每个样本输入特征数

• out_features=2:每个样本输出特征数

它并不表示有 4 个样本或 2 个样本。样本数量通常由输入张量的第 0 维决定。

五、激活函数:引入非线性能力

如果神经网络只有线性层,那么多层线性变换叠加后,本质上仍然可以合并成一个线性变换。为了让模型表达更复杂的非线性关系,需要引入激活函数。

常见激活函数包括:

• nn.ReLU

• nn.Sigmoid

• nn.Tanh

• nn.LeakyReLU

• nn.GELU

• nn.Softmax

示例:

import torchimport torch.nn as nn x = torch.tensor([-2.0, -1.0, 0.0, 1.0, 2.0]) # ReLU 会把负数变为 0,正数保持不变relu = nn.ReLU() # Sigmoid 会把数值压缩到 0 到 1 之间sigmoid = nn.Sigmoid() # Tanh 会把数值压缩到 -1 到 1 之间tanh = nn.Tanh() print(relu(x))print(sigmoid(x))print(tanh(x))

在现代深度学习中,ReLU 和它的变体非常常见;在 Transformer、BERT、GPT 等模型中,GELU 也经常出现。

需要注意的是,激活函数并不是随便添加的。它通常位于线性层或卷积层之后,用于增加模型的非线性表达能力。

六、nn.Sequential:按顺序组织模型

如果模型结构是简单的“从前到后依次执行”,可以使用 nn.Sequential 简化代码。

例如,下面这个模型与前面手写 forward() 的两层网络等价:

import torchimport torch.nn as nn model = nn.Sequential( nn.Linear(4, 16), # 输入层到隐藏层 nn.ReLU(), # 非线性激活 nn.Linear(16, 3) # 隐藏层到输出层) x = torch.randn(8, 4)y = model(x) print(y.shape)

nn.Sequential 的优点是简洁,适合线性堆叠结构。例如:

• 多层感知机

• 简单卷积网络

• 分类头

• 回归头

• 特征映射模块

但如果模型中包含复杂分支、跳跃连接、多输入多输出或条件逻辑,nn.Sequential 就不够灵活。这时更适合继承 nn.Module 并手写 forward()。

七、ModuleList 与 ModuleDict:保存多个子模块

有些模型中,层的数量可能比较多,或者需要在循环中组织多个子模块。这时可以使用 nn.ModuleList 或 nn.ModuleDict。

1、ModuleList:列表形式保存子模块

import torchimport torch.nn as nn class DeepMLP(nn.Module): def __init__(self): super().__init__() # 用 ModuleList 保存多个线性层 self.layers = nn.ModuleList([ nn.Linear(4, 16), nn.Linear(16, 16), nn.Linear(16, 3) ]) self.relu = nn.ReLU() def forward(self, x): # 前两层后接 ReLU,最后一层直接输出 for layer in self.layers[:-1]: x = self.relu(layer(x)) x = self.layers[-1](x) return x model = DeepMLP() x = torch.randn(8, 4)y = model(x) print(y.shape) # torch.Size([8, 3])

ModuleList 的关键作用是:让 PyTorch 能够正确识别并管理其中的子模块参数。

不要简单地用普通 Python 列表保存网络层。普通列表中的层可能不会被模型正确注册,从而导致参数无法被优化器更新。

2、ModuleDict:字典形式保存子模块

import torchimport torch.nn as nn class MultiHeadModel(nn.Module): def __init__(self): super().__init__() self.shared = nn.Linear(4, 16) # 用 ModuleDict 保存多个任务头 self.heads = nn.ModuleDict({ "classification": nn.Linear(16, 3), "regression": nn.Linear(16, 1) }) self.relu = nn.ReLU() def forward(self, x, task): x = self.relu(self.shared(x)) x = self.heads[task](x) return x model = MultiHeadModel() x = torch.randn(8, 4) y_cls = model(x, task="classification")y_reg = model(x, task="regression") print(y_cls.shape) # torch.Size([8, 3])print(y_reg.shape) # torch.Size([8, 1])

ModuleDict 适合需要按名称选择不同子模块的场景,例如多任务学习、多个输出头、多种特征处理分支等。

八、损失函数:衡量预测与目标的差异

神经网络训练不仅需要模型输出,还需要损失函数。损失函数用于衡量模型预测结果与真实目标之间的差异。

常见损失函数包括:

• nn.CrossEntropyLoss:多分类任务常用

• nn.BCELoss:二分类概率输出场景

• nn.BCEWithLogitsLoss:二分类或多标签任务常用

• nn.MSELoss:回归任务常用

• nn.L1Loss:平均绝对误差损失

• nn.NLLLoss:负对数似然损失

1、分类任务中的 CrossEntropyLoss

import torchimport torch.nn as nn class DeepMLP(nn.Module): def __init__(self): super().__init__() # 用 ModuleList 保存多个线性层 self.layers = nn.ModuleList([ nn.Linear(4, 16), nn.Linear(16, 16), nn.Linear(16, 3) ]) self.relu = nn.ReLU() def forward(self, x): # 前两层后接 ReLU,最后一层直接输出 for layer in self.layers[:-1]: x = self.relu(layer(x)) x = self.layers[-1](x) return x model = DeepMLP() x = torch.randn(8, 4)y = model(x) print(y.shape) # torch.Size([8, 3])

这里需要特别注意:

• logits 的形状通常是 (batch_size, num_classes)

• target 的形状通常是 (batch_size,)

• target 中保存的是类别编号,不是 one-hot 向量

• 使用 CrossEntropyLoss 时,模型最后通常不需要手动加 Softmax

这是初学者非常容易出错的地方。如果把标签写成 one-hot,或者提前对 logits 做了不必要的 Softmax,可能会导致训练效果异常。

2、回归任务中的 MSELoss

import torchimport torch.nn as nn # 8 个样本,每个样本预测 1 个连续数值pred = torch.randn(8, 1) # 对应的真实连续数值target = torch.randn(8, 1) # 均方误差损失criterion = nn.MSELoss() loss = criterion(pred, target) print(loss)

回归任务中,预测值和真实值通常都使用浮点张量,并且形状应尽量保持一致。

例如,如果 pred 的形状是 (8, 1),而 target 的形状是 (8,),有时可能会触发广播,导致计算含义不符合预期。因此,回归任务中要特别注意预测值和目标值的形状。

九、卷积层、池化层与图像特征提取

在图像任务中,常用的神经网络层包括卷积层、归一化层、激活函数和池化层。

典型组合可以写成:

import torchimport torch.nn as nn class SmallCNN(nn.Module): def __init__(self): super().__init__() self.features = nn.Sequential( nn.Conv2d(3, 16, kernel_size=3, padding=1), # 输入 3 通道,输出 16 通道 nn.BatchNorm2d(16), # 对 16 个通道做批量归一化 nn.ReLU(), # 引入非线性 nn.MaxPool2d(kernel_size=2), # 高宽减半 nn.Conv2d(16, 32, kernel_size=3, padding=1), nn.BatchNorm2d(32), nn.ReLU(), nn.MaxPool2d(kernel_size=2) ) self.classifier = nn.Linear(32 * 8 * 8, 10) def forward(self, x): x = self.features(x) # 保留批次维度,把每张图像的特征展平成向量 x = torch.flatten(x, start_dim=1) x = self.classifier(x) return x model = SmallCNN() # 8 张 32×32 RGB 图像x = torch.randn(8, 3, 32, 32) y = model(x) print(y.shape) # torch.Size([8, 10])

这里的结构可以理解为:

• 卷积层负责提取局部特征

• 激活函数引入非线性

• 池化层降低空间尺寸

• 展平操作把特征图变成向量

• 全连接层输出分类结果

在卷积网络中,输入通常采用 (N, C, H, W) 格式。如果图像数据是 (N, H, W, C),需要先调整维度顺序。

十、Dropout 与归一化层

在神经网络训练中,除了线性层和卷积层,还经常使用 Dropout 与归一化层来改善训练效果。

1、Dropout:随机失活

import torchimport torch.nn as nn dropout = nn.Dropout(p=0.5) x = torch.ones(10) # 训练模式下,部分元素会被随机置为 0dropout.train()print(dropout(x)) # 推理模式下,Dropout 不再随机丢弃元素dropout.eval()print(dropout(x))

Dropout 常用于缓解过拟合。它在训练阶段随机丢弃部分神经元输出,使模型不要过度依赖某些局部特征。

需要注意的是,Dropout 在训练模式和推理模式下行为不同。因此,训练时要调用 model.train(),推理或验证时要调用 model.eval()。

2、BatchNorm 与 LayerNorm

常见归一化层包括:

• nn.BatchNorm1d

• nn.BatchNorm2d

• nn.LayerNorm

示例:

import torchimport torch.nn as nn # 常用于全连接网络或一维特征bn1d = nn.BatchNorm1d(16) # 常用于卷积网络中的特征图bn2d = nn.BatchNorm2d(16) # 常用于 Transformer 等结构ln = nn.LayerNorm(16) x1 = torch.randn(8, 16)x2 = torch.randn(8, 16, 32, 32) print(bn1d(x1).shape)print(bn2d(x2).shape)

归一化层的作用不是改变任务目标,而是让中间特征的数值分布更稳定,从而帮助模型更顺利地训练。

十一、Embedding、RNN 与 Transformer 相关层

torch.nn 不只用于普通前馈网络和卷积网络,也提供了文本、序列和注意力模型相关的常用层。

1、Embedding:把离散编号映射为向量

nn.Embedding 常用于自然语言处理和推荐系统。它可以把词编号、用户编号、物品编号等离散 ID 映射为连续向量。

示例:

import torchimport torch.nn as nn # 词表大小为 1000,每个词映射为 64 维向量embedding = nn.Embedding(num_embeddings=1000, embedding_dim=64) # 4 个样本,每个样本包含 10 个词编号token_ids = torch.randint(0, 1000, (4, 10)) # 输出形状为 (4, 10, 64)x = embedding(token_ids) print(x.shape)

这里可以理解为:

• 输入是整数编号

• 输出是连续向量

• 每个编号都有一个可学习的向量表示

2、RNN、LSTM 与 GRU:处理序列数据的循环网络结构

RNN、LSTM 与 GRU 都属于处理序列数据的循环神经网络结构,常用于文本、语音、时间序列等任务。

RNN(循环神经网络)是基础循环结构,LSTM(长短期记忆网络)和 GRU(门控循环单元)是对普通 RNN 的改进版本,目的都是让模型更好地处理序列中的上下文信息。

示例:

import torchimport torch.nn as nn # 输入特征维度为 32,隐藏状态维度为 64rnn = nn.LSTM(input_size=32, hidden_size=64, batch_first=True) # 8 个样本,每个样本长度为 10,每个时间步 32 个特征x = torch.randn(8, 10, 32) # output 保存每个时间步的输出,h_n 和 c_n 保存最终隐藏状态与记忆状态output, (h_n, c_n) = rnn(x) print(output.shape)print(h_n.shape)print(c_n.shape)

当 batch_first=True 时,输入形状通常是:

(batch_size, sequence_length, input_size)

序列模型中最容易混淆的是维度顺序。写代码时要特别确认:

• 哪一维是批次

• 哪一维是时间步

• 哪一维是特征

3、MultiheadAttention 与 Transformer

nn.MultiheadAttention 和 nn.Transformer 可用于构建注意力机制与 Transformer 结构。

import torchimport torch.nn as nn # 嵌入维度为 64,注意力头数为 4attention = nn.MultiheadAttention(embed_dim=64, num_heads=4, batch_first=True) # 8 个样本,序列长度为 10,每个 token 是 64 维向量x = torch.randn(8, 10, 64) # 自注意力中,query、key、value 可以来自同一个输入output, weights = attention(x, x, x) print(output.shape)print(weights.shape)

这里重点是理解:

• 输入通常是序列张量

• 每个位置会与其他位置建立关系

• 输出形状通常与输入主结构保持一致

Transformer 结构较复杂,初学阶段不必急于展开所有细节。先理解 Embedding、序列张量形状和注意力输入输出关系,会更稳妥。

十二、参数管理:parameters() 与 state_dict()

神经网络训练的本质,是不断更新模型中的可学习参数。nn.Module 会自动管理模型中的参数。

1、查看模型参数

import torch.nn as nn model = nn.Sequential( nn.Linear(4, 16), nn.ReLU(), nn.Linear(16, 3)) # 遍历模型中所有可学习参数for name, param in model.named_parameters(): print(name, param.shape)

输出结果类似:

0.weight torch.Size([16, 4])0.bias torch.Size([16])2.weight torch.Size([3, 16])2.bias torch.Size([3])

这里可以看到,ReLU 没有可学习参数,而 Linear 有权重和偏置。

2、parameters():交给优化器更新

import torch.optim as optim model = nn.Linear(4, 3) # 优化器通过 model.parameters() 获取需要更新的参数optimizer = optim.Adam(model.parameters(), lr=0.001)

这也是为什么模型层必须正确注册到 nn.Module 中。如果某些层没有被注册,优化器可能无法找到它们的参数。

3、state_dict():保存模型参数

import torchimport torch.nn as nn model = nn.Linear(4, 3) # 查看模型参数字典state = model.state_dict() print(state.keys()) # 保存模型参数torch.save(model.state_dict(), "model.pth")

加载参数通常写成:

model = nn.Linear(4, 3) # 加载已保存的参数model.load_state_dict(torch.load("model.pth"))

state_dict() 是 PyTorch 中非常常用的模型保存方式。它保存的是参数,而不是完整训练代码。因此,加载时通常需要先重新定义相同结构的模型。

十三、train() 与 eval():训练模式和推理模式

某些层在训练和推理时行为不同,例如:

• Dropout:训练时随机丢弃,推理时不丢弃

• BatchNorm:训练时使用当前批次统计量,推理时使用累计统计量

因此,在训练和验证时要明确切换模式。

# 进入训练模式model.train() # 训练阶段:通常会执行前向传播、计算损失、反向传播和参数更新logits = model(x)loss = criterion(logits, target) # 进入推理模式model.eval() # 推理阶段:通常还会配合 torch.no_grad()with torch.no_grad(): logits = model(x)

需要注意:

• model.train() 不会自动训练模型,只是切换为训练模式

• model.eval() 不会停止梯度计算,只是切换为推理模式

• 推理时通常还要使用 torch.no_grad() 关闭梯度记录

十四、一个完整示例:用 nn 构建并训练简单分类模型

图 3:torch.nn 模型训练闭环

下面用一个完整示例,把 torch.nn、损失函数和优化器串起来。

import torchimport torch.nn as nnimport torch.optim as optim # 1. 构造模拟数据:200 个样本,每个样本 4 个特征,类别数为 3X = torch.randn(200, 4)y = torch.randint(0, 3, (200,)) class MLPClassifier(nn.Module): def __init__(self): super().__init__() # 使用 Sequential 组织简单多层感知机 self.net = nn.Sequential( nn.Linear(4, 16), nn.ReLU(), nn.Linear(16, 3) ) def forward(self, x): return self.net(x) # 2. 创建模型model = MLPClassifier() # 3. 多分类任务常用交叉熵损失criterion = nn.CrossEntropyLoss() # 4. Adam 优化器负责更新模型参数optimizer = optim.Adam(model.parameters(), lr=0.01) # 5. 训练模型for epoch in range(10): model.train() # 前向传播 logits = model(X) # 计算损失 loss = criterion(logits, y) # 清空上一轮梯度 optimizer.zero_grad() # 反向传播 loss.backward() # 更新参数 optimizer.step() print(f"第 {epoch + 1} 轮,损失:{loss.item():.4f}")

这个示例体现了神经网络训练的基本闭环:

输入数据 → 模型前向计算 → 计算损失 → 清空梯度 → 反向传播 → 参数更新

其中,torch.nn 主要负责模型结构和损失函数;优化器负责根据梯度更新参数。

十五、使用 torch.nn 时应注意的问题

1、不要忘记继承 nn.Module 并调用 super().init()

自定义模型时,通常要写:

class MyModel(nn.Module): def __init__(self): super().__init__()

如果忘记调用 super().__init__(),子模块和参数可能无法被正常注册,后续训练会出现问题。

2、网络层应定义在 init() 中

推荐写法:

class MyModel(nn.Module): def __init__(self): super().__init__() self.fc = nn.Linear(4, 3) def forward(self, x): return self.fc(x)

不推荐在 forward() 中反复新建带参数的层:

def forward(self, x): # 不推荐:每次前向传播都会新建一层 fc = nn.Linear(4, 3) return fc(x)

原因是:训练需要持续更新同一组参数。如果每次前向传播都创建新层,模型参数就无法稳定学习。

3、注意输入输出形状

神经网络层对输入形状有明确要求。例如:

• nn.Linear 通常关注输入最后一维

• nn.Conv2d 通常要求输入为 (N, C, H, W)

• nn.LSTM 在 batch_first=True 时常用 (N, T, D)

• nn.CrossEntropyLoss 常用 (N, C) 的预测值和 (N,) 的类别标签

很多错误都可以通过打印形状定位:

print(x.shape)print(logits.shape)print(target.shape)

4、区分 logits、概率和类别

分类模型中,常见三个概念:

• logits:模型输出的原始分数

• 概率:经过 Softmax 后得到的归一化结果

• 类别:分数最大或概率最大的类别编号

例如:

import torch logits = torch.randn(4, 3) # 将原始分数转换为概率probs = torch.softmax(logits, dim=1) # 取概率最大的类别编号pred = torch.argmax(probs, dim=1) print(pred)

训练时使用 CrossEntropyLoss,通常直接输入 logits,不需要先手动计算 Softmax。

5、训练与推理模式要切换

涉及 Dropout、BatchNorm 等层时,训练和推理行为不同。

训练阶段:

model.train()

验证或推理阶段:

model.eval() with torch.no_grad(): output = model(x)

这两个操作不应省略。否则,验证结果可能不稳定,推理结果也可能受到训练行为影响。

6、用 ModuleList 保存多个层,而不是普通列表

如果多个层需要放在列表里,推荐使用:

self.layers = nn.ModuleList([ nn.Linear(4, 16), nn.Linear(16, 3)])

不要简单写成:

self.layers = [ nn.Linear(4, 16), nn.Linear(16, 3)]

普通列表中的层可能不会被正确注册,优化器也可能无法更新其中的参数。

7、损失函数要匹配任务类型

不同任务应该使用不同损失函数:

• 多分类任务:常用 CrossEntropyLoss

• 二分类任务:常用 BCEWithLogitsLoss

• 回归任务:常用 MSELoss 或 L1Loss

• 多标签任务:常用 BCEWithLogitsLoss

损失函数选错,模型即使能运行,也可能学不到正确目标。

📘 小结

torch.nn 模块负责神经网络模型的构建与组织,是从张量计算走向深度学习建模的关键模块。学习这一模块,重点不只是记住层名称,而是理解 nn.Module 如何管理层和参数,forward() 如何定义数据流,损失函数如何连接预测与目标,以及训练模式和推理模式为何必须区分。

“点赞有美意,赞赏是鼓励”

http://www.jsqmd.com/news/875089/

相关文章:

  • 再不部署AI Agent,你的核保团队将在2025Q3面临37%产能缺口:来自精算与IT双视角的倒计时预警
  • 《纳瓦尔宝典》自我救赎篇精读:程序员如何走出内卷焦虑,重塑完整自我
  • 跨环境漏洞复现:Docker Desktop与VMware Kali的TCP/信号对齐实战
  • APS与RAPS:置信预测中覆盖保证与集合效率的权衡解析
  • AI Agent驱动的社交关系链重建:基于172万用户行为数据的动态图谱建模方法论
  • 别再花钱买云服务器了!手把手教你用闲置旧电脑搭建CentOS 7本地开发环境(附TitanIDE一键部署脚本)
  • 2026年口碑好的温州加厚拉链袋/拉链袋免费打样推荐品牌厂家 - 品牌宣传支持者
  • Unity AssetBundle浏览器(ABB)深度解析与工程实践技巧
  • 2026-05-24:预算下的最大总容量。用go语言,有两组长度都为 n 的整数数组: - costs:第 i 台机器的价格 - capacity:第 i 台机器的性能指标(容量) 再给定一个预算 b
  • 别再乱改注册表了!Windows系统文件夹移动后还原的完整避坑指南
  • 特征工程与测试时适应:提升表格数据机器学习性能的关键实践
  • 区块链+计算机视觉:构建可信AI系统的链上存证架构实践
  • LeetCode 238:除自身以外数组的乘积 | 前缀积与后缀积
  • 告别密码!5分钟搞定CentOS 7服务器间的SFTP免密互传(附权限避坑指南)
  • 在国产银河麒麟V10上搞定VMware Workstation 17 Pro,手把手教你从下载到创建第一个虚拟机
  • LeetCode 523:连续的子数组和 | 前缀和同余定理
  • 机器学习评估可信度危机:数据污染、选择性报告与结果误报的深度剖析与应对
  • Win10/Win11频繁蓝屏DPC_WATCHDOG_VIOLATION?别慌,用WinDBG的!dpcwatchdog命令5分钟定位元凶
  • [智能体-41]:智能体识别调用外部工具:原理 + 判定手段 + Python 最简代码示例
  • 对抗性环境下基于分布鲁棒优化的k-次模拦截问题求解
  • 基于树莓派与YOLOv8的铁路道口智能安全系统全栈实践
  • Ubuntu 20.04插上网线没反应?手把手教你搞定RTL8111/8168/8411网卡驱动(附自动加载服务配置)
  • Burp Suite扫描深度配置指南:被动扫描、主动扫描与自定义插入点协同调优
  • 信息论视角下的模型压缩与贝叶斯非参数建模理论边界分析
  • 卷积神经网络频谱分析与LFA-SVD优化方法
  • 当国产欧拉系统遇上VMware ESXi:一次非官方兼容环境的部署实践与思考
  • Pico Neo3 Unity XR开发实战:从黑屏到手柄响应的完整链路
  • LeetCode 724:寻找数组的中心下标 | 前缀和的平衡点
  • [智能体-42]:深度解读:Python 免编译 + 动态执行,支撑智能体落地大模型决策
  • Juno平台TF-A安全调试功能恢复与配置指南