【零基础学智能仿真-06】决策树——让模型自动发现力学失效阈值

第六节:决策树------让模型自动发现力学失效阈值

本节摘要

前面两节学习的线性回归与正则化回归,主要通过数学公式描述输入参数和力学响应之间的整体关系。但裂纹扩展、接触状态变化和材料失效往往具有明显的临界特征。

本节以裂纹长度与J积分数据为案例,学习决策树如何通过一系列条件判断,自动发现力学响应中的关键阈值,并分别完成连续响应预测和失效风险分类。


一、本节学习目标

完成本节后,你将能够:

  1. 理解决策树的节点、分支和叶节点;

  2. 了解CART算法的基本划分思想;

  3. 区分回归树和分类树;

  4. 使用回归树预测J积分;

  5. 使用分类树识别裂纹风险;

  6. 从树结构中读取工程判断规则;

  7. 使用树深度和叶节点样本数控制过拟合;

  8. 正确理解决策树的特征重要性。


二、为什么力学问题适合使用决策树?

许多工程问题并不表现为简单的线性关系。

例如:

  • 裂纹较短时,J积分增长缓慢;

  • 裂纹超过一定长度后,J积分快速增大;

  • 接触压力达到某一水平后,接触状态发生变化;

  • 应力超过屈服强度后,材料进入塑性阶段;

  • Courant数超过限制后,CFD计算可能发散。

这类问题常常包含"如果......那么......"的判断逻辑:

如果裂纹长度小于某个值,结构处于低风险状态;如果裂纹继续增大,则需要结合载荷判断是否进入临界状态。

决策树正是通过这种分层判断建立模型。


三、决策树的基本结构

决策树由三类节点组成:

  • 根节点:第一次划分全部样本;

  • 内部节点:继续对样本进行判断;

  • 叶节点:给出最终预测结果。

图6-1 裂纹风险的决策树判断流程

一条决策路径可能写成:

且:

那么模型判断结构处于低风险区域。

树模型的优势是判断规则可以直接阅读,不需要把模型当成完全无法解释的"黑箱"。


四、CART算法在做什么?

CART是Classification and Regression Tree的缩写,即分类与回归树。

它的基本过程是:

  1. 选择一个候选特征;

  2. 尝试多个候选阈值;

  3. 将样本分成左右两个子集;

  4. 计算划分后的不纯度或误差;

  5. 选择效果最好的特征和阈值;

  6. 在子节点中重复以上过程。

决策树每次只进行二叉划分:

或者:

其中j为第个特征,为划分阈值。


五、分类树如何选择划分条件?

分类树常使用基尼不纯度:

其中表示节点中第类样本所占的比例。

假设一个节点中有10个样本:

  • 5个安全;

  • 5个临界。

则:

0.5

如果一个节点中10个样本全部属于安全类:

因此:

  • 基尼不纯度越大,类别越混杂;

  • 基尼不纯度越小,节点越纯;

  • 表示节点中只有一个类别。

决策树倾向于选择能够使子节点更加纯净的划分条件。


六、回归树如何选择划分条件?

回归树的输出是连续数值,例如:

  • 位移;

  • 应力;

  • 温度;

  • J积分;

  • 疲劳寿命。

回归树通常使用均方误差评价节点内部的离散程度:

每个叶节点的预测值通常是该节点所有训练样本的平均值:

因此,回归树的预测曲线通常不是光滑曲线,而是阶梯形状。


七、建立裂纹长度---J积分数据集

假设通过Abaqus参数化计算,得到以下裂纹长度和J积分结果。

复制代码
import numpy as np
import pandas as pd

crack_length = np.array([
    1, 2, 3, 4, 5, 6, 7, 8, 9
], dtype=float)

j_integral = np.array([
    15, 22, 31, 43, 60,
    85, 118, 160, 215
], dtype=float)

data = pd.DataFrame({
    "裂纹长度_mm": crack_length,
    "J积分_N每mm": j_integral
})

print(data.to_string(index=False))

预期输出

复制代码
 裂纹长度_mm  J积分_N每mm
        1.0        15.0
        2.0        22.0
        3.0        31.0
        4.0        43.0
        5.0        60.0
        6.0        85.0
        7.0       118.0
        8.0       160.0
        9.0       215.0

可以看到,裂纹较短时J积分增长相对缓慢;随着裂纹增大,其增长速度明显加快。


八、训练J积分回归树

复制代码
from sklearn.tree import DecisionTreeRegressor

X = data[["裂纹长度_mm"]]
y = data["J积分_N每mm"]

regression_tree = DecisionTreeRegressor(
    max_depth=3,
    min_samples_leaf=1,
    random_state=42
)

regression_tree.fit(X, y)

new_cases = pd.DataFrame({
    "裂纹长度_mm": [2.5, 5.5, 8.5]
})

prediction = regression_tree.predict(
    new_cases
)

for crack, value in zip(
    new_cases["裂纹长度_mm"],
    prediction
):
    print(
        f"裂纹长度={crack:.1f} mm,"
        f"预测J积分={value:.1f} N/mm"
    )

预期输出

复制代码
裂纹长度=2.5 mm,预测J积分=18.5 N/mm
裂纹长度=5.5 mm,预测J积分=60.0 N/mm
裂纹长度=8.5 mm,预测J积分=160.0 N/mm

模型不会像多项式那样输出连续变化的光滑函数,而是先判断新样本落入哪个叶节点,再使用该叶节点的平均值作为预测结果。


九、绘制回归树预测结果

复制代码
import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = [
    "Microsoft YaHei",
    "SimHei"
]
plt.rcParams["axes.unicode_minus"] = False

x_curve = np.linspace(
    1.0, 9.0, 400
).reshape(-1, 1)

x_curve_frame = pd.DataFrame(
    x_curve,
    columns=["裂纹长度_mm"]
)

y_curve = regression_tree.predict(
    x_curve_frame
)

plt.scatter(
    crack_length,
    j_integral,
    s=70,
    color="#1769aa",
    label="仿真样本"
)

plt.plot(
    x_curve,
    y_curve,
    color="#f28e2b",
    linewidth=2.8,
    label="回归树预测"
)

plt.xlabel("裂纹长度 a(mm)")
plt.ylabel("J积分(N/mm)")
plt.title("回归树对J积分的阶梯式预测")
plt.grid(alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()

预期绘图结果

  • 蓝色圆点表示有限元仿真数据;

  • 橙色阶梯线表示回归树预测;

  • 每个平台对应一个叶节点;

  • 阶梯发生变化的位置就是树模型发现的划分阈值。

图6-2 J积分的回归树预测结果


十、把连续响应转化为风险分类

假设工程上规定:

为安全状态,而:

进入临界状态。

复制代码
data["风险等级"] = np.where(
    data["J积分_N每mm"] >= 100,
    "临界",
    "安全"
)

print(
    data[
        ["裂纹长度_mm", "风险等级"]
    ].to_string(index=False)
)

预期输出

复制代码
 裂纹长度_mm 风险等级
        1.0   安全
        2.0   安全
        3.0   安全
        4.0   安全
        5.0   安全
        6.0   安全
        7.0   临界
        8.0   临界
        9.0   临界

十一、训练裂纹风险分类树

复制代码
from sklearn.tree import (
    DecisionTreeClassifier,
    export_text
)

classification_tree = DecisionTreeClassifier(
    max_depth=2,
    criterion="gini",
    random_state=42
)

classification_tree.fit(
    X,
    data["风险等级"]
)

rules = export_text(
    classification_tree,
    feature_names=["裂纹长度_mm"]
)

print(rules)

预期输出

复制代码
|--- 裂纹长度_mm <= 6.50
|   |--- class: 安全
|--- 裂纹长度_mm >  6.50
|   |--- class: 临界

模型自动发现的关键阈值为:

这不是说真实结构一定会在处突然失效,而是表示在当前样本和风险定义下,这个阈值最能区分安全与临界样本。


十二、预测新的裂纹风险

复制代码
risk_cases = pd.DataFrame({
    "裂纹长度_mm": [4.5, 6.2, 7.5]
})

risk_prediction = classification_tree.predict(
    risk_cases
)

for crack, risk in zip(
    risk_cases["裂纹长度_mm"],
    risk_prediction
):
    print(
        f"裂纹长度={crack:.1f} mm,"
        f"预测状态={risk}"
    )

预期输出

复制代码
裂纹长度=4.5 mm,预测状态=安全
裂纹长度=6.2 mm,预测状态=安全
裂纹长度=7.5 mm,预测状态=临界

分类结果应结合安全系数、材料断裂韧度和适用规范解释,不能直接替代工程安全判定。


十三、树深度与过拟合

max_depth控制决策树最多可以生长多少层。

树太浅

  • 规则较少;

  • 容易解释;

  • 可能遗漏重要的非线性变化;

  • 容易欠拟合。

树太深

  • 可以记住大量训练样本;

  • 训练误差很低;

  • 阈值数量过多;

  • 对数据扰动敏感;

  • 容易过拟合。

例如:

复制代码
for depth in [1, 2, 3, 8]:
    model = DecisionTreeRegressor(
        max_depth=depth,
        random_state=42
    )

    model.fit(X, y)

    score = model.score(X, y)

    print(
        f"max_depth={depth},"
        f"训练集R²={score:.4f}"
    )

预期现象

随着树深度增加,训练集通常不断提高。但训练集表现提高,并不意味着新工况预测一定更可靠。


十四、控制决策树复杂度的参数

1. max_depth

限制树的最大深度。

2. min_samples_split

规定一个节点至少包含多少样本才允许继续分裂。

3. min_samples_leaf

规定每个叶节点至少保留多少样本。

4. max_leaf_nodes

限制叶节点总数。

5. ccp_alpha

通过代价复杂度剪枝删除贡献较小的分支。

工程小样本数据中,可以优先尝试:

复制代码
DecisionTreeRegressor(
    max_depth=3,
    min_samples_leaf=3,
    random_state=42
)

这样可以避免模型为个别异常样本建立专门分支。


十五、特征重要性

如果模型包含多个输入:

可以查看特征重要性:

复制代码
importance = pd.Series(
    regression_tree.feature_importances_,
    index=X.columns
).sort_values(ascending=False)

print(importance)

当前案例只有裂纹长度一个特征,因此预期输出为:

复制代码
裂纹长度_mm    1.0
dtype: float64

特征重要性表示该变量对降低节点误差的贡献,但不代表严格的因果关系。

连续变量、取值较多的变量还可能更容易获得较高的重要性,因此后续最好结合置换重要性或SHAP进行验证。


十六、决策树的优点与局限

主要优点

  • 不要求输入与输出满足线性关系;

  • 不需要进行特征标准化;

  • 可以处理明显的阈值效应;

  • 分类与回归都能使用;

  • 判断路径容易解释;

  • 能够处理特征之间的交互。

主要局限

  • 单棵树容易过拟合;

  • 数据轻微变化可能改变树结构;

  • 回归结果呈阶梯状,不够光滑;

  • 外推能力较弱;

  • 深树的规则可能变得复杂;

  • 特征重要性可能存在偏差。

因此,决策树通常还是随机森林、梯度提升树和XGBoost等集成算法的基础组件。


十七、不能把数据阈值直接当成物理定律

分类树得到:

它只在以下条件下成立:

  • 当前材料;

  • 当前载荷范围;

  • 当前几何尺寸;

  • 当前边界条件;

  • 当前J积分临界值;

  • 当前有限元建模方法。

如果载荷、材料或结构尺寸改变,阈值也可能改变。

因此,更严谨的表达应当是:

在本数据集覆盖的工况范围内,裂纹长度约为6.5 mm时,样本的风险类别发生明显分离。


十八、本节练习

基础练习

分别设置:

复制代码
max_depth = 1
max_depth = 2
max_depth = 3
max_depth = None

观察树结构和阶梯预测曲线的变化。

进阶练习

增加载荷特征,建立:

并检查树模型优先使用裂纹长度还是载荷进行划分。

工程挑战

将风险划分为三级:

  • :安全;

  • :预警;

  • :临界。

训练多分类决策树,并将每条路径改写成工程判断规则。


十九、本节小结

本节完成了两个决策树模型:

以及:

决策树的核心价值不只是预测结果,还在于自动发现数据中的关键划分条件:

但必须记住:

下一节将进入Bagging与随机森林,学习如何组合多棵不同的决策树,降低单棵树的不稳定性,并量化载荷、几何和材料参数对力学响应的贡献。

相关推荐
啥都想学点的研究生31 分钟前
一篇文章讲清楚:C4.5决策树和CART决策树
算法·决策树·机器学习
DDXYcoder32 分钟前
万字解析动态内存从编译到运行
java·前端·算法
阳明山水36 分钟前
概念漂移分类与自适应策略解析
人工智能·深度学习·算法·机器学习·架构
欧特克_Glodon1 小时前
OpenCV计算机视觉开发入门与实践<二十九>:grabCut算法分割图像
opencv·算法·计算机视觉·图像分割·grabcut 算法
方方洛1 小时前
vllm教程-02-核心原理
人工智能·算法·vllm
OPEN-F2 小时前
C++并发编程:异步任务与线程池实战
开发语言·c++·算法
凉茶钱2 小时前
【数据结构】计数排序
数据结构·算法·排序算法
克里斯蒂亚诺更新2 小时前
机器学习和深度学习的主要区别--特征提取
人工智能·深度学习·机器学习
同元软控3 小时前
MWORKS EI:从数字空间到物理世界,面向具身智能产品的一体化研发环境
人工智能·机器学习