写作结构:视频引入→项目背景→环境导入→数据读取说明→探索可视化→泊松回归建模→预测评估→结论总结,适配 Jupyter 分段运行,注释通俗易懂,适合零基础学习泊松回归。

开始之前我们先看一条视频,不感兴趣的可自行跳过 o 型环引发的惨案:https://www.bilibili.com/video/BV1ptrMBhESU?t=0.0

1986 年挑战者号航天飞机升空爆炸,事故溯源直指低温环境下 O 型密封圈失效破损。传统线性回归适合连续因变量,而O 型环损伤数量是 0、1、2 这类非负离散计数值,泊松回归正是处理计数型因变量的经典模型,本篇我们依托真实事故数据集,手把手用 Python 实现泊松回归,量化温度、气压等因素对密封圈破损数量的影响。

一、导入所需依赖库

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
import statsmodels.formula.api as smf
from sklearn.metrics import mean_squared_error

# 解决Matplotlib中文乱码、负号不显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 屏蔽pandas版本冗余警告
import warnings
warnings.filterwarnings("ignore")

代码讲解

  • pandas/numpy:数据读取、数据运算与表格处理;
  • matplotlib:数据可视化,绘制损伤分布直方图;
  • statsmodels:统计学建模库,内置 GLM 广义线性模型,实现泊松回归;
  • mean_squared_error:用来计算 RMSE,完成模型预测效果评估。

二、读取外部数据集并约束字段数据类型

# 读取外部 CSV 文件
data=pd.read_csv('o-ring-erosion-only.csv'
                ,names=['Num_ring',
                      'num-distress',
                      'temperature',
                      'pressure',
                      'flight_order'],
                 dtype={'Num_ring':int,
                      'num-distress':int,
                      'temperature':float,
                      'pressure':float,
                      'flight_order':int})
print("数据集行列:",data.shape)
print(data.head())

代码讲解

  1. 原始 CSV 文件无表头,names=[]手动自定义 5 列字段名称:
    • Num_ring:单次飞行 O 型环总数量;
    • num-distress目标因变量,破损 O 型环个数(计数变量,泊松回归适配场景)
    • temperature:发射环境温度(华氏度,核心自变量);
    • pressure:舱内加压压力;
    • flight_order:飞行发射批次序号;
  2. dtype强制指定每列数据格式,防止读入数据出现字符串、格式错乱;
  3. data.shape查看样本数与字段数,head()预览前 5 条原始数据。

注意:字段名含横杠num-distress,后续建模公式需要用Q("字段名")包裹,规避 Python 语法报错。

三、探索性可视化:因变量分布直方图

plt.figure(figsize=(8, 5))
plt.hist(data['num-distress'], bins=10, facecolor='blue', edgecolor='black', alpha=0.7)
plt.xlabel("O型环热损伤数量")
plt.ylabel("样本频数")
plt.title("O型环破损数量分布直方图")
plt.show()

代码讲解 & 结果说明

  1. 直方图统计每一种破损数量对应的样本条数;
  2. 从分布图可以看到:绝大多数样本破损数为 0,少量 1、2,非负离散计数分布,完美契合泊松分布的数据特征,佐证选用泊松回归的合理性,不能使用普通最小二乘线性回归。

四、搭建泊松回归 GLM 模型,输出统计检验结果

# 字段带横杠用Q()转义,回归公式:因变量~自变量1+自变量2+...
formula = 'Q("num-distress") ~ Num_ring + temperature + pressure + flight_order'
# family=sm.families.Poisson 指定使用泊松回归
model = smf.glm(formula=formula, data=data, family=sm.families.Poisson())
# IRLS迭代加权最小二乘法拟合模型
result = model.fit()

print("===== 泊松回归模型统计结果 =====")
print(result.summary())

结果解读要点(CSDN 正文重点)

  1. coef:回归系数,泊松回归使用 log 对数链接函数,系数含义为对数期望变化率
  2. P>|z|:P 值,小于 0.05 代表该变量在统计学上显著影响因变量;
  3. 本例中temperature温度 P<0.05,温度是显著影响因素;压力、批次、密封圈总数 P>0.05,无显著统计影响。

五、模型预测、效果评估与核心指标量化

# 基于训练好的模型对全量样本做预测,保留3位小数
data['predict_result'] = result.predict(data).round(3)

# 展示原始值+预测值前5行
display(data[['Num_ring','num-distress','temperature','pressure','flight_order','predict_result']].head())

# RMSE均方根误差:衡量预测值与真实破损数的整体偏差,数值越小拟合越好
rmse = np.sqrt(mean_squared_error(data['num-distress'],data['predict_result']))
print(f"\n模型RMSE: {rmse:.4f}")

# 提取温度系数与P值,量化温度对破损率的影响
coef_temp = result.params['temperature']
p_temp = result.pvalues['temperature']
print(f"\n温度回归系数: {coef_temp:.4f},p值: {p_temp:.4f}")

if p_temp < 0.05:
    # 泊松系数指数换算:exp(β)为倍率,1-exp(β)得到变化百分比
    rate = 100 * (1 - np.exp(coef_temp))
    print(f"温度影响显著,每升高1℉,O型环期望损伤数量下降 {rate:.1f}%")
else:
    print("温度影响不显著")

关键公式讲解: 泊松回归:\(ln(\lambda)=\beta_0+\beta_1X_1+...\),\(\lambda\)为破损数期望值 温度系数\(\beta<0\),温度每 + 1,期望破损变为原先\(\exp(\beta)\)倍,因此破损降幅 =\(100\times(1-e^\beta)\%\)。

六、项目总结(博文结尾段落)

通过挑战者号 O 型环真实数据集的泊松回归实战,我们得到关键结论:

  1. O 型环破损数量是离散计数数据,放弃线性回归,泊松回归是最优建模方案;
  2. 发射温度是影响密封圈破损的显著性因素,低温会大幅提升 O 型环失效概率,从数据层面印证挑战者号事故诱因;
  3. 发射压力、批次、密封圈总数量对破损无统计学显著影响;
  4. 模型 RMSE 用来量化整体预测误差,完成模型性能评价。

补充:下方附带免本地 CSV 文件版完整代码,直接复制即可运行,内置字符串数据源,无需额外下载 csv。

附无外部文件完整版代码(直接运行)

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
import statsmodels.formula.api as smf
from sklearn.metrics import mean_squared_error
from io import StringIO

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
warnings.filterwarnings("ignore")


# 从字符串读取数据
data = pd.read_csv(
    StringIO(csv_data),
    names=['Num_ring', 'num_distress', 'temperature', 'pressure', 'flight_order'],
    dtype={
        'Num_ring': int,
        'num_distress': int,
        'temperature': float,
        'pressure': float,
        'flight_order': int})

# 基础信息
print("数据形状:", data.shape)
print("\n数据前5行:")
print(data.head())

# 绘图
plt.figure(figsize=(8, 5))
plt.hist(data['num_distress'], bins=10, facecolor='blue', edgecolor='black', alpha=0.7)
plt.xlabel("热损伤O型环个数")
plt.ylabel("频数")
plt.title("num_distress 频数分布直方图")
plt.show()

# 泊松建模
formula = 'num_distress ~ Num_ring + temperature + pressure + flight_order'
model = smf.glm(formula=formula, data=data, family=sm.families.Poisson())
result = model.fit()

print("\n==================== 泊松回归模型结果 ====================")
print(result.summary())

# 预测
data['predict_result'] = result.predict(data).apply(lambda x: round(x, 3))
print("\n==================== 预测结果 ====================")
print(data[['Num_ring', 'num_distress', 'temperature', 'pressure', 'flight_order', 'predict_result']].head())

# 模型评估
rmse = np.sqrt(mean_squared_error(data['num_distress'], data['predict_result']))
print(f"\nRMSE(均方根误差): {rmse:.4f}")

# 温度分析
coef_temp = result.params['temperature']
p_temp = result.pvalues['temperature']
print("\n==================== 温度影响分析 ====================")
print(f"温度系数: {coef_temp:.4f},p值: {p_temp:.4f}")
if p_temp < 0.05:
    print("温度对O型环损伤有显著影响(p < 0.05)")
    print(f"温度每升高1华氏度,预期损伤数减少约 {100*(1-np.exp(coef_temp)):.1f}%")
else:
    print("温度影响不显著")

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐