學(xué)建模競(jìng)賽中神經(jīng)網(wǎng)絡(luò)應(yīng)用:從時(shí)序預(yù)測(cè)到多目標(biāo)優(yōu)化實(shí)戰(zhàn))
1. 從“黑箱”到“白盒”神經(jīng)網(wǎng)絡(luò)在數(shù)模競(jìng)賽中的角色轉(zhuǎn)變?nèi)绻銋⒓舆^(guò)數(shù)學(xué)建模競(jìng)賽或者正準(zhǔn)備參加那么“神經(jīng)網(wǎng)絡(luò)”這個(gè)詞對(duì)你來(lái)說(shuō)一定不陌生。它可能出現(xiàn)在隊(duì)友興奮的提議里——“這道題數(shù)據(jù)量這么大我們用神經(jīng)網(wǎng)絡(luò)試試吧”也可能出現(xiàn)在你查閱往年優(yōu)秀論文時(shí)看到那些結(jié)構(gòu)復(fù)雜的“黑箱”模型圖。長(zhǎng)久以來(lái)神經(jīng)網(wǎng)絡(luò)在數(shù)模圈子里尤其是對(duì)非計(jì)算機(jī)專業(yè)的同學(xué)而言常常被貼上“高端”、“復(fù)雜”、“難以解釋”的標(biāo)簽甚至被當(dāng)作一種“萬(wàn)能擬合器”來(lái)使用只要數(shù)據(jù)扔進(jìn)去總能得到一個(gè)看起來(lái)不錯(cuò)的預(yù)測(cè)結(jié)果。但這樣的用法在越來(lái)越強(qiáng)調(diào)模型可解釋性和物理意義的現(xiàn)代數(shù)模賽題中正在逐漸失去競(jìng)爭(zhēng)力。我參與和指導(dǎo)數(shù)學(xué)建模競(jìng)賽多年親眼見(jiàn)證了神經(jīng)網(wǎng)絡(luò)在其中的應(yīng)用從“炫技”走向“務(wù)實(shí)”。今天的數(shù)模競(jìng)賽無(wú)論是國(guó)賽、美賽還是其他區(qū)域性比賽賽題越來(lái)越傾向于交叉學(xué)科和實(shí)際問(wèn)題。例如你可能需要預(yù)測(cè)城市交通流量、分析社交媒體上的輿情傳播、或者優(yōu)化復(fù)雜的供應(yīng)鏈網(wǎng)絡(luò)。這些問(wèn)題往往具有高維度、非線性、時(shí)序依賴或圖結(jié)構(gòu)等特征而這恰恰是神經(jīng)網(wǎng)絡(luò)所擅長(zhǎng)的領(lǐng)域。但關(guān)鍵在于我們不能再把神經(jīng)網(wǎng)絡(luò)當(dāng)作一個(gè)扔進(jìn)去數(shù)據(jù)就萬(wàn)事大吉的“黑箱”。相反我們需要將它視為一個(gè)強(qiáng)大的“函數(shù)逼近器”或“特征提取器”并將其有機(jī)地嵌入到我們對(duì)問(wèn)題的整體數(shù)學(xué)建??蚣苤小_@個(gè)過(guò)程我稱之為從“黑箱”到“白盒”的轉(zhuǎn)變。它要求我們不僅要會(huì)調(diào)用sklearn或TensorFlow的API更要理解網(wǎng)絡(luò)每一層在數(shù)學(xué)上做了什么變換它的輸出如何與我們的微分方程、優(yōu)化目標(biāo)或概率模型相結(jié)合。比如你可以用循環(huán)神經(jīng)網(wǎng)絡(luò)RNN的隱藏狀態(tài)來(lái)刻畫(huà)動(dòng)態(tài)系統(tǒng)中的狀態(tài)變量用圖神經(jīng)網(wǎng)絡(luò)GNN來(lái)顯式地建模實(shí)體間的關(guān)聯(lián)關(guān)系然后用這些網(wǎng)絡(luò)的輸出作為另一個(gè)優(yōu)化模型的輸入或約束條件。這樣神經(jīng)網(wǎng)絡(luò)就成了你數(shù)學(xué)模型的一個(gè)可微分的、可訓(xùn)練的組成部分而不僅僅是最后那個(gè)“預(yù)測(cè)模塊”。這篇文章我就想結(jié)合最新的技術(shù)熱點(diǎn)和競(jìng)賽趨勢(shì)和你深入聊聊如何把神經(jīng)網(wǎng)絡(luò)真正“用對(duì)”、“用好”在數(shù)學(xué)建模中。我們會(huì)避開(kāi)那些空洞的理論直接切入幾個(gè)核心場(chǎng)景面對(duì)時(shí)序預(yù)測(cè)問(wèn)題除了LSTM我們還有什么更輕量的選擇當(dāng)問(wèn)題本質(zhì)是圖結(jié)構(gòu)時(shí)如何用圖卷積網(wǎng)絡(luò)GCN將拓?fù)湫畔⑷谌肽P驮诙嗄繕?biāo)優(yōu)化中神經(jīng)網(wǎng)絡(luò)如何幫助我們逼近復(fù)雜的Pareto前沿我們會(huì)拆解這些網(wǎng)絡(luò)背后的數(shù)學(xué)直覺(jué)并提供可以直接套用到賽題中的代碼骨架和思考框架。目標(biāo)很簡(jiǎn)單讓你下次在賽題中看到“神經(jīng)網(wǎng)絡(luò)”這個(gè)選項(xiàng)時(shí)能清晰地知道它是否適用、該如何設(shè)計(jì)、以及如何向評(píng)委優(yōu)雅地解釋你的模型。2. 前饋神經(jīng)網(wǎng)絡(luò)數(shù)模中基礎(chǔ)的萬(wàn)能函數(shù)逼近器當(dāng)我們談?wù)撋窠?jīng)網(wǎng)絡(luò)時(shí)最基礎(chǔ)、最核心的形態(tài)就是前饋神經(jīng)網(wǎng)絡(luò)也常被稱為多層感知機(jī)。在數(shù)模中它最常見(jiàn)的角色就是解決復(fù)雜的非線性回歸或分類問(wèn)題。你可能覺(jué)得它太“基礎(chǔ)”了但恰恰是這種基礎(chǔ)模型如果理解透徹能解決大部分賽題中“建立輸入到輸出的映射關(guān)系”這一核心需求。2.1 核心數(shù)學(xué)原理從線性組合到非線性激活前饋神經(jīng)網(wǎng)絡(luò)的數(shù)學(xué)本質(zhì)并不神秘。假設(shè)我們有一個(gè)簡(jiǎn)單的三層網(wǎng)絡(luò)輸入層、隱藏層、輸出層。對(duì)于隱藏層的第j個(gè)神經(jīng)元其輸出 \(h_j\) 是\(h_j \sigma(\sum_{i1}^{n} w_{ji}^{(1)} x_i b_j^{(1)})\)這里\(x_i\) 是輸入特征\(w_{ji}^{(1)}\) 是連接輸入i到隱藏神經(jīng)元j的權(quán)重\(b_j^{(1)}\) 是偏置項(xiàng)。最關(guān)鍵的是 \(\sigma(\cdot)\)即激活函數(shù)。如果沒(méi)有它那么無(wú)論堆疊多少層整個(gè)網(wǎng)絡(luò)仍然只能表示線性變換失去了“深度”的意義。激活函數(shù)引入了非線性使得網(wǎng)絡(luò)能夠逼近任意復(fù)雜的連續(xù)函數(shù)這是著名的通用近似定理。在數(shù)模中選擇激活函數(shù)不是隨意的。對(duì)于隱藏層ReLU最常用計(jì)算簡(jiǎn)單能緩解梯度消失問(wèn)題。公式為 \(f(x) max(0, x)\)。它會(huì)讓負(fù)值輸出為0可能導(dǎo)致“神經(jīng)元死亡”。如果你的數(shù)據(jù)經(jīng)過(guò)標(biāo)準(zhǔn)化后可能有正有負(fù)且你擔(dān)心這個(gè)問(wèn)題可以考慮Leaky ReLU。Sigmoid將輸出壓縮到(0,1)之間。過(guò)去常用但現(xiàn)在多用于輸出層做二分類概率輸出。在隱藏層使用容易導(dǎo)致梯度消失。Tanh輸出在(-1,1)之間關(guān)于原點(diǎn)對(duì)稱。在某些情況下比Sigmoid表現(xiàn)更好。對(duì)于輸出層回歸問(wèn)題通常使用線性激活函數(shù)即無(wú)激活讓網(wǎng)絡(luò)直接輸出任意實(shí)數(shù)。二分類問(wèn)題使用Sigmoid將輸出解釋為概率。多分類問(wèn)題使用Softmax確保所有輸出之和為1每個(gè)輸出代表對(duì)應(yīng)類別的概率。在數(shù)模論文中你絕不能只寫(xiě)“我們使用了神經(jīng)網(wǎng)絡(luò)”。你必須說(shuō)明網(wǎng)絡(luò)的結(jié)構(gòu)輸入層維度對(duì)應(yīng)你的特征數(shù)、隱藏層的層數(shù)和每層的神經(jīng)元數(shù)量、以及每層使用的激活函數(shù)。例如“我們構(gòu)建了一個(gè)包含一個(gè)輸入層8個(gè)神經(jīng)元對(duì)應(yīng)8個(gè)特征、兩個(gè)隱藏層分別包含64和32個(gè)神經(jīng)元均使用ReLU激活函數(shù)和一個(gè)輸出層1個(gè)神經(jīng)元使用線性激活的全連接前饋網(wǎng)絡(luò)用于預(yù)測(cè)連續(xù)目標(biāo)變量?!?.2 在數(shù)模中的典型應(yīng)用場(chǎng)景與實(shí)操步驟假設(shè)賽題要求根據(jù)歷史數(shù)據(jù)預(yù)測(cè)某個(gè)經(jīng)濟(jì)指標(biāo)。你的特征可能包括多種宏觀經(jīng)濟(jì)數(shù)據(jù)維度高、可能存在復(fù)雜非線性關(guān)系。這時(shí)前饋神經(jīng)網(wǎng)絡(luò)就是一個(gè)強(qiáng)有力的候選模型。實(shí)操步驟問(wèn)題轉(zhuǎn)化與特征工程這是最重要的一步。將你的預(yù)測(cè)目標(biāo)明確為回歸或分類問(wèn)題。對(duì)輸入特征進(jìn)行標(biāo)準(zhǔn)化或歸一化這對(duì)神經(jīng)網(wǎng)絡(luò)的訓(xùn)練穩(wěn)定性至關(guān)重要。例如使用sklearn.preprocessing.StandardScaler。同時(shí)思考特征之間的交互作用神經(jīng)網(wǎng)絡(luò)雖然能自動(dòng)學(xué)習(xí)但提供一些先驗(yàn)知識(shí)如比率特征、交叉特征可能有助于提升性能和可解釋性。網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計(jì)輸入層神經(jīng)元數(shù)量等于特征維度。隱藏層從簡(jiǎn)單開(kāi)始。一個(gè)經(jīng)驗(yàn)法則是第一隱藏層的神經(jīng)元數(shù)可以在輸入層和輸出層維度之間或采用“金字塔”結(jié)構(gòu)逐層減少。對(duì)于數(shù)模這種數(shù)據(jù)量通常不大的場(chǎng)景1-3個(gè)隱藏層足矣每層神經(jīng)元數(shù)不宜過(guò)多如16, 32, 64以防過(guò)擬合。輸出層根據(jù)問(wèn)題設(shè)定。代碼骨架使用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) # 回歸任務(wù)單輸出 def forward(self, x): x self.relu1(self.fc1(x)) x self.relu2(self.fc2(x)) x self.fc3(x) # 最后一層無(wú)激活函數(shù) return x模型訓(xùn)練與驗(yàn)證損失函數(shù)回歸常用均方誤差MSE分類常用交叉熵?fù)p失。優(yōu)化器Adam是默認(rèn)的、效果良好的選擇。防止過(guò)擬合數(shù)模數(shù)據(jù)量小過(guò)擬合是大敵。務(wù)必使用早停和交叉驗(yàn)證。將數(shù)據(jù)分為訓(xùn)練集和驗(yàn)證集監(jiān)控驗(yàn)證集損失當(dāng)其在連續(xù)多個(gè)epoch不再下降時(shí)停止訓(xùn)練。也可以添加Dropout層。訓(xùn)練代碼骨架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() # 每個(gè)epoch后在驗(yàn)證集上評(píng)估 model.eval() with torch.no_grad(): val_loss ... if val_loss 不再下降: break # 早停結(jié)果分析與論文呈現(xiàn)不僅要給出預(yù)測(cè)精度如RMSE, R2還要進(jìn)行誤差分析。繪制預(yù)測(cè)值 vs 真實(shí)值的散點(diǎn)圖、殘差分布圖。嘗試進(jìn)行簡(jiǎn)單的可解釋性分析例如使用SHAP或LIME庫(kù)如果時(shí)間允許找出哪些輸入特征對(duì)預(yù)測(cè)結(jié)果影響最大。這能極大提升論文的深度。在論文中除了文字描述務(wù)必附上清晰的結(jié)構(gòu)圖。你可以使用torchviz庫(kù)生成計(jì)算圖或者用繪圖工具如draw.io畫(huà)一個(gè)簡(jiǎn)潔的示意圖類似經(jīng)典的“bp神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)圖”并標(biāo)注各層維度。注意在數(shù)模中使用神經(jīng)網(wǎng)絡(luò)一定要和傳統(tǒng)模型如線性回歸、決策樹(shù)做對(duì)比。在論文中建立一個(gè)“消融實(shí)驗(yàn)”或?qū)Ρ缺砀褡C明神經(jīng)網(wǎng)絡(luò)確實(shí)因?yàn)槠浞蔷€性能力而取得了更優(yōu)的效果否則使用它的必要性就會(huì)受到評(píng)委質(zhì)疑。3. 征服序列數(shù)據(jù)超越LSTM的時(shí)序預(yù)測(cè)新思路時(shí)間序列預(yù)測(cè)是數(shù)模競(jìng)賽的常客從股票價(jià)格到流行病傳播從能耗預(yù)測(cè)到交通流量。過(guò)去幾年長(zhǎng)短期記憶網(wǎng)絡(luò)幾乎是時(shí)序預(yù)測(cè)的代名詞。但LSTM及其變體GRU結(jié)構(gòu)相對(duì)復(fù)雜參數(shù)多訓(xùn)練慢在小數(shù)據(jù)集上容易過(guò)擬合。對(duì)于數(shù)模競(jìng)賽這種時(shí)間緊、數(shù)據(jù)量未必巨大的場(chǎng)景我們需要更高效、更穩(wěn)健的工具。3.1 時(shí)序問(wèn)題的本質(zhì)與神經(jīng)網(wǎng)絡(luò)的選擇邏輯時(shí)序預(yù)測(cè)的核心是捕捉序列中的依賴關(guān)系當(dāng)前時(shí)刻的值如何受到過(guò)去多個(gè)時(shí)刻值的影響。這種依賴可能包括趨勢(shì)、周期季節(jié)性和突發(fā)模式。傳統(tǒng)方法如ARIMA有嚴(yán)格的平穩(wěn)性假設(shè)而神經(jīng)網(wǎng)絡(luò)是一種數(shù)據(jù)驅(qū)動(dòng)的、非參數(shù)的方法假設(shè)更少。選擇網(wǎng)絡(luò)結(jié)構(gòu)的邏輯在于你如何理解這種依賴循環(huán)神經(jīng)網(wǎng)絡(luò)顯式地維護(hù)一個(gè)“記憶狀態(tài)”理論上可以捕捉任意長(zhǎng)的依賴。但實(shí)際中LSTM/GRU通過(guò)門(mén)控機(jī)制緩解了梯度消失仍是處理長(zhǎng)序列的有力工具。適用于依賴關(guān)系非常長(zhǎng)且復(fù)雜的場(chǎng)景。一維卷積神經(jīng)網(wǎng)絡(luò)將時(shí)間序列視為一個(gè)一維信號(hào)使用一維卷積核在時(shí)間軸上滑動(dòng)提取局部模式如最近幾個(gè)時(shí)間點(diǎn)的特征。適用于依賴關(guān)系主要是局部性的場(chǎng)景計(jì)算效率遠(yuǎn)高于RNN。注意力機(jī)制與Transformer徹底拋棄了循環(huán)結(jié)構(gòu)完全依賴自注意力機(jī)制來(lái)建立序列中任意兩個(gè)位置之間的關(guān)聯(lián)。在足夠數(shù)據(jù)下它能捕捉非常復(fù)雜的全局依賴。但對(duì)于中小規(guī)模時(shí)序數(shù)據(jù)原版Transformer可能過(guò)于龐大。在2025年的數(shù)模賽題中我特別推薦你關(guān)注一種輕量且強(qiáng)大的結(jié)構(gòu)Temporal Convolutional Network。它結(jié)合了CNN的高效和因果卷積確保預(yù)測(cè)不會(huì)使用未來(lái)信息的特性在許多基準(zhǔn)數(shù)據(jù)集上超越了LSTM且訓(xùn)練速度更快更易于并行化。3.2 TCN實(shí)戰(zhàn)為城市交通流量預(yù)測(cè)建模假設(shè)賽題C是關(guān)于城市交通流量預(yù)測(cè)給出了過(guò)去幾個(gè)月各個(gè)路口每小時(shí)的車流量數(shù)據(jù)。這是一個(gè)典型的多變量時(shí)間序列預(yù)測(cè)問(wèn)題。步驟一問(wèn)題形式化我們需要用過(guò)去N個(gè)小時(shí)如24小時(shí)的所有路口流量數(shù)據(jù)來(lái)預(yù)測(cè)未來(lái)M個(gè)小時(shí)如下一個(gè)小時(shí)的流量。這是一個(gè)“多步預(yù)測(cè)”問(wèn)題。我們可以采用滾動(dòng)預(yù)測(cè)的方式先預(yù)測(cè)t1時(shí)刻再用預(yù)測(cè)值作為輸入的一部分去預(yù)測(cè)t2時(shí)刻或使用Seq2Seq結(jié)構(gòu)。步驟二構(gòu)建TCN模型TCN的核心是因果膨脹卷積。因果確保卷積輸出只依賴于當(dāng)前及過(guò)去的時(shí)間點(diǎn)膨脹則允許卷積核在覆蓋更長(zhǎng)歷史的同時(shí)不增加參數(shù)數(shù)量通過(guò)間隔采樣。import torch import torch.nn as nn from torch.nn.utils import weight_norm class Chomp1d(nn.Module): # 因果卷積后裁剪掉右側(cè)多余的填充 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: 各層卷積的輸出通道數(shù)列表如[25, 25, 25]表示3個(gè)隱層每層25個(gè)通道 super(TCN, self).__init__() layers [] num_levels len(num_channels) for i in range(num_levels): dilation_size 2 ** i # 膨脹系數(shù)指數(shù)增長(zhǎng) 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) # 預(yù)測(cè)未來(lái)一個(gè)時(shí)間步 def forward(self, x): # x shape: (batch_size, seq_len, num_features) - 需要轉(zhuǎn)為 (batch_size, num_features, seq_len) 給Conv1d x x.transpose(1, 2) y self.network(x) # 取最后一個(gè)時(shí)間步的輸出進(jìn)行預(yù)測(cè) y self.linear(y[:, :, -1]) return y步驟三數(shù)據(jù)準(zhǔn)備與訓(xùn)練# 假設(shè)我們有數(shù)據(jù) X: (樣本數(shù), 歷史序列長(zhǎng)度seq_len24, 特征數(shù)num_features路口數(shù)) # 目標(biāo) y: (樣本數(shù), 1) 即下一個(gè)時(shí)刻的總流量或某個(gè)關(guān)鍵路口流量 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) # 訓(xùn)練循環(huán)...步驟四模型對(duì)比與論文寫(xiě)作要點(diǎn)在論文中你需要闡明選擇TCN的理由強(qiáng)調(diào)其因果性、并行計(jì)算效率、以及膨脹卷積在捕捉長(zhǎng)期依賴上的優(yōu)勢(shì)。與基線模型對(duì)比務(wù)必與ARIMA、簡(jiǎn)單的線性回歸、乃至LSTM進(jìn)行對(duì)比在一個(gè)統(tǒng)一的驗(yàn)證集上比較RMSE、MAE等指標(biāo)??梢灾谱饕粋€(gè)對(duì)比表格??梢暬L制真實(shí)流量與TCN預(yù)測(cè)流量的時(shí)序?qū)Ρ葓D。還可以繪制感受野示意圖解釋你的TCN結(jié)構(gòu)通過(guò)膨脹系數(shù)能夠看到多長(zhǎng)的歷史數(shù)據(jù)感受野大小 1 2 * (kernel_size - 1) * (2^層數(shù) -1)這體現(xiàn)了模型的可解釋性。討論局限性例如TCN對(duì)周期性的建??赡懿蝗鐚iT(mén)加入季節(jié)性分量的傳統(tǒng)模型直觀如果數(shù)據(jù)有強(qiáng)季節(jié)性可以考慮將周期性特征如小時(shí)、星期幾作為額外輸入特征加入。實(shí)操心得對(duì)于數(shù)模TCN的超參數(shù)如num_channels,kernel_size,dropout不宜設(shè)置過(guò)多。建議固定kernel_size3或5通過(guò)調(diào)整num_channels如[16,16]或[32,32]和dropout率來(lái)平衡擬合能力與過(guò)擬合風(fēng)險(xiǎn)。使用早停法至關(guān)重要。4. 理解關(guān)系與結(jié)構(gòu)圖卷積網(wǎng)絡(luò)在數(shù)模中的破局應(yīng)用當(dāng)你的賽題數(shù)據(jù)中實(shí)體之間存在著明確的關(guān)系或網(wǎng)絡(luò)結(jié)構(gòu)時(shí)傳統(tǒng)的神經(jīng)網(wǎng)絡(luò)前饋或循環(huán)就力有不逮了。例如2025年賽題C如果涉及社交網(wǎng)絡(luò)信息傳播、交通路網(wǎng)擁堵分析、論文引用網(wǎng)絡(luò)分類、或化學(xué)分子性質(zhì)預(yù)測(cè)其數(shù)據(jù)本質(zhì)是一張圖。每個(gè)節(jié)點(diǎn)用戶、路口、論文、原子有自身的特征節(jié)點(diǎn)之間通過(guò)邊關(guān)注關(guān)系、道路、引用、化學(xué)鍵連接。圖卷積網(wǎng)絡(luò)正是為處理這類非歐幾里得結(jié)構(gòu)化數(shù)據(jù)而生的。4.1 圖卷積的通俗理解從“鄰居投票”到特征傳播你可以把GCN想象成一個(gè)“信息傳播”或“鄰居投票”的過(guò)程。在社交網(wǎng)絡(luò)中要判斷一個(gè)人的興趣除了看他自己的資料看他朋友的興趣也很有幫助。GCN做的就是這件事但它是通過(guò)數(shù)學(xué)來(lái)做的。假設(shè)我們有一張圖可以用鄰接矩陣A表示如果節(jié)點(diǎn)i和j相連則A_ij1否則為0。每個(gè)節(jié)點(diǎn)有一個(gè)特征向量h。最簡(jiǎn)單形式的GCN層操作可以表示為\(H^{(l1)} \sigma(\hat{D}^{-\frac{1}{2}} \hat{A} \hat{D}^{-\frac{1}{2}} H^{(l)} W^{(l)})\)看起來(lái)復(fù)雜我們來(lái)拆解\(\hat{A} A I\)給每個(gè)節(jié)點(diǎn)加上自連接自己也給自己“投票”。\(\hat{D}\) 是 \(\hat{A}\) 的度矩陣對(duì)角矩陣每個(gè)元素表示對(duì)應(yīng)節(jié)點(diǎn)的連接數(shù)。\(\hat{D}^{-\frac{1}{2}} \hat{A} \hat{D}^{-\frac{1}{2}}\) 這一步是對(duì)鄰接矩陣進(jìn)行對(duì)稱歸一化。目的是防止度數(shù)高的節(jié)點(diǎn)在聚合信息時(shí)“聲音”過(guò)大相當(dāng)于給每個(gè)鄰居的“投票”權(quán)重做了標(biāo)準(zhǔn)化。\(H^{(l)}\) 是第l層所有節(jié)點(diǎn)的特征矩陣。\(W^{(l)}\) 是該層可學(xué)習(xí)的權(quán)重矩陣。\(\sigma\) 是非線性激活函數(shù)。這個(gè)過(guò)程在做什么矩陣乘法 \(\hat{A} H^{(l)}\) 實(shí)現(xiàn)了每個(gè)節(jié)點(diǎn)將其鄰居的特征加總過(guò)來(lái)。歸一化操作讓這個(gè)過(guò)程更穩(wěn)定。然后再經(jīng)過(guò)一個(gè)可學(xué)習(xí)的線性變換和非線性激活就得到了節(jié)點(diǎn)新的特征表示 \(H^{(l1)}\)。經(jīng)過(guò)多層這樣的操作每個(gè)節(jié)點(diǎn)的特征就融合了多跳鄰居的信息。4.2 實(shí)戰(zhàn)用GCN分析社交網(wǎng)絡(luò)中的影響力傳播假設(shè)賽題給出了一個(gè)社交網(wǎng)絡(luò)的拓?fù)浣Y(jié)構(gòu)誰(shuí)關(guān)注了誰(shuí)和每個(gè)用戶的初始特征如歷史發(fā)帖關(guān)鍵詞向量要求我們識(shí)別出潛在的“影響力樞紐”節(jié)點(diǎn)或者預(yù)測(cè)某個(gè)信息是否會(huì)在這個(gè)網(wǎng)絡(luò)中大范圍傳播。步驟一圖數(shù)據(jù)構(gòu)建這是最關(guān)鍵的步驟。你需要定義什么是節(jié)點(diǎn)什么是邊。節(jié)點(diǎn)每個(gè)用戶。節(jié)點(diǎn)特征可以是其個(gè)人資料向量、近期發(fā)帖的TF-IDF向量等。邊關(guān)注關(guān)系。注意社交網(wǎng)絡(luò)通常是有向圖A關(guān)注B但B未必關(guān)注A。在GCN中我們常先將其視為無(wú)向圖處理或者使用有向GCN變體。鄰接矩陣A根據(jù)關(guān)注關(guān)系構(gòu)建。節(jié)點(diǎn)標(biāo)簽如果是分類任務(wù)如區(qū)分普通用戶和大V則需要部分節(jié)點(diǎn)的標(biāo)簽。步驟二PyTorch Geometric實(shí)現(xiàn)PyTorch Geometric是處理圖神經(jīng)網(wǎng)絡(luò)的利器極大簡(jiǎn)化了流程。import torch import torch.nn.functional as F from torch_geometric.nn import GCNConv from torch_geometric.data import Data # 1. 準(zhǔn)備數(shù)據(jù) # 假設(shè) node_features 是形狀為 [num_nodes, num_features] 的特征矩陣 # edge_index 是形狀為 [2, num_edges] 的邊列表第一行是源節(jié)點(diǎn)索引第二行是目標(biāo)節(jié)點(diǎn)索引 # labels 是形狀為 [num_nodes] 的標(biāo)簽部分節(jié)點(diǎn)有標(biāo)簽用于半監(jiān)督學(xué)習(xí) data Data(xnode_features, edge_indexedge_index, ylabels) # 劃分訓(xùn)練、驗(yàn)證、測(cè)試掩碼 data.train_mask ... # 布爾張量標(biāo)記訓(xùn)練節(jié)點(diǎn) 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) # 輸出每個(gè)節(jié)點(diǎn)的類別分?jǐn)?shù) return F.log_softmax(x, dim1) # 3. 訓(xùn)練與評(píng)估 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]) # 僅用有標(biāo)簽的訓(xùn)練節(jié)點(diǎn)計(jì)算損失 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})步驟三結(jié)果分析與模型解釋任務(wù)性能在測(cè)試集上報(bào)告分類準(zhǔn)確率、精確率、召回率等??梢暬褂胻-SNE或UMAP將GCN最后一層輸出的節(jié)點(diǎn)嵌入即節(jié)點(diǎn)的最終特征表示降維到2D并可視化用顏色表示預(yù)測(cè)類別或真實(shí)標(biāo)簽。一個(gè)好的GCN模型應(yīng)該能讓同類節(jié)點(diǎn)在嵌入空間聚集。影響力分析雖然GCN本身是一個(gè)分類器但你可以通過(guò)分析節(jié)點(diǎn)的嵌入向量來(lái)評(píng)估其“影響力”。例如計(jì)算所有節(jié)點(diǎn)嵌入的中心度如接近中心性或者觀察那些被模型高置信度分類為“影響力樞紐”的節(jié)點(diǎn)在圖中的結(jié)構(gòu)位置它們往往是連接不同社群的橋梁節(jié)點(diǎn)。傳播預(yù)測(cè)如果要預(yù)測(cè)信息傳播可以將問(wèn)題轉(zhuǎn)化為鏈路預(yù)測(cè)或級(jí)聯(lián)預(yù)測(cè)。例如使用GCN學(xué)習(xí)到的節(jié)點(diǎn)嵌入計(jì)算節(jié)點(diǎn)對(duì)之間的嵌入相似度如余弦相似度作為鏈接存在的可能性。重要提示在數(shù)模論文中解釋GCN模型時(shí)一定要用直觀的語(yǔ)言和示意圖。畫(huà)一張簡(jiǎn)單的圖展示一個(gè)中心節(jié)點(diǎn)如何聚合其鄰居的信息。說(shuō)明你的網(wǎng)絡(luò)層數(shù)通常2-3層足夠因?yàn)檫^(guò)多的層會(huì)導(dǎo)致“過(guò)度平滑”所有節(jié)點(diǎn)的特征趨向一致和每層的含義第一層學(xué)習(xí)直接鄰居特征第二層學(xué)習(xí)兩跳鄰居特征。這能有效化解評(píng)委對(duì)“黑箱”的疑慮。5. 多目標(biāo)優(yōu)化當(dāng)神經(jīng)網(wǎng)絡(luò)遇見(jiàn)帕累托前沿很多數(shù)模優(yōu)化問(wèn)題并非單目標(biāo)而是需要同時(shí)權(quán)衡多個(gè)相互沖突的目標(biāo)。例如在資源調(diào)度中既要成本最低又要時(shí)間最短在產(chǎn)品設(shè)計(jì)中既要性能最強(qiáng)又要重量最輕。這類問(wèn)題的解不是一個(gè)最優(yōu)值而是一個(gè)帕累托最優(yōu)解集集合中的任何一個(gè)解都無(wú)法在改進(jìn)一個(gè)目標(biāo)時(shí)不損害另一個(gè)目標(biāo)。神經(jīng)網(wǎng)絡(luò)在這里可以扮演兩個(gè)關(guān)鍵角色一是作為高效的代理模型來(lái)近似復(fù)雜的目標(biāo)函數(shù)二是直接學(xué)習(xí)并生成帕累托前沿。5.1 神經(jīng)網(wǎng)絡(luò)作為代理模型加速計(jì)算昂貴的優(yōu)化在一些工程優(yōu)化問(wèn)題中目標(biāo)函數(shù)的計(jì)算可能極其昂貴例如需要運(yùn)行一次耗時(shí)的流體動(dòng)力學(xué)仿真才能得到一個(gè)性能指標(biāo)。在優(yōu)化算法如遺傳算法、粒子群算法中需要成千上萬(wàn)次評(píng)估目標(biāo)函數(shù)這直接不可行。此時(shí)我們可以用神經(jīng)網(wǎng)絡(luò)訓(xùn)練一個(gè)代理模型用少量仿真數(shù)據(jù)訓(xùn)練網(wǎng)絡(luò)讓它學(xué)習(xí)從設(shè)計(jì)變量到目標(biāo)值的映射。之后優(yōu)化算法就在這個(gè)快速的代理模型上進(jìn)行評(píng)估大大加速尋優(yōu)過(guò)程。操作流程實(shí)驗(yàn)設(shè)計(jì)使用拉丁超立方采樣等方法在設(shè)計(jì)空間內(nèi)生成一批有代表性的樣本點(diǎn)。昂貴評(píng)估對(duì)這組樣本點(diǎn)運(yùn)行真實(shí)的仿真或?qū)嶒?yàn)得到其目標(biāo)函數(shù)值。訓(xùn)練代理模型為每個(gè)目標(biāo)函數(shù)訓(xùn)練一個(gè)獨(dú)立的前饋神經(jīng)網(wǎng)絡(luò)回歸模型或者一個(gè)多輸出網(wǎng)絡(luò)。輸入是設(shè)計(jì)變量輸出是目標(biāo)值。集成優(yōu)化將訓(xùn)練好的代理模型嵌入到多目標(biāo)優(yōu)化算法如NSGA-II中替代原始昂貴函數(shù)進(jìn)行評(píng)估。驗(yàn)證與更新對(duì)代理模型預(yù)測(cè)的帕累托前沿上的解再進(jìn)行少量真實(shí)評(píng)估驗(yàn)證其準(zhǔn)確性。如果偏差大可以將這些新數(shù)據(jù)加入訓(xùn)練集重新訓(xùn)練代理模型這是一個(gè)主動(dòng)學(xué)習(xí)過(guò)程。這種方法在論文中被稱為“基于代理模型的優(yōu)化”能顯著提升解決復(fù)雜工程優(yōu)化問(wèn)題的可行性。5.2 神經(jīng)網(wǎng)絡(luò)直接生成帕累托前沿Pareto Set Learning另一種更“端到端”的思路是訓(xùn)練一個(gè)神經(jīng)網(wǎng)絡(luò)其輸入是一個(gè)偏好向量或標(biāo)量輸出直接是對(duì)應(yīng)于該偏好的帕累托最優(yōu)解。這個(gè)網(wǎng)絡(luò)被稱為Pareto Set Learner。它的優(yōu)勢(shì)在于一旦訓(xùn)練完成我們可以通過(guò)連續(xù)地改變偏好向量實(shí)時(shí)、平滑地生成整個(gè)帕累托前沿的近似而無(wú)需重新運(yùn)行優(yōu)化算法。核心思想以兩目標(biāo)最小化問(wèn)題為例假設(shè)有兩個(gè)目標(biāo)f1和f2。我們引入一個(gè)偏好標(biāo)量 \(\lambda \in [0, 1]\)。將多目標(biāo)問(wèn)題轉(zhuǎn)化為一個(gè)帶偏好的標(biāo)量化問(wèn)題例如使用加權(quán)切比雪夫方法 \(g(x | \lambda, z^) max{ \lambda |f_1(x) - z_1^|, (1-\lambda) |f_2(x) - z_2^| }\) 其中 \(z^\) 是理想點(diǎn)每個(gè)目標(biāo)單獨(dú)能達(dá)到的最優(yōu)值。對(duì)于每個(gè)固定的 \(\lambda\)求解 \(min_x g(x | \lambda, z^*)\) 可以得到一個(gè)帕累托最優(yōu)解。神經(jīng)網(wǎng)絡(luò)的角色我們訓(xùn)練一個(gè)網(wǎng)絡(luò) \(PSL-Net\)輸入是 \(\lambda\)輸出是解 \(x\)。即 \(x PSL-Net(\lambda; \theta)\)。網(wǎng)絡(luò)的參數(shù) \(\theta\) 通過(guò)優(yōu)化以下?lián)p失函數(shù)來(lái)學(xué)習(xí) \(L(\theta) E_{\lambda \sim U(0,1)}[ g(PSL-Net(\lambda; \theta) | \lambda, z^* ) ]\) 通過(guò)隨機(jī)采樣不同的 \(\lambda\) 并最小化上述損失的期望網(wǎng)絡(luò)就學(xué)會(huì)了覆蓋整個(gè)帕累托前沿的解。簡(jiǎn)易代碼示意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) - 經(jīng)過(guò)一個(gè)評(píng)價(jià)函數(shù)得到目標(biāo)值 # 這里假設(shè)我們有一個(gè)函數(shù)能計(jì)算f1和f2 f1, f2 evaluate_objectives(solution) # 假設(shè)返回都是(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 # 訓(xùn)練循環(huán) model ParetoSetNetwork(solution_dim10) optimizer optim.Adam(model.parameters(), lr1e-3) ideal_point torch.tensor([f1_min, f2_min]) # 需要預(yù)先估計(jì) for epoch in range(epochs): optimizer.zero_grad() lambda_batch torch.rand(batch_size, 1) # 隨機(jī)采樣偏好 solutions model(lambda_batch) loss weighted_chebyshev(solutions, lambda_batch, ideal_point).mean() loss.backward() optimizer.step()訓(xùn)練完成后要生成帕累托前沿只需均勻采樣多個(gè) \(\lambda\) 值輸入網(wǎng)絡(luò)得到一系列解再評(píng)估這些解的真實(shí)目標(biāo)值繪制在目標(biāo)空間即可。在數(shù)模論文中的應(yīng)用要點(diǎn)問(wèn)題適配明確說(shuō)明你的問(wèn)題是一個(gè)多目標(biāo)優(yōu)化問(wèn)題并列出沖突的目標(biāo)。方法選擇理由解釋為什么選擇神經(jīng)網(wǎng)絡(luò)方法例如目標(biāo)函數(shù)復(fù)雜、需要快速得到前沿近似、解空間連續(xù)等。對(duì)比實(shí)驗(yàn)將神經(jīng)網(wǎng)絡(luò)方法無(wú)論是代理模型還是PSL與經(jīng)典多目標(biāo)優(yōu)化算法如NSGA-II在解的質(zhì)量如超體積指標(biāo)和計(jì)算時(shí)間上進(jìn)行對(duì)比。前沿可視化這是最大的亮點(diǎn)。繪制出由神經(jīng)網(wǎng)絡(luò)方法生成的帕累托前沿并與傳統(tǒng)方法生成的前沿進(jìn)行對(duì)比。清晰的二維或三維前沿圖極具說(shuō)服力。決策支持說(shuō)明如何利用這個(gè)前沿進(jìn)行決策。例如決策者可以根據(jù)對(duì)兩個(gè)目標(biāo)的偏好程度即選擇一個(gè) \(\lambda\)直接從網(wǎng)絡(luò)中讀取出對(duì)應(yīng)的最優(yōu)設(shè)計(jì)方案。這體現(xiàn)了模型的實(shí)用價(jià)值。神經(jīng)網(wǎng)絡(luò)在數(shù)模中的應(yīng)用早已超越了簡(jiǎn)單的數(shù)據(jù)擬合。無(wú)論是處理時(shí)序、圖結(jié)構(gòu)還是多目標(biāo)優(yōu)化其核心價(jià)值在于為我們提供了強(qiáng)大的、可微分的建模組件能夠?qū)㈩I(lǐng)域知識(shí)如時(shí)序因果性、圖連接關(guān)系、多目標(biāo)權(quán)衡以數(shù)據(jù)驅(qū)動(dòng)的方式嵌入到數(shù)學(xué)模型中。掌握這些工具并理解其背后的數(shù)學(xué)直覺(jué)和應(yīng)用場(chǎng)景能讓你在面對(duì)復(fù)雜賽題時(shí)擁有更多樣、更犀利的解題武器。關(guān)鍵在于永遠(yuǎn)不要為了用神經(jīng)網(wǎng)絡(luò)而用而是要清楚它在你整個(gè)模型框架中究竟解決了哪個(gè)傳統(tǒng)方法難以處理的子問(wèn)題。