ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数学建模竞赛中神经网络应用:从时序预测到多目标优化实战

数学建模竞赛中神经网络应用:从时序预测到多目标优化实战 1. 从“黑箱”到“白盒”神经网络在数模竞赛中的角色转变如果你参加过数学建模竞赛或者正准备参加那么“神经网络”这个词对你来说一定不陌生。它可能出现在队友兴奋的提议里——“这道题数据量这么大我们用神经网络试试吧”也可能出现在你查阅往年优秀论文时看到那些结构复杂的“黑箱”模型图。长久以来神经网络在数模圈子里尤其是对非计算机专业的同学而言常常被贴上“高端”、“复杂”、“难以解释”的标签甚至被当作一种“万能拟合器”来使用只要数据扔进去总能得到一个看起来不错的预测结果。但这样的用法在越来越强调模型可解释性和物理意义的现代数模赛题中正在逐渐失去竞争力。我参与和指导数学建模竞赛多年亲眼见证了神经网络在其中的应用从“炫技”走向“务实”。今天的数模竞赛无论是国赛、美赛还是其他区域性比赛赛题越来越倾向于交叉学科和实际问题。例如你可能需要预测城市交通流量、分析社交媒体上的舆情传播、或者优化复杂的供应链网络。这些问题往往具有高维度、非线性、时序依赖或图结构等特征而这恰恰是神经网络所擅长的领域。但关键在于我们不能再把神经网络当作一个扔进去数据就万事大吉的“黑箱”。相反我们需要将它视为一个强大的“函数逼近器”或“特征提取器”并将其有机地嵌入到我们对问题的整体数学建模框架中。这个过程我称之为从“黑箱”到“白盒”的转变。它要求我们不仅要会调用sklearn或TensorFlow的API更要理解网络每一层在数学上做了什么变换它的输出如何与我们的微分方程、优化目标或概率模型相结合。比如你可以用循环神经网络RNN的隐藏状态来刻画动态系统中的状态变量用图神经网络GNN来显式地建模实体间的关联关系然后用这些网络的输出作为另一个优化模型的输入或约束条件。这样神经网络就成了你数学模型的一个可微分的、可训练的组成部分而不仅仅是最后那个“预测模块”。这篇文章我就想结合最新的技术热点和竞赛趋势和你深入聊聊如何把神经网络真正“用对”、“用好”在数学建模中。我们会避开那些空洞的理论直接切入几个核心场景面对时序预测问题除了LSTM我们还有什么更轻量的选择当问题本质是图结构时如何用图卷积网络GCN将拓扑信息融入模型在多目标优化中神经网络如何帮助我们逼近复杂的Pareto前沿我们会拆解这些网络背后的数学直觉并提供可以直接套用到赛题中的代码骨架和思考框架。目标很简单让你下次在赛题中看到“神经网络”这个选项时能清晰地知道它是否适用、该如何设计、以及如何向评委优雅地解释你的模型。2. 前馈神经网络数模中基础的万能函数逼近器当我们谈论神经网络时最基础、最核心的形态就是前馈神经网络也常被称为多层感知机。在数模中它最常见的角色就是解决复杂的非线性回归或分类问题。你可能觉得它太“基础”了但恰恰是这种基础模型如果理解透彻能解决大部分赛题中“建立输入到输出的映射关系”这一核心需求。2.1 核心数学原理从线性组合到非线性激活前馈神经网络的数学本质并不神秘。假设我们有一个简单的三层网络输入层、隐藏层、输出层。对于隐藏层的第j个神经元其输出 \(h_j\) 是\(h_j \sigma(\sum_{i1}^{n} w_{ji}^{(1)} x_i b_j^{(1)})\)这里\(x_i\) 是输入特征\(w_{ji}^{(1)}\) 是连接输入i到隐藏神经元j的权重\(b_j^{(1)}\) 是偏置项。最关键的是 \(\sigma(\cdot)\)即激活函数。如果没有它那么无论堆叠多少层整个网络仍然只能表示线性变换失去了“深度”的意义。激活函数引入了非线性使得网络能够逼近任意复杂的连续函数这是著名的通用近似定理。在数模中选择激活函数不是随意的。对于隐藏层ReLU最常用计算简单能缓解梯度消失问题。公式为 \(f(x) max(0, x)\)。它会让负值输出为0可能导致“神经元死亡”。如果你的数据经过标准化后可能有正有负且你担心这个问题可以考虑Leaky ReLU。Sigmoid将输出压缩到(0,1)之间。过去常用但现在多用于输出层做二分类概率输出。在隐藏层使用容易导致梯度消失。Tanh输出在(-1,1)之间关于原点对称。在某些情况下比Sigmoid表现更好。对于输出层回归问题通常使用线性激活函数即无激活让网络直接输出任意实数。二分类问题使用Sigmoid将输出解释为概率。多分类问题使用Softmax确保所有输出之和为1每个输出代表对应类别的概率。在数模论文中你绝不能只写“我们使用了神经网络”。你必须说明网络的结构输入层维度对应你的特征数、隐藏层的层数和每层的神经元数量、以及每层使用的激活函数。例如“我们构建了一个包含一个输入层8个神经元对应8个特征、两个隐藏层分别包含64和32个神经元均使用ReLU激活函数和一个输出层1个神经元使用线性激活的全连接前馈网络用于预测连续目标变量。”2.2 在数模中的典型应用场景与实操步骤假设赛题要求根据历史数据预测某个经济指标。你的特征可能包括多种宏观经济数据维度高、可能存在复杂非线性关系。这时前馈神经网络就是一个强有力的候选模型。实操步骤问题转化与特征工程这是最重要的一步。将你的预测目标明确为回归或分类问题。对输入特征进行标准化或归一化这对神经网络的训练稳定性至关重要。例如使用sklearn.preprocessing.StandardScaler。同时思考特征之间的交互作用神经网络虽然能自动学习但提供一些先验知识如比率特征、交叉特征可能有助于提升性能和可解释性。网络结构设计输入层神经元数量等于特征维度。隐藏层从简单开始。一个经验法则是第一隐藏层的神经元数可以在输入层和输出层维度之间或采用“金字塔”结构逐层减少。对于数模这种数据量通常不大的场景1-3个隐藏层足矣每层神经元数不宜过多如16, 32, 64以防过拟合。输出层根据问题设定。代码骨架使用PyTorchimport torch import torch.nn as nn class EconomicPredictor(nn.Module): def __init__(self, input_dim): super(EconomicPredictor, self).__init__() self.fc1 nn.Linear(input_dim, 64) self.relu1 nn.ReLU() self.fc2 nn.Linear(64, 32) self.relu2 nn.ReLU() self.fc3 nn.Linear(32, 1) # 回归任务单输出 def forward(self, x): x self.relu1(self.fc1(x)) x self.relu2(self.fc2(x)) x self.fc3(x) # 最后一层无激活函数 return x模型训练与验证损失函数回归常用均方误差MSE分类常用交叉熵损失。优化器Adam是默认的、效果良好的选择。防止过拟合数模数据量小过拟合是大敌。务必使用早停和交叉验证。将数据分为训练集和验证集监控验证集损失当其在连续多个epoch不再下降时停止训练。也可以添加Dropout层。训练代码骨架model EconomicPredictor(input_dim8) criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr0.001) for epoch in range(num_epochs): model.train() for batch_x, batch_y in train_loader: optimizer.zero_grad() outputs model(batch_x) loss criterion(outputs, batch_y) loss.backward() optimizer.step() # 每个epoch后在验证集上评估 model.eval() with torch.no_grad(): val_loss ... if val_loss 不再下降: break # 早停结果分析与论文呈现不仅要给出预测精度如RMSE, R²还要进行误差分析。绘制预测值 vs 真实值的散点图、残差分布图。尝试进行简单的可解释性分析例如使用SHAP或LIME库如果时间允许找出哪些输入特征对预测结果影响最大。这能极大提升论文的深度。在论文中除了文字描述务必附上清晰的结构图。你可以使用torchviz库生成计算图或者用绘图工具如draw.io画一个简洁的示意图类似经典的“bp神经网络结构图”并标注各层维度。注意在数模中使用神经网络一定要和传统模型如线性回归、决策树做对比。在论文中建立一个“消融实验”或对比表格证明神经网络确实因为其非线性能力而取得了更优的效果否则使用它的必要性就会受到评委质疑。3. 征服序列数据超越LSTM的时序预测新思路时间序列预测是数模竞赛的常客从股票价格到流行病传播从能耗预测到交通流量。过去几年长短期记忆网络几乎是时序预测的代名词。但LSTM及其变体GRU结构相对复杂参数多训练慢在小数据集上容易过拟合。对于数模竞赛这种时间紧、数据量未必巨大的场景我们需要更高效、更稳健的工具。3.1 时序问题的本质与神经网络的选择逻辑时序预测的核心是捕捉序列中的依赖关系当前时刻的值如何受到过去多个时刻值的影响。这种依赖可能包括趋势、周期季节性和突发模式。传统方法如ARIMA有严格的平稳性假设而神经网络是一种数据驱动的、非参数的方法假设更少。选择网络结构的逻辑在于你如何理解这种依赖循环神经网络显式地维护一个“记忆状态”理论上可以捕捉任意长的依赖。但实际中LSTM/GRU通过门控机制缓解了梯度消失仍是处理长序列的有力工具。适用于依赖关系非常长且复杂的场景。一维卷积神经网络将时间序列视为一个一维信号使用一维卷积核在时间轴上滑动提取局部模式如最近几个时间点的特征。适用于依赖关系主要是局部性的场景计算效率远高于RNN。注意力机制与Transformer彻底抛弃了循环结构完全依赖自注意力机制来建立序列中任意两个位置之间的关联。在足够数据下它能捕捉非常复杂的全局依赖。但对于中小规模时序数据原版Transformer可能过于庞大。在2025年的数模赛题中我特别推荐你关注一种轻量且强大的结构Temporal Convolutional Network。它结合了CNN的高效和因果卷积确保预测不会使用未来信息的特性在许多基准数据集上超越了LSTM且训练速度更快更易于并行化。3.2 TCN实战为城市交通流量预测建模假设赛题C是关于城市交通流量预测给出了过去几个月各个路口每小时的车流量数据。这是一个典型的多变量时间序列预测问题。步骤一问题形式化我们需要用过去N个小时如24小时的所有路口流量数据来预测未来M个小时如下一个小时的流量。这是一个“多步预测”问题。我们可以采用滚动预测的方式先预测t1时刻再用预测值作为输入的一部分去预测t2时刻或使用Seq2Seq结构。步骤二构建TCN模型TCN的核心是因果膨胀卷积。因果确保卷积输出只依赖于当前及过去的时间点膨胀则允许卷积核在覆盖更长历史的同时不增加参数数量通过间隔采样。import torch import torch.nn as nn from torch.nn.utils import weight_norm class Chomp1d(nn.Module): # 因果卷积后裁剪掉右侧多余的填充 def __init__(self, chomp_size): super(Chomp1d, self).__init__() self.chomp_size chomp_size def forward(self, x): return x[:, :, :-self.chomp_size].contiguous() class TemporalBlock(nn.Module): # TCN的基本模块 def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout0.2): super(TemporalBlock, self).__init__() self.conv1 weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size, stridestride, paddingpadding, dilationdilation)) self.chomp1 Chomp1d(padding) self.relu1 nn.ReLU() self.dropout1 nn.Dropout(dropout) self.conv2 weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size, stridestride, paddingpadding, dilationdilation)) self.chomp2 Chomp1d(padding) self.relu2 nn.ReLU() self.dropout2 nn.Dropout(dropout) self.net nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1, self.conv2, self.chomp2, self.relu2, self.dropout2) self.downsample nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs ! n_outputs else None self.relu nn.ReLU() self.init_weights() def init_weights(self): self.conv1.weight.data.normal_(0, 0.01) self.conv2.weight.data.normal_(0, 0.01) if self.downsample is not None: self.downsample.weight.data.normal_(0, 0.01) def forward(self, x): out self.net(x) res x if self.downsample is None else self.downsample(x) return self.relu(out res) # 残差连接 class TCN(nn.Module): def __init__(self, num_inputs, num_channels, kernel_size2, dropout0.2): # num_channels: 各层卷积的输出通道数列表如[25, 25, 25]表示3个隐层每层25个通道 super(TCN, self).__init__() layers [] num_levels len(num_channels) for i in range(num_levels): dilation_size 2 ** i # 膨胀系数指数增长 in_channels num_inputs if i 0 else num_channels[i-1] out_channels num_channels[i] layers [TemporalBlock(in_channels, out_channels, kernel_size, stride1, dilationdilation_size, padding(kernel_size-1) * dilation_size, dropoutdropout)] self.network nn.Sequential(*layers) self.linear nn.Linear(num_channels[-1], 1) # 预测未来一个时间步 def forward(self, x): # x shape: (batch_size, seq_len, num_features) - 需要转为 (batch_size, num_features, seq_len) 给Conv1d x x.transpose(1, 2) y self.network(x) # 取最后一个时间步的输出进行预测 y self.linear(y[:, :, -1]) return y步骤三数据准备与训练# 假设我们有数据 X: (样本数, 历史序列长度seq_len24, 特征数num_features路口数) # 目标 y: (样本数, 1) 即下一个时刻的总流量或某个关键路口流量 model TCN(num_inputsnum_features, num_channels[25, 25, 25], kernel_size3, dropout0.1) criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr0.001) # 训练循环...步骤四模型对比与论文写作要点在论文中你需要阐明选择TCN的理由强调其因果性、并行计算效率、以及膨胀卷积在捕捉长期依赖上的优势。与基线模型对比务必与ARIMA、简单的线性回归、乃至LSTM进行对比在一个统一的验证集上比较RMSE、MAE等指标。可以制作一个对比表格。可视化绘制真实流量与TCN预测流量的时序对比图。还可以绘制感受野示意图解释你的TCN结构通过膨胀系数能够看到多长的历史数据感受野大小 1 2 * (kernel_size - 1) * (2^层数 -1)这体现了模型的可解释性。讨论局限性例如TCN对周期性的建模可能不如专门加入季节性分量的传统模型直观如果数据有强季节性可以考虑将周期性特征如小时、星期几作为额外输入特征加入。实操心得对于数模TCN的超参数如num_channels,kernel_size,dropout不宜设置过多。建议固定kernel_size3或5通过调整num_channels如[16,16]或[32,32]和dropout率来平衡拟合能力与过拟合风险。使用早停法至关重要。4. 理解关系与结构图卷积网络在数模中的破局应用当你的赛题数据中实体之间存在着明确的关系或网络结构时传统的神经网络前馈或循环就力有不逮了。例如2025年赛题C如果涉及社交网络信息传播、交通路网拥堵分析、论文引用网络分类、或化学分子性质预测其数据本质是一张图。每个节点用户、路口、论文、原子有自身的特征节点之间通过边关注关系、道路、引用、化学键连接。图卷积网络正是为处理这类非欧几里得结构化数据而生的。4.1 图卷积的通俗理解从“邻居投票”到特征传播你可以把GCN想象成一个“信息传播”或“邻居投票”的过程。在社交网络中要判断一个人的兴趣除了看他自己的资料看他朋友的兴趣也很有帮助。GCN做的就是这件事但它是通过数学来做的。假设我们有一张图可以用邻接矩阵A表示如果节点i和j相连则A_ij1否则为0。每个节点有一个特征向量h。最简单形式的GCN层操作可以表示为\(H^{(l1)} \sigma(\hat{D}^{-\frac{1}{2}} \hat{A} \hat{D}^{-\frac{1}{2}} H^{(l)} W^{(l)})\)看起来复杂我们来拆解\(\hat{A} A I\)给每个节点加上自连接自己也给自己“投票”。\(\hat{D}\) 是 \(\hat{A}\) 的度矩阵对角矩阵每个元素表示对应节点的连接数。\(\hat{D}^{-\frac{1}{2}} \hat{A} \hat{D}^{-\frac{1}{2}}\) 这一步是对邻接矩阵进行对称归一化。目的是防止度数高的节点在聚合信息时“声音”过大相当于给每个邻居的“投票”权重做了标准化。\(H^{(l)}\) 是第l层所有节点的特征矩阵。\(W^{(l)}\) 是该层可学习的权重矩阵。\(\sigma\) 是非线性激活函数。这个过程在做什么矩阵乘法 \(\hat{A} H^{(l)}\) 实现了每个节点将其邻居的特征加总过来。归一化操作让这个过程更稳定。然后再经过一个可学习的线性变换和非线性激活就得到了节点新的特征表示 \(H^{(l1)}\)。经过多层这样的操作每个节点的特征就融合了多跳邻居的信息。4.2 实战用GCN分析社交网络中的影响力传播假设赛题给出了一个社交网络的拓扑结构谁关注了谁和每个用户的初始特征如历史发帖关键词向量要求我们识别出潜在的“影响力枢纽”节点或者预测某个信息是否会在这个网络中大范围传播。步骤一图数据构建这是最关键的步骤。你需要定义什么是节点什么是边。节点每个用户。节点特征可以是其个人资料向量、近期发帖的TF-IDF向量等。边关注关系。注意社交网络通常是有向图A关注B但B未必关注A。在GCN中我们常先将其视为无向图处理或者使用有向GCN变体。邻接矩阵A根据关注关系构建。节点标签如果是分类任务如区分普通用户和大V则需要部分节点的标签。步骤二PyTorch Geometric实现PyTorch Geometric是处理图神经网络的利器极大简化了流程。import torch import torch.nn.functional as F from torch_geometric.nn import GCNConv from torch_geometric.data import Data # 1. 准备数据 # 假设 node_features 是形状为 [num_nodes, num_features] 的特征矩阵 # edge_index 是形状为 [2, num_edges] 的边列表第一行是源节点索引第二行是目标节点索引 # labels 是形状为 [num_nodes] 的标签部分节点有标签用于半监督学习 data Data(xnode_features, edge_indexedge_index, ylabels) # 划分训练、验证、测试掩码 data.train_mask ... # 布尔张量标记训练节点 data.val_mask ... data.test_mask ... # 2. 定义GCN模型 class GCNInfluencePredictor(torch.nn.Module): def __init__(self, in_channels, hidden_channels, out_channels, dropout0.5): super(GCNInfluencePredictor, self).__init__() self.conv1 GCNConv(in_channels, hidden_channels) self.conv2 GCNConv(hidden_channels, out_channels) self.dropout dropout def forward(self, data): x, edge_index data.x, data.edge_index x self.conv1(x, edge_index) x F.relu(x) x F.dropout(x, pself.dropout, trainingself.training) x self.conv2(x, edge_index) # 输出每个节点的类别分数 return F.log_softmax(x, dim1) # 3. 训练与评估 model GCNInfluencePredictor(in_channelsnum_features, hidden_channels16, out_channelsnum_classes) optimizer torch.optim.Adam(model.parameters(), lr0.01, weight_decay5e-4) def train(): model.train() optimizer.zero_grad() out model(data) loss F.nll_loss(out[data.train_mask], data.y[data.train_mask]) # 仅用有标签的训练节点计算损失 loss.backward() optimizer.step() return loss def test(mask): model.eval() with torch.no_grad(): out model(data) pred out.argmax(dim1) correct pred[mask] data.y[mask] acc int(correct.sum()) / int(mask.sum()) return acc for epoch in range(200): loss train() train_acc test(data.train_mask) val_acc test(data.val_mask) if epoch % 20 0: print(fEpoch: {epoch:03d}, Loss: {loss:.4f}, Train Acc: {train_acc:.4f}, Val Acc: {val_acc:.4f})步骤三结果分析与模型解释任务性能在测试集上报告分类准确率、精确率、召回率等。可视化使用t-SNE或UMAP将GCN最后一层输出的节点嵌入即节点的最终特征表示降维到2D并可视化用颜色表示预测类别或真实标签。一个好的GCN模型应该能让同类节点在嵌入空间聚集。影响力分析虽然GCN本身是一个分类器但你可以通过分析节点的嵌入向量来评估其“影响力”。例如计算所有节点嵌入的中心度如接近中心性或者观察那些被模型高置信度分类为“影响力枢纽”的节点在图中的结构位置它们往往是连接不同社群的桥梁节点。传播预测如果要预测信息传播可以将问题转化为链路预测或级联预测。例如使用GCN学习到的节点嵌入计算节点对之间的嵌入相似度如余弦相似度作为链接存在的可能性。重要提示在数模论文中解释GCN模型时一定要用直观的语言和示意图。画一张简单的图展示一个中心节点如何聚合其邻居的信息。说明你的网络层数通常2-3层足够因为过多的层会导致“过度平滑”所有节点的特征趋向一致和每层的含义第一层学习直接邻居特征第二层学习两跳邻居特征。这能有效化解评委对“黑箱”的疑虑。5. 多目标优化当神经网络遇见帕累托前沿很多数模优化问题并非单目标而是需要同时权衡多个相互冲突的目标。例如在资源调度中既要成本最低又要时间最短在产品设计中既要性能最强又要重量最轻。这类问题的解不是一个最优值而是一个帕累托最优解集集合中的任何一个解都无法在改进一个目标时不损害另一个目标。神经网络在这里可以扮演两个关键角色一是作为高效的代理模型来近似复杂的目标函数二是直接学习并生成帕累托前沿。5.1 神经网络作为代理模型加速计算昂贵的优化在一些工程优化问题中目标函数的计算可能极其昂贵例如需要运行一次耗时的流体动力学仿真才能得到一个性能指标。在优化算法如遗传算法、粒子群算法中需要成千上万次评估目标函数这直接不可行。此时我们可以用神经网络训练一个代理模型用少量仿真数据训练网络让它学习从设计变量到目标值的映射。之后优化算法就在这个快速的代理模型上进行评估大大加速寻优过程。操作流程实验设计使用拉丁超立方采样等方法在设计空间内生成一批有代表性的样本点。昂贵评估对这组样本点运行真实的仿真或实验得到其目标函数值。训练代理模型为每个目标函数训练一个独立的前馈神经网络回归模型或者一个多输出网络。输入是设计变量输出是目标值。集成优化将训练好的代理模型嵌入到多目标优化算法如NSGA-II中替代原始昂贵函数进行评估。验证与更新对代理模型预测的帕累托前沿上的解再进行少量真实评估验证其准确性。如果偏差大可以将这些新数据加入训练集重新训练代理模型这是一个主动学习过程。这种方法在论文中被称为“基于代理模型的优化”能显著提升解决复杂工程优化问题的可行性。5.2 神经网络直接生成帕累托前沿Pareto Set Learning另一种更“端到端”的思路是训练一个神经网络其输入是一个偏好向量或标量输出直接是对应于该偏好的帕累托最优解。这个网络被称为Pareto Set Learner。它的优势在于一旦训练完成我们可以通过连续地改变偏好向量实时、平滑地生成整个帕累托前沿的近似而无需重新运行优化算法。核心思想以两目标最小化问题为例假设有两个目标f1和f2。我们引入一个偏好标量 \(\lambda \in [0, 1]\)。将多目标问题转化为一个带偏好的标量化问题例如使用加权切比雪夫方法 \(g(x | \lambda, z^) max{ \lambda |f_1(x) - z_1^|, (1-\lambda) |f_2(x) - z_2^| }\) 其中 \(z^\) 是理想点每个目标单独能达到的最优值。对于每个固定的 \(\lambda\)求解 \(min_x g(x | \lambda, z^*)\) 可以得到一个帕累托最优解。神经网络的角色我们训练一个网络 \(PSL-Net\)输入是 \(\lambda\)输出是解 \(x\)。即 \(x PSL-Net(\lambda; \theta)\)。网络的参数 \(\theta\) 通过优化以下损失函数来学习 \(L(\theta) E_{\lambda \sim U(0,1)}[ g(PSL-Net(\lambda; \theta) | \lambda, z^* ) ]\) 通过随机采样不同的 \(\lambda\) 并最小化上述损失的期望网络就学会了覆盖整个帕累托前沿的解。简易代码示意import torch import torch.nn as nn import torch.optim as optim class ParetoSetNetwork(nn.Module): def __init__(self, solution_dim): super(ParetoSetNetwork, self).__init__() self.net nn.Sequential( nn.Linear(1, 32), # 输入是偏好lambda (1维) nn.ReLU(), nn.Linear(32, 64), nn.ReLU(), nn.Linear(64, solution_dim) # 输出是解向量x ) def forward(self, lambda_pref): # lambda_pref: (batch_size, 1) return self.net(lambda_pref) def weighted_chebyshev(solution, lambda_pref, ideal_point): # solution: (batch_size, solution_dim) - 经过一个评价函数得到目标值 # 这里假设我们有一个函数能计算f1和f2 f1, f2 evaluate_objectives(solution) # 假设返回都是(batch_size, 1) obj1 torch.abs(f1 - ideal_point[0]) obj2 torch.abs(f2 - ideal_point[1]) g torch.max(lambda_pref * obj1, (1 - lambda_pref) * obj2) return g # 训练循环 model ParetoSetNetwork(solution_dim10) optimizer optim.Adam(model.parameters(), lr1e-3) ideal_point torch.tensor([f1_min, f2_min]) # 需要预先估计 for epoch in range(epochs): optimizer.zero_grad() lambda_batch torch.rand(batch_size, 1) # 随机采样偏好 solutions model(lambda_batch) loss weighted_chebyshev(solutions, lambda_batch, ideal_point).mean() loss.backward() optimizer.step()训练完成后要生成帕累托前沿只需均匀采样多个 \(\lambda\) 值输入网络得到一系列解再评估这些解的真实目标值绘制在目标空间即可。在数模论文中的应用要点问题适配明确说明你的问题是一个多目标优化问题并列出冲突的目标。方法选择理由解释为什么选择神经网络方法例如目标函数复杂、需要快速得到前沿近似、解空间连续等。对比实验将神经网络方法无论是代理模型还是PSL与经典多目标优化算法如NSGA-II在解的质量如超体积指标和计算时间上进行对比。前沿可视化这是最大的亮点。绘制出由神经网络方法生成的帕累托前沿并与传统方法生成的前沿进行对比。清晰的二维或三维前沿图极具说服力。决策支持说明如何利用这个前沿进行决策。例如决策者可以根据对两个目标的偏好程度即选择一个 \(\lambda\)直接从网络中读取出对应的最优设计方案。这体现了模型的实用价值。神经网络在数模中的应用早已超越了简单的数据拟合。无论是处理时序、图结构还是多目标优化其核心价值在于为我们提供了强大的、可微分的建模组件能够将领域知识如时序因果性、图连接关系、多目标权衡以数据驱动的方式嵌入到数学模型中。掌握这些工具并理解其背后的数学直觉和应用场景能让你在面对复杂赛题时拥有更多样、更犀利的解题武器。关键在于永远不要为了用神经网络而用而是要清楚它在你整个模型框架中究竟解决了哪个传统方法难以处理的子问题。
返回列表