
课程摘要上一节通过Stacking组合多个机器学习模型本节进一步学习能够自动构造非线性特征的神经网络。课程以悬臂梁最大弯曲应力预测为案例讲解神经元、权重、偏置、激活函数、网络层、前向传播、损失函数和反向传播并完成数据标准化、MLP训练、验证集早停和独立测试。学习者将理解神经网络“如何预测、怎样学习、如何判断可靠”为后续CNN、LSTM、Transformer和PINN课程建立基础。一、承接第十三节为什么继续学习神经网络第十三节使用Ridge、随机森林、梯度提升和RBF-SVR构建了Stacking模型其基本思想是\[ \text{多个基模型的预测} \longrightarrow \text{元学习器} \longrightarrow \text{最终预测} \]Stacking的优势是综合已有模型但每个基模型仍需人工选择。面对应力场、位移场、裂纹图像和瞬态响应等高维问题传统模型会遇到三个困难输入可能包含成千上万个网格节点或像素几何、载荷和材料之间存在复杂非线性耦合很难完全依靠人工设计特征。神经网络可以在训练过程中自动构造中间特征\[ \text{原始输入} \longrightarrow \text{多层特征变换} \longrightarrow \text{力学响应} \]本节先从最基本的多层感知机开始。后续的CNN、LSTM、Transformer和PINN本质上都建立在神经元、激活函数、前向传播与反向传播之上。二、本节学习目标完成本节后学习者应能够解释神经元中权重和偏置的作用理解激活函数为什么能够引入非线性区分输入层、隐藏层和输出层说清楚前向传播、损失计算和反向传播的关系使用MLP预测悬臂梁最大弯曲应力正确划分训练集、验证集和测试集查看训练曲线、预测散点图和残差图认识神经网络在力学预测中的能力边界。三、从一个神经元开始3.1 神经元的计算过程设神经元接收四个标准化后的力学参数\[ \tilde{\boldsymbol{x}} \begin{bmatrix} \tilde{F}\\ \tilde{L}\\ \tilde{b}\\ \tilde{h} \end{bmatrix} \]其中\(F\)载荷\(L\)梁长\(b\)截面宽度\(h\)截面高度。神经元首先进行加权求和\[ z w_1\tilde{F} w_2\tilde{L} w_3\tilde{b} w_4\tilde{h} c \]式中\(w_1,w_2,w_3,w_4\) 为权重\(c\) 为偏置\(z\) 为神经元的线性输入。这里用 \(c\) 表示偏置避免与截面宽度 \(b\) 混淆。随后神经元通过激活函数得到输出\[ a\phi(z) \]因此一个神经元包含两个步骤\[ \boxed{ \text{加权求和} \longrightarrow \text{激活函数} } \]3.2 一个可以手算的例子假设输入为\[ \tilde{\boldsymbol{x}} \begin{bmatrix} 10-10.5 \end{bmatrix}^{\mathrm T} \]权重和偏置为\[ \boldsymbol{w} \begin{bmatrix} 0.40.2-0.3-0.6 \end{bmatrix}^{\mathrm T} \]\[ c0.1 \]则加权求和结果为\[ \begin{aligned} z 0.4\times1 0.2\times0 (-0.3)\times(-1)\\ \quad(-0.6)\times0.5 0.1\\ 0.5 \end{aligned} \]如果使用Tanh激活函数\[ a\tanh(0.5)\approx0.4621 \]这里的 \(0.4621\) 是神经元产生的中间特征值不直接代表应力或位移。四、为什么必须使用激活函数假设一个两层网络没有激活函数\[ \boldsymbol{a}^{(1)} \boldsymbol{W}^{(1)}\boldsymbol{x} \boldsymbol{c}^{(1)} \]\[ \hat{\boldsymbol{y}} \boldsymbol{W}^{(2)}\boldsymbol{a}^{(1)} \boldsymbol{c}^{(2)} \]将第一式代入第二式\[ \hat{\boldsymbol{y}} \boldsymbol{W}^{(2)} \boldsymbol{W}^{(1)} \boldsymbol{x} \boldsymbol{W}^{(2)} \boldsymbol{c}^{(1)} \boldsymbol{c}^{(2)} \]无论叠加多少层最终仍然是关于输入的线性函数。激活函数可以打破这种线性关系使网络能够学习应力与梁高之间的平方反比关系材料进入塑性后的非线性响应裂纹扩展的突变趋势接触状态改变产生的分段响应多种材料参数和边界条件的耦合关系。五、常用激活函数5.1 ReLU函数\[ \operatorname{ReLU}(z)\max(0,z) \]当 \(z0\) 时\[ \operatorname{ReLU}(z)0 \]当 \(z\geq0\) 时\[ \operatorname{ReLU}(z)z \]ReLU计算简单在深层网络和CNN中使用非常广泛。5.2 Tanh函数\[ \tanh(z) \frac{e^z-e^{-z}}{e^ze^{-z}} \]输出范围为\[ -1\tanh(z)1 \]Tanh连续、平滑在某些平滑力学响应和物理信息神经网络中较常见。【正文插图1ReLU与Tanh激活函数】需要注意隐藏层使用Tanh并不意味着最终预测应力只能在 \(-1\) 到 \(1\) MPa之间。回归网络的输出层通常使用线性函数标准化后的结果还会被恢复为原来的应力单位。六、从神经元组成多层感知机多个神经元可以组成一层多层神经元连接后形成多层感知机即MLP。本节采用的网络结构为\[ 4 \longrightarrow 32 \longrightarrow 32 \longrightarrow 1 \]它表示网络层神经元数量作用输入层4接收 \(F,L,b,h\)第一隐藏层32提取初级非线性特征第二隐藏层32组合更复杂的特征输出层1预测最大弯曲应力需要强调的是普通神经网络的隐藏神经元通常没有明确的物理名称。不能直接断言某个神经元代表弯矩另一个神经元代表惯性矩。6.1 网络参数量输入层到第一隐藏层\[ 4\times3232160 \]第一隐藏层到第二隐藏层\[ 32\times32321056 \]第二隐藏层到输出层\[ 32\times1133 \]总参数量为\[ 1601056331249 \]也就是说这个看起来并不大的网络已经包含1249个需要从数据中学习的参数。七、神经网络如何完成预测对于一个样本第一隐藏层计算\[ \boldsymbol{a}^{(1)} \tanh \left( \boldsymbol{W}^{(1)} \tilde{\boldsymbol{x}} \boldsymbol{c}^{(1)} \right) \]第二隐藏层计算\[ \boldsymbol{a}^{(2)} \tanh \left( \boldsymbol{W}^{(2)} \boldsymbol{a}^{(1)} \boldsymbol{c}^{(2)} \right) \]输出层计算\[ \hat{\tilde{\sigma}} \boldsymbol{W}^{(3)} \boldsymbol{a}^{(2)} c^{(3)} \]这一过程称为前向传播\[ \boxed{ \text{输入} \longrightarrow \text{隐藏层1} \longrightarrow \text{隐藏层2} \longrightarrow \text{预测结果} } \]前向传播只负责使用当前参数完成预测还没有修改网络参数。八、神经网络如何学习8.1 计算损失对于回归问题可以使用均方误差\[ \mathcal{L}_{\mathrm{data}} \frac{1}{N} \sum_{i1}^{N} \left( \hat{\tilde{\sigma}}_i - \tilde{\sigma}_i \right)^2 \]损失越小说明预测值整体越接近目标值。为了抑制过大的权重还可以加入L2正则化\[ \mathcal{L} \mathcal{L}_{\mathrm{data}} \alpha \sum_l \left\| \boldsymbol{W}^{(l)} \right\|_2^2 \]其中 \(\alpha\) 控制正则化强度。8.2 反向传播反向传播利用链式法则计算\[ \frac{\partial\mathcal{L}} {\partial\boldsymbol{W}^{(l)}} \]以及\[ \frac{\partial\mathcal{L}} {\partial\boldsymbol{c}^{(l)}} \]它回答的问题是某个权重发生微小变化时预测误差将怎样变化8.3 参数更新得到梯度后优化器更新参数\[ \boldsymbol{W}_{t1} \boldsymbol{W}_t - \eta \frac{\partial\mathcal{L}} {\partial\boldsymbol{W}_t} \]其中 \(\eta\) 是学习率。完整训练循环为\[ \boxed{ \text{前向预测} \rightarrow \text{计算损失} \rightarrow \text{反向传播} \rightarrow \text{更新参数} } \]反向传播负责计算梯度Adam等优化器负责根据梯度更新参数两者不是同一个概念。九、实战项目悬臂梁最大应力预测9.1 力学模型矩形截面悬臂梁自由端承受集中载荷 \(F\)。固定端弯矩为\[ MFL \]截面惯性矩为\[ I\frac{bh^3}{12} \]截面最外缘距离中性轴\[ c\frac{h}{2} \]最大弯曲正应力为\[ \sigma_{\max} \frac{Mc}{I} \frac{6FL}{bh^2} \]当载荷使用N、尺寸使用mm时\[ 1\ \mathrm{N/mm^2}1\ \mathrm{MPa} \]9.2 数据范围生成1000组教学数据参数范围载荷 \(F\)1050 N梁长 \(L\)300600 mm梁宽 \(b\)1530 mm梁高 \(h\)1020 mm目标数据为\[ \sigma_{\mathrm{target}} \frac{6FL}{bh^2} \varepsilon \]其中\[ \varepsilon \sim \mathcal{N}(0,0.40^2) \]这里加入小幅可重复扰动用于模拟含噪声数据的训练过程。本节数据来自解析公式并非真实有限元计算结果。十、准备数据from copy import deepcopy import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neural_network import MLPRegressor from sklearn.linear_model import Ridge from sklearn.metrics import ( mean_squared_error, mean_absolute_error, r2_score ) def rmse(y_true, y_pred): return float( np.sqrt(mean_squared_error(y_true, y_pred)) ) rng np.random.default_rng(42) n_samples 1000 F rng.uniform(10.0, 50.0, n_samples) L rng.uniform(300.0, 600.0, n_samples) b rng.uniform(15.0, 30.0, n_samples) h rng.uniform(10.0, 20.0, n_samples) sigma_theory 6.0 * F * L / (b * h**2) sigma_target ( sigma_theory rng.normal(0.0, 0.40, n_samples) ) features [ load_N, length_mm, width_mm, height_mm ] X pd.DataFrame({ load_N: F, length_mm: L, width_mm: b, height_mm: h })十一、划分训练集、验证集和测试集X_dev, X_test, y_dev, y_test train_test_split( X, sigma_target, test_size0.20, random_state42 ) X_train, X_val, y_train, y_val train_test_split( X_dev, y_dev, test_size0.20, random_state42 ) print(训练集, len(X_train)) print(验证集, len(X_val)) print(测试集, len(X_test))实际输出训练集 640 验证集 160 测试集 200三类数据的职责不同训练集用于更新网络参数验证集用于选择最佳训练轮次测试集只用于最终评价。测试集不能参与标准化器拟合、训练轮数选择和模型参数调整。十二、为什么神经网络需要标准化四个输入特征的数值尺度明显不同\[ F\approx10\sim50 \]\[ L\approx300\sim600 \]\[ h\approx10\sim20 \]如果直接输入网络梁长的数值可能在梯度计算中占据过大影响。标准化公式为\[ \tilde{x}_j \frac{x_j-\mu_{j,\mathrm{train}}} {s_{j,\mathrm{train}}} \]代码如下input_scaler StandardScaler() target_scaler StandardScaler() X_train_scaled input_scaler.fit_transform(X_train) X_val_scaled input_scaler.transform(X_val) X_test_scaled input_scaler.transform(X_test) y_train_scaled target_scaler.fit_transform( y_train.reshape(-1, 1) ).ravel() print(X_train_scaled.shape) print(y_train_scaled.shape)实际输出(640, 4) (640,)标准化器只能在训练集上调用fit。验证集、测试集和后续新工况只能调用transform。十三、建立MLP网络model MLPRegressor( hidden_layer_sizes(32, 32), activationtanh, solveradam, learning_rate_init0.001, alpha0.0001, batch_size64, random_state42, early_stoppingFalse )主要参数含义参数本节设置作用hidden_layer_sizes(32, 32)两个隐藏层每层32个神经元activationtanh隐藏层激活函数solveradam参数优化方法learning_rate_init0.001初始学习率alpha0.0001L2正则化强度batch_size64每批训练样本数random_state42保证结果可重复定义预测函数将标准化结果恢复为MPadef predict_mpa(network, X_scaled): pred_scaled network.predict(X_scaled) return target_scaler.inverse_transform( pred_scaled.reshape(-1, 1) ).ravel()十四、逐轮训练并保存最佳模型history [] best_val_rmse np.inf best_epoch 0 best_model None max_epochs 1500 patience 120 for epoch in range(1, max_epochs 1): model.partial_fit( X_train_scaled, y_train_scaled ) train_pred predict_mpa( model, X_train_scaled ) val_pred predict_mpa( model, X_val_scaled ) train_error rmse( y_train, train_pred ) val_error rmse( y_val, val_pred ) history.append([ epoch, train_error, val_error ]) if val_error best_val_rmse: best_val_rmse val_error best_epoch epoch best_model deepcopy(model) if epoch - best_epoch patience: break model best_model print(实际训练轮数, len(history)) print(最佳模型轮数, best_epoch) print( f最佳验证RMSE f{best_val_rmse:.6f} MPa )实际运行输出实际训练轮数 1374 最佳模型轮数 1254 最佳验证RMSE0.427851 MPadeepcopy用于保存当时的模型参数副本。如果只写best_model model两个变量会指向同一个持续更新的对象无法真正保留最佳轮次。十五、分析训练曲线import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [ Microsoft YaHei, SimHei, DejaVu Sans ] plt.rcParams[axes.unicode_minus] False history_array np.asarray(history) plt.figure(figsize(9, 4.5)) plt.plot( history_array[:, 0], history_array[:, 1], label训练集 ) plt.plot( history_array[:, 0], history_array[:, 2], label验证集 ) plt.axvline( best_epoch, linestyle--, colorgray, labelf保留第{best_epoch}轮 ) plt.yscale(log) plt.xlabel(训练轮数 Epoch) plt.ylabel(RMSEMPa对数刻度) plt.legend() plt.grid(alpha0.2) plt.tight_layout() plt.show()【正文插图2神经网络训练曲线】从曲线可以看到训练初期误差迅速下降约200轮后网络已经学到主要非线性趋势后期误差仍在缓慢下降第1254轮取得最低验证误差此后连续120轮没有刷新最佳值训练停止。本例后期验证曲线基本趋于平稳并未出现明显的大幅上升。因此更准确的判断是模型已经接近收敛而不是严重过拟合。十六、独立测试与线性基线比较为了判断神经网络是否真正学到了非线性关系使用相同训练数据建立Ridge基线。mlp_pred predict_mpa( model, X_test_scaled ) ridge Ridge(alpha1.0) ridge.fit( X_train_scaled, y_train ) ridge_pred ridge.predict( X_test_scaled ) print( fRidge测试RMSE f{rmse(y_test, ridge_pred):.6f} MPa ) print( fMLP测试RMSE f{rmse(y_test, mlp_pred):.6f} MPa ) print( fMLP测试MAE f{mean_absolute_error(y_test, mlp_pred):.6f} MPa ) print( fMLP测试R² f{r2_score(y_test, mlp_pred):.6f} )实际运行输出Ridge测试RMSE4.696376 MPa MLP测试RMSE0.470548 MPa MLP测试MAE0.367447 MPa MLP测试R²0.998709结果说明在只输入 \(F,L,b,h\) 四个原始特征的条件下MLP比线性模型更好地学习了\[ \sigma_{\max} \frac{6FL}{bh^2} \]中的乘法、除法和平方关系。这个实验不表示神经网络比解析公式更合适。已知准确公式时直接计算更快速、更透明。本例使用解析问题是为了核验神经网络是否学到了正确的输入输出关系。十七、查看预测结果与残差【正文插图3测试集预测和残差】左图中散点整体接近理想预测线\[ \hat{\sigma}\sigma \]右图展示残差\[ e_i \hat{\sigma}_i-\sigma_i \]残差图可以帮助发现模型是否整体偏高或偏低高应力区域是否误差更大是否存在少量异常工况误差是否随目标值发生系统变化。虽然测试集 \(R^2\) 达到0.9987但高应力区域仍出现较大的个别残差。因此不能只看一个综合指标。对于工程应用还应检查\[ e_{\max} \max_i \left| \hat{\sigma}_i-\sigma_i \right| \]以及相对误差\[ e_{\mathrm{relative},i} \frac{ \left| \hat{\sigma}_i-\sigma_i \right| }{ \left| \sigma_i \right|\epsilon } \times100\% \]十八、预测一个新工况设新工况为\[ F30\ \mathrm{N} \]\[ L450\ \mathrm{mm} \]\[ b22\ \mathrm{mm} \]\[ h15\ \mathrm{mm} \]理论应力为\[ \begin{aligned} \sigma_{\max} \frac{6\times30\times450} {22\times15^2}\\ 16.363636\ \mathrm{MPa} \end{aligned} \]网络预测代码new_case pd.DataFrame( [[30.0, 450.0, 22.0, 15.0]], columnsfeatures ) new_case_scaled input_scaler.transform( new_case ) new_prediction predict_mpa( model, new_case_scaled )[0] theory_value ( 6.0 * 30.0 * 450.0 / (22.0 * 15.0**2) ) print( f理论应力 f{theory_value:.6f} MPa ) print( f网络预测 f{new_prediction:.6f} MPa ) print( f绝对误差 f{abs(new_prediction-theory_value):.6f} MPa )实际运行输出理论应力16.363636 MPa 网络预测16.391931 MPa 绝对误差0.028295 MPa新工况位于训练参数范围之内因此属于插值预测。若输入\[ F100\ \mathrm{N} \]或者\[ h5\ \mathrm{mm} \]就可能进入训练范围之外。此时即使程序能够给出数值也不能直接认为预测可靠。十九、与第十三节结果应该怎样比较第十三节中RBF-SVR和Stacking也取得了很高精度本节MLP的测试RMSE为\[ 0.470548\ \mathrm{MPa} \]它与上一节的优秀模型处于接近水平。不过两节的训练方案存在差异第十三节使用800条开发数据进行基模型拟合第十四节从开发集中划出160条验证数据本节只有640条样本直接参与网络参数更新模型选择和训练过程也不完全相同。因此这些结果适合帮助理解算法特点不应作为严格的排行榜。若要正式比较应使用相同的数据划分、相同的评价流程和重复交叉验证。二十、如何迁移到真实有限元项目真实项目可以将输入扩展为\[ \boldsymbol{x} \begin{bmatrix} \text{几何参数}\\ \text{材料参数}\\ \text{载荷参数}\\ \text{边界条件编码}\\ \text{网格参数} \end{bmatrix} \]输出可以是\[ \boldsymbol{y} \begin{bmatrix} U_{\max}\\ \sigma_{\mathrm{Mises,max}}\\ J\\ K_I\\ N_f \end{bmatrix} \]一个实际工作流可以写成Abaqus参数化建模 ↓ 多工况批量计算 ↓ ODB结果提取 ↓ 工况级数据划分 ↓ 输入与目标标准化 ↓ 神经网络训练 ↓ 验证集选择模型 ↓ 独立工况测试 ↓ 物理合理性检查这里有三个必须保持的习惯。第一模型与标准化器应同时保存。只有网络参数而没有训练时的均值、标准差和特征顺序模型不能可靠部署。第二输出量的定义必须统一。例如“固定位置的名义应力”和“全模型最大积分点应力”不是同一个目标。第三普通MLP只从数据误差中学习。本节损失函数没有加入平衡方程、本构方程或边界条件因此它属于数据驱动网络不属于PINN。二十一、常见问题1. 隐藏层越多越好吗不一定。网络加深会增加参数量和训练难度。对于本节这种四输入、单输出的小问题两层隐藏层已经具有足够的表达能力。2. 神经元越多越准确吗不一定。神经元过少可能欠拟合过多则可能增加过拟合风险和计算成本应根据验证集结果选择。3. 损失下降就表示模型可靠了吗只能说明优化过程取得进展。最终还需要独立测试、残差分析、物理趋势检查和适用范围检查。4. 为什么同一代码可能得到略有不同的结果网络权重初始化和批次训练包含随机过程。固定random_state可以提高可重复性但不同软件版本或计算环境仍可能导致最后几位存在差异。5. 神经网络会自动学会力学定律吗不保证。它可能在训练范围内很好地拟合数据却在外推区域违反单调性、对称性、平衡关系或边界条件。二十二、课后练习练习一改变网络规模将hidden_layer_sizes(32, 32)改为hidden_layer_sizes(16, 16)计算新网络的参数量并比较验证集与测试集误差。其参数量应为\[ 4\times1616 16\times1616 16\times11 369 \]练习二比较激活函数分别设置activationtanh和activationrelu比较最佳验证RMSE达到最佳结果所需的训练轮数高应力区域的最大残差。练习三加入物理特征构造新特征\[ q\frac{FL}{bh^2} \]根据力学公式\[ \sigma_{\max}6q \]使用单变量线性回归预测应力并与MLP比较。这个练习可以说明合理的物理特征能够显著降低模型学习难度。练习四检查物理单调性固定 \(F,L,b\)让梁高 \(h\) 从10 mm增加到20 mm绘制网络预测曲线。理论上应满足\[ \frac{\partial\sigma_{\max}}{\partial h} -\frac{12FL}{bh^3}0 \]也就是说梁高增大时应力应单调下降。检查神经网络是否遵守这一趋势。二十三、本节小结本节从第十三节的集成学习过渡到神经网络建立了后续深度学习课程需要的基本概念\[ \boxed{ \text{神经元} \text{加权求和} \text{激活函数} } \]\[ \boxed{ \text{网络预测} \text{多层前向传播} } \]\[ \boxed{ \text{网络训练} \text{损失计算} \text{反向传播} \text{参数更新} } \]神经网络能够学习复杂的力学映射但模型的可靠性仍依赖于数据覆盖、验证方法、物理检查和适用范围。完整课程附件完整代码建议放在本节末尾的“附录完整可运行代码”中。正文保留分段代码便于学习者跟随讲解逐步运行。[完整可运行代码][悬臂梁教学数据][逐轮训练记录][实际运行结果][模型与标准化器文件]附件地址【零基础学智能仿真-14】神经网络基础-从集成学习走向深度学习资源-CSDN下载
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。