現(xiàn))
物理信息神經(jīng)網(wǎng)絡(luò)PINN入門課程走到第 11 講這一講不寫復(fù)雜算例先把框架選型這件決定后面所有代碼風(fēng)格的事情講清楚。前面的課程已經(jīng)解釋了 PINN 的核心思路把偏微分方程PDE的殘差、邊界條件、初值條件一起塞進(jìn)損失函數(shù)用神經(jīng)網(wǎng)絡(luò)反向傳播去逼近物理系統(tǒng)的解。到了真正寫代碼這一步新手面臨的第一道坎不是方程而是選 PyTorch 還是 TensorFlow。這個(gè)選擇題沒(méi)有標(biāo)準(zhǔn)答案但不同選擇會(huì)直接影響你后續(xù)寫損失函數(shù)、做自動(dòng)微分、跑批量算例、甚至部署到工程環(huán)境的效率。這一講會(huì)把兩個(gè)框架在 PINN 場(chǎng)景下的真實(shí)差異拆開對(duì)比給出可復(fù)制的環(huán)境搭建命令分別用 PyTorch 和 TensorFlow 寫一個(gè)最小可運(yùn)行的 PINN 代碼然后告訴你如何驗(yàn)證訓(xùn)練是否真正收斂、遇到 loss 不下降和梯度異常時(shí)該從哪里排查。讀完這一講你應(yīng)該能根據(jù)自己手里的 GPU、后續(xù)應(yīng)用場(chǎng)景和代碼習(xí)慣做出一個(gè)不后悔的框架選擇。1. 核心能力速覽PINN 代碼本質(zhì)上只需要三個(gè)能力神經(jīng)網(wǎng)絡(luò)前向計(jì)算、自動(dòng)微分求物理殘差、優(yōu)化器更新參數(shù)。兩個(gè)主流框架都具備但使用方式和工程側(cè)重點(diǎn)不同。選型維度PyTorch 方案TensorFlow 方案說(shuō)明自動(dòng)微分方式torch.autograd.grad動(dòng)態(tài)計(jì)算圖tf.GradientTape默認(rèn) Eager 執(zhí)行PINN 需要高階導(dǎo)數(shù)兩者都能實(shí)現(xiàn)寫法差異明顯網(wǎng)絡(luò)構(gòu)建nn.Module子類化Python 風(fēng)格keras層 API 或自定義tf.keras.ModelPyTorch 更貼近 Python 原生習(xí)慣TensorFlow 更偏工程化組裝自定義損失直接寫函數(shù)返回標(biāo)量 tensor 即可繼承tf.keras.Model重寫train_step或用GradientTape手動(dòng)更新PINN 的損失函數(shù)包含 PDE 殘差兩個(gè)框架都支持調(diào)試體驗(yàn)print直接打印中間張量斷點(diǎn)調(diào)試友好2.x 后 Eager 模式也支持但部分 1.x 舊代碼風(fēng)格有遺留新手建議優(yōu)先考慮調(diào)試便利性部署環(huán)境TorchScript / ONNX / TorchServeTensorFlow Serving / Lite / ONNX如果后續(xù)要把 PINN 模型做成接口服務(wù)需要提前考慮學(xué)習(xí)資源PINN 論文附帶的官方代碼很多基于 PyTorch老牌 PINN 庫(kù)和部分工業(yè)案例使用 TensorFlow找到參考代碼的速度決定上手效率從 PINN 入門角度說(shuō)更穩(wěn)妥的建議是如果你過(guò)去沒(méi)寫過(guò)任何深度學(xué)習(xí)代碼優(yōu)先選 PyTorch。它的動(dòng)態(tài)圖和 Python 原生風(fēng)格能讓你把注意力放在“物理?yè)p失怎么寫”上而不是被框架語(yǔ)法絆住。如果你所在團(tuán)隊(duì)已經(jīng)有 TensorFlow 部署鏈路或者后續(xù)要把 PINN 模型接入工業(yè)流水線就選 TensorFlow。2. PINN 為什么必須用框架先回答一個(gè)很多初學(xué)者會(huì)問(wèn)的問(wèn)題PINN 不就是解方程嗎為什么不能自己寫個(gè)普通全連接網(wǎng)絡(luò)普通的神經(jīng)網(wǎng)絡(luò)訓(xùn)練損失函數(shù)一般只依賴模型輸出和標(biāo)簽之間的差值比如交叉熵或均方誤差。但 PINN 的損失函數(shù)里包含對(duì)模型輸出的導(dǎo)數(shù)項(xiàng)。以最簡(jiǎn)單的二維熱傳導(dǎo)方程為例損失函數(shù)要計(jì)算溫度場(chǎng)對(duì)空間坐標(biāo)的二階導(dǎo)數(shù)、對(duì)時(shí)間的導(dǎo)數(shù)然后把方程殘差作為一項(xiàng)加到損失里。這個(gè)需求直接指向深度學(xué)習(xí)框架最核心的能力自動(dòng)微分。你可以手動(dòng)推導(dǎo)導(dǎo)數(shù)表達(dá)式再用有限差分近似但那樣精度低、實(shí)現(xiàn)復(fù)雜而且邊界條件一旦復(fù)雜就基本不可維護(hù)。自動(dòng)微分能把“網(wǎng)絡(luò)輸出對(duì)輸入求導(dǎo)”這件事在每次前向傳播中自動(dòng)完成無(wú)論是二階導(dǎo)、混合偏導(dǎo)還是幾十個(gè)輸出分量一起求導(dǎo)都只需要幾行代碼。PINN 對(duì)框架的訴求可以總結(jié)為三點(diǎn)任意階自動(dòng)微分物理方程里的殘差項(xiàng)通常是高階導(dǎo)框架必須支持連續(xù)求導(dǎo)例如先求一階導(dǎo)再對(duì)一階導(dǎo)求導(dǎo)得到二階導(dǎo)。靈活的自定義損失PINN 的損失由 PDE 殘差、邊界條件、初值條件、數(shù)據(jù)擬合項(xiàng)等組成每項(xiàng)權(quán)重不同框架不能限制你只能使用預(yù)置損失函數(shù)。GPU 加速真實(shí)物理問(wèn)題往往需要成千上萬(wàn)次迭代純 CPU 訓(xùn)練會(huì)很慢框架必須能很方便地把張量運(yùn)算切到 CUDA。PyTorch 和 TensorFlow 都能滿足這三個(gè)訴求差別在于寫起來(lái)順不順手。接下來(lái)的章節(jié)分別演示。3. PyTorch 還是 TensorFlow按場(chǎng)景選3.1 什么時(shí)候選 PyTorch如果你是學(xué)術(shù)研究或課程學(xué)習(xí)場(chǎng)景選擇 PyTorch 更合適。原因是近幾年發(fā)布的 PINN 相關(guān)論文中基于 PyTorch 的參考代碼占比很高。遇到問(wèn)題你很容易在 GitHub 上找到對(duì)應(yīng)實(shí)現(xiàn)把別人的網(wǎng)絡(luò)結(jié)構(gòu)、損失函數(shù)寫法直接拿過(guò)來(lái)改。PyTorch 的調(diào)試體驗(yàn)對(duì)新手非常友好。你可以在任意一行代碼處設(shè)置斷點(diǎn)查看某個(gè)中間張量的形狀和數(shù)值。PINN 訓(xùn)練過(guò)程中經(jīng)常需要檢查某個(gè)物理量殘差的具體數(shù)值這個(gè)特點(diǎn)會(huì)大幅節(jié)省排查時(shí)間。另外PyTorch 的生態(tài)組件對(duì)自定義模型非常友好。torch.utils.data可以做數(shù)據(jù)加載和 batch 劃分torch.optim提供 Adam、L-BFGS 等優(yōu)化器后面如果要做批量物理參數(shù)掃描組合起來(lái)很方便。3.2 什么時(shí)候選 TensorFlow如果團(tuán)隊(duì)已經(jīng)有 TensorFlow 部署基礎(chǔ)設(shè)施或者模型最終要放到服務(wù)端長(zhǎng)期運(yùn)行TensorFlow 的部署鏈路會(huì)更成熟。TensorFlow Serving 對(duì)模型的版本管理、線上更新、并發(fā)請(qǐng)求處理都有完整方案這在工業(yè)場(chǎng)景中比“代碼寫起來(lái)是否順手”更重要。另外TensorFlow 的tf.keras高層 API 封裝程度很高網(wǎng)絡(luò)層定義、訓(xùn)練循環(huán)結(jié)構(gòu)比較固定。如果你只做標(biāo)準(zhǔn)的前饋網(wǎng)絡(luò)擬合物理場(chǎng)用 Keras Sequential API 幾行就能搭完一個(gè)網(wǎng)絡(luò)代碼量看起來(lái)確實(shí)更簡(jiǎn)潔。需要提醒的是TensorFlow 2.x 雖然默認(rèn) Eager 執(zhí)行自定義 PINN 時(shí)會(huì)用到tf.GradientTape和手動(dòng)更新參數(shù)這和 PyTorch 的autograd思考方式有些差異但學(xué)會(huì)之后也能順暢使用。3.3 我的建議這一講給出的結(jié)論是入門階段優(yōu)先選 PyTorch不要在這里過(guò)度糾結(jié)。核心原因是 PINN 學(xué)習(xí)過(guò)程本身就是不斷修改損失函數(shù)和網(wǎng)絡(luò)結(jié)構(gòu)來(lái)對(duì)照物理現(xiàn)象的過(guò)程PyTorch 的動(dòng)態(tài)圖和 Python 風(fēng)格能讓你用最低的認(rèn)知成本完成這些事情。等真正進(jìn)入工程項(xiàng)目如果框架滿足不了性能或部署需求再考慮遷移到 TensorFlow 或其他推理框架。學(xué)習(xí)階段的代碼遷移成本不高因?yàn)槲锢頁(yè)p失的計(jì)算邏輯是通用的換框架只需要重寫網(wǎng)絡(luò)和求導(dǎo)部分。4. 本地部署環(huán)境準(zhǔn)備無(wú)論選哪個(gè)框架先準(zhǔn)備好 Python 環(huán)境和 GPU 環(huán)境。下面給出通用步驟適用于 Windows 和 Linux具體版本號(hào)請(qǐng)以官方文檔為準(zhǔn)。4.1 創(chuàng)建獨(dú)立虛擬環(huán)境PINN 學(xué)習(xí)中會(huì)頻繁安裝和更新依賴強(qiáng)烈建議使用虛擬環(huán)境隔離不要直接裝到系統(tǒng) Python 里。# 使用 conda 創(chuàng)建 Python 3.10 環(huán)境 conda create -n pinn python3.10 conda activate pinn如果不使用 conda用 venv 也可以python -m venv pinn_env source pinn_env/bin/activate4.2 安裝 PyTorchPyTorch 的安裝命令需要根據(jù)你的操作系統(tǒng)、CUDA 版本和是否使用 GPU 來(lái)選擇建議直接訪問(wèn) PyTorch 官網(wǎng)獲取對(duì)應(yīng)命令。一個(gè)通用模板如下# CPU 版本 pip install torch # GPU 版本示例實(shí)際安裝命令以官網(wǎng)選擇為準(zhǔn) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121注意在命令行直接運(yùn)行pip install torch默認(rèn)安裝的是 PyTorch 官網(wǎng)的預(yù)編譯包CPU 版和 GPU 版的差別在安裝后可以通過(guò)torch.cuda.is_available()驗(yàn)證。import torch print(torch.__version__) print(torch.cuda.is_available())如果輸出False說(shuō)明當(dāng)前環(huán)境沒(méi)有可用的 CUDA訓(xùn)練時(shí)只能走 CPU 路徑。4.3 安裝 TensorFlowTensorFlow 同樣分為 CPU 版和 GPU 版。安裝前確認(rèn)你的顯卡驅(qū)動(dòng)支持 CUDA 版本一個(gè)通用模板如下# CPU 版本 pip install tensorflow # GPU 版本通過(guò)官方 pip 源安裝 pip install tensorflow安裝完成后同樣需要驗(yàn)證 GPU 是否可用import tensorflow as tf print(tf.__version__) print(tf.config.list_physical_devices(GPU))如果 GPU 列表為空說(shuō)明 TensorFlow 沒(méi)有識(shí)別到 GPU需要檢查驅(qū)動(dòng)和 CUDA 工具包版本。4.4 硬件與磁盤PINN 訓(xùn)練對(duì) GPU 顯存的要求與網(wǎng)絡(luò)規(guī)模和批大小有關(guān)。入門階段用全連接網(wǎng)絡(luò)、每層 20 到 64 個(gè)神經(jīng)元、批大小 128 左右時(shí)顯存占用并不高很多集成顯卡或低端獨(dú)立顯卡也能運(yùn)行。但要注意如果做高維 PDE 或大批量訓(xùn)練顯存占用會(huì)快速上升。這不是框架本身的問(wèn)題而是自動(dòng)微分需要保存反向傳播所需的中間張量。降低顯存占用的通用辦法是減小 batch size、減少網(wǎng)絡(luò)層數(shù)、降低輸入分辨率或使用混合精度訓(xùn)練。磁盤空間方面Python 環(huán)境加兩個(gè)框架包大約需要 3 到 5 GB如果包含 CUDA 工具包會(huì)更多。建議為訓(xùn)練實(shí)驗(yàn)單獨(dú)準(zhǔn)備一個(gè)數(shù)據(jù)目錄把輸入數(shù)據(jù)、模型權(quán)重和輸出結(jié)果分目錄管理。5. 用 PyTorch 寫一個(gè)最小 PINN下面用一維泊松方程作為示例展示 PyTorch 中 PINN 的完整代碼結(jié)構(gòu)。方程形式為[ -u(x) \pi^2 \sin(\pi x), \quad x \in [0, 1] ]邊界條件為 ( u(0)0, u(1)0 )精確解為 ( u(x)\sin(\pi x) )。PINN 的損失由兩部分組成方程殘差損失和邊界條件損失。import torch import torch.nn as nn # 定義網(wǎng)絡(luò)結(jié)構(gòu) class PINN(nn.Module): def __init__(self): super().__init__() self.net nn.Sequential( nn.Linear(1, 20), nn.Tanh(), nn.Linear(20, 20), nn.Tanh(), nn.Linear(20, 1) ) def forward(self, x): return self.net(x) # 初始化模型和優(yōu)化器 model PINN() optimizer torch.optim.Adam(model.parameters(), lr1e-3) # 計(jì)算方程殘差損失 def pde_loss(x): x.requires_grad_(True) u model(x) # 一階導(dǎo) u_x torch.autograd.grad(u, x, grad_outputstorch.ones_like(u), create_graphTrue)[0] # 二階導(dǎo) u_xx torch.autograd.grad(u_x, x, grad_outputstorch.ones_like(u_x), create_graphTrue)[0] # 方程右端項(xiàng) f torch.pi**2 * torch.sin(torch.pi * x) # 方程殘差 residual -u_xx - f return torch.mean(residual**2) # 邊界條件損失 def boundary_loss(): x_left torch.zeros((100, 1), requires_gradFalse) x_right torch.ones((100, 1), requires_gradFalse) u_left model(x_left) u_right model(x_right) return torch.mean(u_left**2) torch.mean(u_right**2) # 訓(xùn)練循環(huán) n_iter 5000 for it in range(n_iter): optimizer.zero_grad() # 內(nèi)部配置點(diǎn)用于計(jì)算方程殘差 x_collocation torch.rand((256, 1)) # 在 [0,1] 內(nèi)采樣 loss_pde pde_loss(x_collocation) loss_bc boundary_loss() # 加權(quán)組合 loss loss_pde loss_bc loss.backward() optimizer.step() if it % 500 0: print(fIter {it}, Loss: {loss.item():.6f})這段代碼的關(guān)鍵點(diǎn)有三個(gè)requires_grad_(True)讓輸入張量參與自動(dòng)微分這樣神經(jīng)網(wǎng)絡(luò)輸出才能對(duì)輸入求梯度。torch.autograd.grad中的create_graphTrue表示允許對(duì)梯度再求梯度這是計(jì)算二階導(dǎo)的必要條件。邊界條件通過(guò)直接輸入x0和x1的采樣點(diǎn)來(lái)約束模型輸出。只有一階導(dǎo)的方程create_graph可以設(shè)置為 False需要二階或更高階導(dǎo)數(shù)時(shí)必須保留計(jì)算圖。6. 用 TensorFlow 寫一個(gè)最小 PINNTensorFlow 版本使用GradientTape完成相同的計(jì)算。import tensorflow as tf # 定義網(wǎng)絡(luò) class PINN(tf.keras.Model): def __init__(self): super().__init__() self.dense1 tf.keras.layers.Dense(20, activationtanh) self.dense2 tf.keras.layers.Dense(20, activationtanh) self.dense3 tf.keras.layers.Dense(1) def call(self, x): x self.dense1(x) x self.dense2(x) return self.dense3(x) model PINN() optimizer tf.keras.optimizers.Adam(learning_rate1e-3) # 計(jì)算方程殘差損失 def pde_loss(x): with tf.GradientTape(persistentTrue) as tape: tape.watch(x) u model(x) u_x tape.gradient(u, x) u_xx tape.gradient(u_x, x) f tf.constant(tf.math.pi**2, dtypetf.float32) * tf.sin(tf.constant(tf.math.pi, dtypetf.float32) * x) residual -u_xx - f return tf.reduce_mean(tf.square(residual)) # 訓(xùn)練循環(huán) for it in range(5000): with tf.GradientTape() as tape: x_collocation tf.random.uniform((256, 1), minval0.0, maxval1.0) # 方程殘差損失 loss_pde pde_loss(x_collocation) # 邊界條件損失 x_left tf.zeros((100, 1)) x_right tf.ones((100, 1)) loss_bc tf.reduce_mean(tf.square(model(x_left))) tf.reduce_mean(tf.square(model(x_right))) loss loss_pde loss_bc grads tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(grads, model.trainable_variables)) if it % 500 0: print(fIter {it}, Loss: {loss.numpy():.6f})TensorFlow 版本的差異點(diǎn)tf.GradientTape(persistentTrue)允許重復(fù)調(diào)用多次梯度操作。求完一階導(dǎo)再求二階導(dǎo)時(shí)如果用普通GradientTape需要在同一個(gè)上下文內(nèi)完成全部計(jì)算。tf.random.uniform生成采樣點(diǎn)張量默認(rèn)參與自動(dòng)微分但通過(guò)tape.watch(x)顯式監(jiān)聽輸入張量。參數(shù)更新需要手動(dòng)apply_gradients這一步在 PyTorch 里對(duì)應(yīng)optimizer.step()。從代碼量看兩個(gè)框架差別不大。真正影響體驗(yàn)的是你對(duì)哪種寫法的直覺(jué)更接近。PyTorch 的tensor.grad和autograd更透明TensorFlow 的GradientTape更強(qiáng)調(diào)作用域。7. PINN 典型問(wèn)題測(cè)試與結(jié)果驗(yàn)證寫完最小代碼后下一步是驗(yàn)證訓(xùn)練是否真的收斂到了物理上正確的解。7.1 用精確解對(duì)照上面的泊松方程有解析解 ( u(x)\sin(\pi x) )。訓(xùn)練結(jié)束后在 [0,1] 上均勻取 100 個(gè)點(diǎn)對(duì)比網(wǎng)絡(luò)輸出和解析解import numpy as np import torch # PyTorch 對(duì)比示例 model.eval() x_test torch.linspace(0, 1, 100).reshape(-1, 1) u_pred model(x_test).detach().numpy().ravel() u_true np.sin(np.pi * x_test.numpy().ravel()) # 計(jì)算最大誤差和均方誤差 error np.abs(u_pred - u_true) print(fMax error: {error.max():.2e}) print(fRMSE: {np.sqrt(np.mean(error**2)):.2e})一般來(lái)說(shuō)迭代到后期最大誤差降到 ( 10^{-2} ) 到 ( 10^{-3} ) 量級(jí)說(shuō)明模型已經(jīng)學(xué)習(xí)到了方程的主要特征。如果一直停留在 ( 10^{-1} ) 以上需要檢查網(wǎng)絡(luò)層數(shù)、激活函數(shù)、采樣點(diǎn)數(shù)和迭代次數(shù)。7.2 觀察損失曲線的不同階段PINN 訓(xùn)練中損失曲線通常不會(huì)像圖像分類那樣平滑下降。物理殘差和邊界條件損失在初始階段權(quán)重不同可能出現(xiàn)以下幾個(gè)現(xiàn)象邊界條件損失快速下降但 PDE 殘差損失下降緩慢。這說(shuō)明網(wǎng)絡(luò)優(yōu)先擬合了邊界內(nèi)部物理約束還沒(méi)學(xué)透??梢赃m當(dāng)增大迭代次數(shù)或調(diào)整兩項(xiàng)損失的權(quán)重。PDE 殘差下降到某個(gè)值后不再變化。此時(shí)不一定是代碼寫錯(cuò)了而是網(wǎng)絡(luò)容量或采樣點(diǎn)密度不足。嘗試加深網(wǎng)絡(luò)、增加采樣點(diǎn)或者切換到 L-BFGS 這類二階優(yōu)化器。訓(xùn)練后期損失出現(xiàn)周期性波動(dòng)。這是配置點(diǎn)每次重新采樣導(dǎo)致的屬正?,F(xiàn)象。更穩(wěn)定的做法是把配置點(diǎn)固定并進(jìn)行較多次迭代或者使用帶重置策略的采樣方法。7.3 判斷收斂的物理準(zhǔn)則PINN 訓(xùn)練不僅看 Loss 數(shù)值更要看預(yù)測(cè)解是否滿足物理規(guī)律。以熱傳導(dǎo)方程為例預(yù)測(cè)的溫度場(chǎng)不應(yīng)該出現(xiàn)局部突變或違背能量守恒。因此測(cè)試時(shí)應(yīng)增加一組物理約束驗(yàn)證檢查預(yù)測(cè)值的單調(diào)性、極值位置、邊界值誤差。如果預(yù)測(cè)結(jié)果在某些區(qū)域明顯偏離物理直覺(jué)優(yōu)先懷疑配置點(diǎn)分布是否覆蓋了這些區(qū)域。PINN 以配置點(diǎn)方式離散物理域配置點(diǎn)稀疏的地方網(wǎng)絡(luò)學(xué)習(xí)到的物理約束就弱。8. 資源占用與性能觀察PINN 訓(xùn)練的資源占用沒(méi)有固定數(shù)字因?yàn)樗c網(wǎng)絡(luò)大小、批量大小、方程維度和自動(dòng)微分階數(shù)直接相關(guān)。不過(guò)可以給出通用的觀察和調(diào)優(yōu)思路。8.1 如何觀察顯存和內(nèi)存占用訓(xùn)練過(guò)程中可以用系統(tǒng)自帶的nvidia-smi命令查看 GPU 顯存占用或者使用watch -n 1 nvidia-smi持續(xù)刷新。在 Python 內(nèi)部也可以用torch.cuda.memory_allocated()獲取當(dāng)前顯存占用。print(torch.cuda.memory_allocated() / 1024**2, MB)如果顯存不足優(yōu)先減少 batch size。PINN 使用隨機(jī)采樣batch size 從 256 降到 128 幾乎不影響物理規(guī)律學(xué)習(xí)反而可能讓單次迭代的穩(wěn)定性提升。8.2 CPU 和 GPU 訓(xùn)練差異PINN 入門代碼在沒(méi)有 GPU 的環(huán)境中也能跑起來(lái)只是訓(xùn)練速度慢。CPU 訓(xùn)練 5000 次迭代可能在幾分鐘到十幾分鐘GPU 訓(xùn)練通常能在幾秒到幾十秒內(nèi)完成。差異主要來(lái)自矩陣運(yùn)算的并行度和自動(dòng)微分構(gòu)建計(jì)算圖的開銷。如果你暫時(shí)沒(méi)有 GPU優(yōu)先用小網(wǎng)絡(luò)小采樣點(diǎn)跑通流程。但要注意最后的效果驗(yàn)證部分必須基于真實(shí)訓(xùn)練結(jié)果不能只用小采樣點(diǎn)數(shù)量“硬推”出物理規(guī)律。8.3 如何降低顯存占用幾個(gè)常見手段減少網(wǎng)絡(luò)層數(shù)和每層神經(jīng)元數(shù)。降低每個(gè) iteration 的采樣點(diǎn)數(shù)量。使用混合精度訓(xùn)練例如 PyTorch 的torch.autocast。清理不再使用的中間張量例如del u_x, u_xx; torch.cuda.empty_cache()。這些手段在入門階段不一定都需要但它們能幫助你理解 PINN 的資源瓶頸在哪里后續(xù)做高維問(wèn)題時(shí)直接用得上。9. 常見問(wèn)題與排查方法PINN 訓(xùn)練中的問(wèn)題很多下面列出最常遇到的幾類。問(wèn)題現(xiàn)象可能原因排查方式解決方案安裝框架后import torch報(bào)錯(cuò)環(huán)境類型不匹配、Python 版本不兼容檢查 Python 版本和 pip 安裝源重新創(chuàng)建虛擬環(huán)境按官方安裝命令安裝torch.cuda.is_available()返回 FalseCUDA 驅(qū)動(dòng)版本過(guò)低或 PyTorch 裝成 CPU 版運(yùn)行nvidia-smi查看驅(qū)動(dòng)版本安裝與驅(qū)動(dòng)匹配的 CUDA 版 PyTorchTensorFlow 識(shí)別不到 GPUCUDA、cuDNN 版本與 TensorFlow 版本不匹配運(yùn)行tf.config.list_physical_devices(GPU)參照官方 GPU 支持矩陣安裝對(duì)應(yīng)版本訓(xùn)練時(shí) loss 不下降學(xué)習(xí)率過(guò)大或過(guò)小、網(wǎng)絡(luò)結(jié)構(gòu)不合理、損失函數(shù)權(quán)重失衡打印各分項(xiàng)損失數(shù)值調(diào)小學(xué)習(xí)率、調(diào)整損失權(quán)重、加大采樣點(diǎn)數(shù)二階導(dǎo)計(jì)算結(jié)果異常create_graph參數(shù)錯(cuò)誤或采樣點(diǎn)超出定義域打印中間梯度值比較檢查create_graphTrue是否設(shè)置訓(xùn)練后期 loss 波動(dòng)大配置點(diǎn)隨機(jī)采樣導(dǎo)致梯度噪聲觀察波動(dòng)幅度固定配置點(diǎn)或增大 batch size預(yù)測(cè)邊界值偏差大邊界條件權(quán)重太低檢查邊界損失數(shù)值提高邊界條件損失權(quán)重模型在局部區(qū)域預(yù)測(cè)異常配置點(diǎn)稀疏可視化采樣點(diǎn)分布該區(qū)域加密采樣點(diǎn)針對(duì)“訓(xùn)練時(shí) loss 不下降”這個(gè)最常見問(wèn)題一個(gè)有效的排查思路是先把物理?yè)p失去掉只保留邊界條件損失看模型是否能學(xué)會(huì)邊界值。如果能學(xué)會(huì)再逐步加回物理殘差定位是哪一項(xiàng)導(dǎo)致數(shù)值不穩(wěn)定。10. 框架學(xué)習(xí)路徑與工程實(shí)踐建議選框架只是起點(diǎn)真正決定 PINN 學(xué)習(xí)進(jìn)度的是后面幾個(gè)習(xí)慣。第一建議把“最小可運(yùn)行代碼”保存下來(lái)。后續(xù)所有更復(fù)雜的算例都在這份代碼基礎(chǔ)上修改網(wǎng)絡(luò)、損失函數(shù)和數(shù)據(jù)加載邏輯。不要每次從零開始寫。第二訓(xùn)練過(guò)程中要有記錄意識(shí)。每次修改網(wǎng)絡(luò)結(jié)構(gòu)、采樣點(diǎn)數(shù)或?qū)W習(xí)率后記錄 loss 曲線和最終預(yù)測(cè)誤差并保留模型權(quán)重文件。這樣能準(zhǔn)確判斷哪個(gè)改動(dòng)帶來(lái)了實(shí)際效果而不是靠感覺(jué)調(diào)參。第三批量實(shí)驗(yàn)時(shí)要做好任務(wù)隊(duì)列。PINN 經(jīng)常需要掃描多個(gè)物理參數(shù)例如擴(kuò)散系數(shù)、邊界溫度、材料屬性等??梢韵葘懸粋€(gè)參數(shù)列表循環(huán)創(chuàng)建不同實(shí)驗(yàn)?zāi)夸浢總€(gè)目錄下保存對(duì)應(yīng)配置和模型輸出。接口調(diào)用層面如果后面要把訓(xùn)練好的 PINN 模型封裝成服務(wù)優(yōu)先考慮 ONNX 導(dǎo)出或框架自帶的 serving 方案這樣其他程序可以通過(guò)統(tǒng)一接口訪問(wèn)模型。第四合規(guī)問(wèn)題需要從一開始就重視。如果使用實(shí)驗(yàn)數(shù)據(jù)、仿真數(shù)據(jù)或任何第三方數(shù)據(jù)集務(wù)必確認(rèn)數(shù)據(jù)來(lái)源合法、具備使用權(quán)。涉及真實(shí)工業(yè)生產(chǎn)數(shù)據(jù)、人體相關(guān)數(shù)據(jù)或受版權(quán)保護(hù)的材料時(shí)必須做匿名化和授權(quán)合規(guī)處理。PINN 的應(yīng)用場(chǎng)景越多數(shù)據(jù)合規(guī)的邊界就越重要。第五不要盲目使用最新版本框架。對(duì)于 PINN 學(xué)習(xí)穩(wěn)定性和生態(tài)兼容性比新功能更重要。熱門框架版本升級(jí)后自動(dòng)微分 API 或部署工具鏈可能發(fā)生變動(dòng)優(yōu)先選擇文檔較為成熟、周圍同學(xué)或同事用得多的版本。11. 這一講之后第 12 講方向本講已經(jīng)完成框架選型和最小代碼驗(yàn)證。接下來(lái)第 12 講會(huì)繼續(xù)深入 PINN 的損失函數(shù)權(quán)重配置、激活函數(shù)選擇以及邊界條件的標(biāo)準(zhǔn)化處理這些都是實(shí)際訓(xùn)練中直接影響收斂速度和精度的細(xì)節(jié)。建議你先動(dòng)手跑一遍本講的代碼把 PyTorch 和 TensorFlow 兩個(gè)版本都運(yùn)行一次對(duì)比兩者的 loss 下降速度。通過(guò)這個(gè)對(duì)比你才能真正理解框架選擇對(duì)你編程習(xí)慣和調(diào)試效率的影響。選擇 PyTorch 還是 TensorFlow答案不在別人嘴里在你自己的運(yùn)行結(jié)果里。