简介:2022年五一杯数学建模竞赛C题‘火灾报警系统问题’的完整解题论文,面向备战数学建模的高校学生与科研人员。论文以真实火灾报警数据为背景,围绕火灾探测器可靠性评价、报警信息误报判别及消防大队管理水平评估三大任务,先后构建了熵权-TOPSIS综合评价模型、基于logistic回归的区域报警部件智能研判模型,并引入WOE值对模型进行优化。模型分析过程中,完整展示了指标选取、权重确定、虚拟变量构造、回归检验与优化等规范步骤,最终给出最可靠的五种探测器类型、各大队报警真实概率及管理水平改进建议。压缩包内共1个docx文档,大小约291KB,内容包含问题重述、模型假设、符号说明、模型建立与求解、结果对比和关键词等完整章节,结构清晰,便于对照学习。目前已有913人学习下载,对想掌握评价类与分类预测类模型综合应用的同学具有很好的参考价值。
1. 五一杯C题火灾报警系统:418起真实火警背后的三套评价模型
拿到2022年五一杯C题时,第一反应是数据量不小:附件一里6月1日到18日的报警记录密密麻麻,误报、故障、重复报警混在一起,光是把“到底发生了多少次真实火灾”数清楚就得花一番功夫。这道题的实质是把一个消防场景里的决策问题拆成三层:先靠熵权-TOPSIS从16种探测器部件里筛出可靠型号,再用Logistic回归判断某条报警信号是真是假,最后给18个消防大队的管理水平打分排名。对参赛者来说,这套题的核心不是堆算法,而是把“指标方向统一、权重客观、模型可解释”这三件事做到位。这篇笔记会把四问的建模流程、参数代入和踩过的坑完整过一遍,适合正在备赛数学建模、或者做评价类与二分类预测模型的人直接对照复现。
2. 熵权法+TOPSIS:从16种探测器部件里筛出5种最可靠类型
2.1 真实火警计数:先按“三相同”去重,再算部件指标
问题一的第一步是确定6月1日至18日的真实火灾起数。附件一的报警记录里有地址、机号、回路编号这三个关键字段,题目给出的判定规则是:当多个火灾探测器的机号和回路编号相同、且都发出火灾报警信号时,认为是同一起火灾。
实际操作分两层过滤:
第一层,把标记为“误报”的记录剔除。第二层,对剩下的真实报警按机号、回路、地址三个字段去重。这里有个容易理解偏的点:不是每个探测器报一次就算一起火灾,同一建筑内多个探测器同时报警,物理上对应的是同一场火。我处理时的做法是用Excel先加筛选器,把误报记录排除,再按机号、回路、地址做“删除重复项”,统计得到418起。这个数字是后面所有指标计算的基础,如果去重条件写错,第二问的Logistic回归样本标签也会跟着错。
import pandas as pd df = pd.read_excel("附件一.xlsx") # 剔除误报记录,误报标记字段为“是否误报”,1表示误报 df_real = df[df["是否误报"] == 0].copy() # 按机号、回路、地址去重,三字段完全相同视为同一场火灾 df_dedup = df_real.drop_duplicates(subset=["机号", "回路", "地址"]) true_fire_count = df_dedup.shape[0] print(true_fire_count) # 418逻辑说明:先过滤误报,再按三个字段去重,顺序不能反。如果先去重再过滤,同一个地址下误报和真实报警混在一起,去重会把真实火警误删。参数说明:subset里三个字段必须同时传入,只按地址去重会漏掉同建筑多探测器的情况,只按机号去重又会把不同地址的报警合并。
2.2 指标统一方向:误报率转可靠性、故障率转完善率
确定418起真实火警后,下一步是评估16种部件的可靠性。题目原话给了两个指标:可靠性和故障率。但直接用原始比例做评价有个问题——方向不一致。可靠性是越高越好(效益型),故障率是越低越好(成本型),如果直接放进同一个评价矩阵,TOPSIS计算距离时会互相抵消。
原文的处理方式值得记下来:
误报警率计算公式为:
P_i = T_i / F_i
其中T_i是部件i的误报警次数,F_i是报警总次数。误报警率越低,可靠性越高,所以用指数变换把P_i映射为可靠性D_i = e^(-P_i)。这样误报率高的部件可靠性得分低,方向就统一了。
故障率的处理类似。设G_i为部件i的故障次数,A为所有部件的故障总次数,则故障率V_i = G_i / A。故障率是成本型指标,所以同样做指数变换得到完善率W_i = e^(-V_i)。完善率越高,说明部件越不容易出故障,方向与可靠性一致。
这里我踩过一个坑:直接用P_i和V_i做熵权法,结果权重被误报率主导,因为误报率的数值范围远大于故障率。后来把两个指标都转换为[0,1]区间内的指数型得分,再做归一化,权重分配才合理。附带一提,原文里光束感烟、手动报警按钮等部件的故障率较低,完善率接近1,而点型感烟探测器故障率偏高,完善率只有0.585左右,这个差异后面直接影响综合排名。
2.3 熵权法确定权重:为什么不用专家打分
评价模型里最容易被质疑的就是权重来源。如果直接拍脑袋定“可靠性占0.6、故障率占0.4”,评阅时很难站住脚。熵权法的思路是:某个指标下各样本的取值差异越大,这个指标能提供的信息越多,权重就应该越高。从数据本身出发,避免人为干扰。
熵权法计算步骤:
- 构造m个评价对象、n个评价指标的原始矩阵X。
- 对每个指标做归一化,得到P_ij。
- 计算每个指标的熵值H_i = -k * Σ(P_ij * ln(P_ij)),其中k = 1/ln(n)。
- 计算差异系数d_i = 1 - H_i,权重w_i = d_i / Σd_i。
原文算出的可靠性权重为0.943,完善率权重为0.0569。这个结果很符合直觉:16种部件的误报率差异极大,从接近0到超过0.99,区分度高;而多数部件的故障率其实都不高,差异小,所以熵权法自动把权重大部分给了可靠性。
import numpy as np def entropy_weight(data): # data: shape (n_samples, n_features) n, m = data.shape # 归一化 P = data / data.sum(axis=0, keepdims=True) # 计算熵值 k = 1 / np.log(n) H = -k * np.sum(P * np.log(P + 1e-12), axis=0) # 差异系数和权重 d = 1 - H w = d / np.sum(d) return w # 构造可靠性D与完善率W构成的矩阵 X = np.array([[0.075, 1.0], [0.0646, 0.9226], [0.0616, 0.8033]]) weights = entropy_weight(X) print(weights)逻辑说明:P = data / data.sum(axis=0, keepdims=True)这行是按列归一化,让每个指标下的所有样本取值之和为1,这样熵值才有可比性。1e-12是为了避免P_ij为0时ln报错。参数说明:熵权法对归一化方式敏感,这里用的是比例归一化;如果数据里有负值,需要先做平移处理,否则P_ij会出现负数导致熵值计算错误。
2.4 TOPSIS打分排序:贴近度怎么算,结果怎么读
权重确定后,进入TOPSIS环节。TOPSIS全称是“优劣解距离法”,核心思想是:构造一个虚拟的最优方案(所有指标都取最大值)和一个最劣方案(所有指标都取最小值),然后计算每个评价对象到最优解和最劣解的距离。得分用贴近度C_i表示:
C_i = D_i- / (D_i+ + D_i-)
其中D_i+是到最优解的距离,D_i-是到最劣解的距离。C_i越接近1,说明该方案越接近最优。
由于两个指标已经统一为效益型方向,正向化这步可以跳过,直接做标准化。标准化用向量归一化:每个值除以所在列的向量长度。
def topsis(data, weights): # 向量归一化 norm = data / np.sqrt(np.sum(data**2, axis=0)) # 加权 weighted = norm * weights # 最优解与最劣解 ideal_best = weighted.max(axis=0) ideal_worst = weighted.min(axis=0) # 距离 dist_best = np.sqrt(np.sum((weighted - ideal_best)**2, axis=1)) dist_worst = np.sqrt(np.sum((weighted - ideal_worst)**2, axis=1)) # 贴近度 score = dist_worst / (dist_best + dist_worst) return score scores = topsis(X, weights) print(scores)逻辑说明:norm行按列做向量归一化,让不同量纲的指标可以直接比较。weighted = norm * weights这行是关键——必须先归一化再加权,如果反过来先加权再归一化,权重就失去意义了。参数说明:ideal_best和ideal_worst都基于加权后的矩阵计算,这符合TOPSIS标准流程;贴近度公式里分母加的是两个距离之和,如果某方案恰好等于最优解,score为1,反之则为0。
2.5 求解结果与参数:前5名部件得分对照
把16种部件的可靠性和完善率代入模型,统计得到综合得分前五名:
| 排名 | 部件名称 | 综合得分 |
|---|---|---|
| 1 | 光束感烟 | 0.18889 |
| 2 | 手动报警按钮 | 0.16205 |
| 3 | 智能光电探头 | 0.15024 |
| 4 | 点型感温探测器 | 0.066336 |
| 5 | 线型光束感烟探测器 | 0.041577 |
注意前两名得分显著高于后三名。原因是光束感烟和手动报警按钮的误报率极低,可靠性接近1,而且故障率也为0,完善率直接是1,两个指标都拉满。智能光电探头可靠性略低,但依然远高于排名靠后的火焰探测器、气体探测器(这两类得分只有0.037左右)。排名靠后的部件问题多出在误报率上,比如点型感烟探测器误报率高达0.9902,可靠性几乎为0,即使故障率不算最高,综合得分也被拖垮了。
如果只看故障率排序,点型感烟探测器并非最差,但熵权法把权重压在可靠性上,排名自然就拉下来了。这个结果提示一个建模技巧:当评价指标数量少但方向不同时,指标变换和权重计算的方式直接决定结论,务必在论文里写清楚为什么用指数变换而不是线性变换。
3. Logistic回归与WOE编码:报警信号真实概率的智能研判
3.1 问题转化与变量选择:二分类因变量和哑变量陷阱
问题二的目标很明确:当某个大队辖区内的某类型探测器发出报警时,判断这条报警是真实火警还是误报。这是个标准的二分类问题,因变量是“是否误报”,取值为0或1。原文比较了决策树、贝叶斯、神经网络和Logistic回归,最终选择Logistic回归的理由很实在:决策树只能处理离散变量且运算量大,贝叶斯缺少准确的概率分布,神经网络解释力差。Logistic回归对自变量没有正态分布要求,输出直接是概率值,且模型可解释。
自变量选了几个:探测器类型(16个类别)、消防大队(18个类别)、故障次数、火警次数。探测器类型和消防大队都是无序多分类变量,不能直接赋值为1、2、3然后扔进回归方程——那样模型会误认为类别之间有大小关系。正确做法是转成哑变量,即每个类别生成一个0/1列,并留一个参照组。
这里有个实操细节:参照组怎么选。原文选择的是报警次数最多的点型感烟探测器,以及管辖面积最大的Q大队作为参照。这是常见做法,因为参照组样本量大,模型估计更稳定。处理完后的数据长这样:
| 数据编号 | 探测器类型 | 消防大队 | 故障次数 | 火警次数 | 误报数 | 是否误报 |
|---|---|---|---|---|---|---|
| 1 | 1(光束感烟) | A | 1 | 201 | 1 | 1 |
| 2 | 3(智能光电探头) | B | 0 | 119 | 0 | 0 |
3.2 回归方程参数解读:SPSS输出B值怎么代入
Logistic回归方程的标准形式是:
P(误报|X) = exp(β0 + βX) / (1 + exp(β0 + βX))
其中X是自变量向量,β是待估计参数。SPSS跑完输出一组B值,比如常量B=-4.983,探测器类型(1)的B=9.501,火警次数B=0.035,等等。
代入公式时要留意:B值是针对哑变量组的。比如探测器类型(1)代表光束感烟这个类别相对于参照组点型感烟探测器的系数,消防大队(1)代表A大队相对于参照组Q大队的系数。预测时,需要把对应类别的哑变量置为1,其余置为0,然后代入计算。
原文给出的检验结果模型真实性为94.7%,也就是说训练集内预测准确率不错。但拿到附件三预测各大队报警信号的真实概率时,结果就暴露出问题:比如某个大队的某类部件预测真实火警概率只有0.8%,明显偏低;而另一个高达98.67%,两级分化严重。这说明模型虽然整体拟合好,但对部分类别的估计不稳定,原因在于哑变量数量太多——16个探测器类型加18个消防大队,生成了30多个哑变量,回归方程参数过多,部分类别样本量小,系数估计方差大。
3.3 WOE值优化:离散变量过多时的常用替代
针对哑变量过多的问题,原文用WOE(Weight of Evidence,证据权重)替换原始分类变量值。WOE的计算公式是:
WOE = ln(误报次数占误报总次数的比值 / 非误报次数占非误报总次数的比值)
直观理解:某个消防大队(或某类探测器)的WOE值为正,说明该类别下误报占比高于非误报占比,即该类别更容易产生误报;WOE为负,则说明该类别下真实报警占比更高。把WOE值当作连续变量放进Logistic回归,可以减少哑变量数量,同时保留分类变量的信息。
import pandas as pd import numpy as np def calc_woe(df, col, target): """ df: 数据框 col: 需要编码的分类变量列名 target: 因变量列名,1表示误报,0表示非误报 """ total_bad = df[target].sum() total_good = df.shape[0] - total_bad grouped = df.groupby(col)[target].agg(['sum', 'count']) grouped['bad_ratio'] = grouped['sum'] / total_bad grouped['good_ratio'] = (grouped['count'] - grouped['sum']) / total_good grouped['woe'] = np.log(grouped['bad_ratio'] / grouped['good_ratio']) return grouped['woe'] # 以消防大队为例 woe_series = calc_woe(df, '消防大队', '是否误报') df['消防大队_woe'] = df['消防大队'].map(woe_series)逻辑说明:total_bad和total_good先算全局的误报总数和非误报总数,然后按类别分组统计。bad_ratio是每个类别下误报次数占全局误报总数的比例,good_ratio同理。两者相除再取对数,就是该类别相对整体平均水平的偏移量。参数说明:如果某个类别下good_ratio为0,ln会报错,需要加平滑项,例如分子分母同时加0.5,这是实际处理时的经验做法。
用WOE值替换原始分类变量后重新跑Logistic回归,附件三的真实概率结果分布更合理,不再出现极端值。这个优化方向值得借鉴,它本质上是把高维稀疏的哑变量矩阵压缩成一个有业务含义的连续变量,既保住了模型精度,又降低了过拟合风险。
3.4 附件三概率结果排序与说明
用WOE优化后的模型处理附件三数据,得到各大队不同探测器类型报警信号为真实火警的概率,原文给的序列是:19.3%、0.8%、1.01%、2.6%、98.67%、0.55%、7.02%、75.23%、0.85%、11.2%、71.2%、79.06%、7.9%、54.67%、19.38%。
读这个结果有个技巧:概率低于5%的报警信号基本可以直接判定为误报,高于70%的则需要优先调度核实。比如98.67%和79.06%这两条,属于高置信真实火警,对应的大队辖区内探测器类型大概率是可靠性排名靠前的型号。而0.55%和0.8%这两条,几乎可以肯定是误报,通常出现在误报率高的部件上,比如点型感烟探测器。实际应用中,可以按这个概率值设定双阈值——低于0.1直接标记误报,高于0.9直接出警,中间区间留给人工复核。
4. 消防大队管理水平评价与常见建模避坑
4.1 四个成本型指标构建:单位面积概率、误报率、故障率
问题三要求对各消防大队的综合管理水平进行排序。评价指标选了四个:
- 单位面积火灾发生概率Q_i = N_i / S_i,其中N_i是真实火灾数,S_i是辖区面积。
- 单位面积火灾报警数量R_i = M_i / S_i,其中M_i是报警总数。
- 误报警率P_i = T_i / F_i。
- 部件故障率V_i = G_i / A,其中G_i是该大队故障次数,A是全局故障总数。
注意这四个指标全部是成本型——数值越低管理水平越高。这和问题一不同,问题一里可靠性和完善率都是效益型,越高越好。指标方向如果搞错,后面的排名就完全反了。
原始数据的量纲差异在这四个指标里非常明显:单位面积火灾报警数的数值范围可能从几十到上千,而故障率可能只有0.001级别。如果不做归一化直接算,大数值指标会完全主导距离计算。所以必须走完整的标准化流程。
4.2 各大队得分排名与JGI大队诊断
熵权法算出的四个指标权重依次为:误报警率0.0216、部件故障率0.1772、单位面积火灾发生概率0.259、单位面积火灾报警数0.5422。权重最大的是单位面积火灾报警数,说明各大队在这个指标上差异最大,信息量最丰富。
代入TOPSIS得到18个大队的得分排名。得分最高的三个是J大队、G大队、I大队——注意这里因为全是成本型指标,得分越低管理水平越高。原文后半段给出的诊断信息是:这三个大队的误报警率分别为0.970、0.992、0.998,单位面积火灾发生概率分别为3.43、3.85、1.60,均明显高于全体大队平均值0.953和0.942。也就是说,这三个大队的辖区面积小但火灾发生频繁,报警基数大,且报警器可靠性差,误报率居高不下。
改进方案的核心是:在辖区内增加问题一选出的5种可靠探测器(光束感烟、手动报警按钮、智能光电探头、点型感温、线型光束感烟),替换掉误报率高的部件。这个方案直接串联了问题一和问题三,体现出整套模型的连贯性。
4.3 常见问题排查:踩过的5个坑
坑一:指标方向没统一就进TOPSIS。现象是排名结果和直觉完全相反。原因是可靠性和故障率一个效益型一个成本型,直接计算距离时互相拉扯。解决:先对成本型指标做倒数或取反变换,统一为效益型方向再计算。我习惯用指数变换,因为能保持数据分布特征。
坑二:归一化顺序写错。现象是权重算出来和手算对不上。原因是先加权再归一化,导致权重被归一化步骤抵消。解决:严格按“先向量归一化,再乘权重”的顺序执行。
坑三:哑变量参照组选错。现象是Logistic回归里某个类别的系数爆炸式增长。原因是不是每个类别都有足够样本,选样本量小的类别做参照会导致估计不稳定。解决:参照组选择频数最高的类别,或者在频数不足时先合并类别。
坑四:WOE计算时除零。现象是某个类别下没有非误报样本,ln里出现无穷大。解决:分子分母各加0.5做平滑,或者合并该类别。
坑五:消防大队得分排序读反。现象是以为得分高就是管理好,结果提交的结论完全反了。原因是没有注意到四个指标都是成本型。解决:先把指标方向检查一遍,再决定是取大还是取小。建议在论文里明确写出“得分越低管理水平越高”这句关键说明。
5. 从建模到落地:维护建议与模型效果验证技巧
5.1 问题四的维护建议怎么从模型结果推导
问题四看起来是开放题,但答案其实可以从前三问的结论里顺出来。原文把建议分成五块:触发装置检查、报警装置检查、电源检查、联动控制系统检查、技术档案管理。
触发装置这部分的要点是环境适配。感烟探测器不适合用在厨房和锅炉房这类高温高湿环境,应该换成感温探测器,因为感烟探测器的使用环境温度一般在50℃左右,超过容易故障。这个细节直接对应问题一里气体探测器、火焰探测器得分低的现象——不是设备本身差,而是使用场景不匹配导致误报率高。
报警装置检查讲究实测。用专用加烟工具对探测器实际操作,看报警确认灯是否亮起,同时检查控制器有没有时间记录。检查完要消音和复位,防止元件长时间通电损坏。电源检查则是看主备电源切换是否正常,原文建议每季度做1至2次充放电试验、1至3次切换试验。
技术档案管理这块容易被忽略,但实际是建模之外的“软功夫”。系统安装调试完,施工图纸、测试记录、调试报告都要归档;运行期间的值班记录、维修记录也要同步保存。这些历史数据正是问题二Logistic回归建模的原料,档案越完整,模型可用的训练样本越多。
5.2 快速验证模型效果:混淆矩阵和概率校准
写完模型别急着交,验证这步很值钱。我常用的验证方式有两个:
第一个是混淆矩阵。把预测概率按0.5阈值切成预测类别,和真实类别对比,得到四个数:TP(真正例)、FP(假正例)、TN(真负例)、FN(假负例)。然后算准确率、精确率、召回率。问题二里模型真实性94.7%这个数字,其实就是准确率——但只报准确率不够,如果误报样本占90%,模型全预测误报也能有90%准确率,所以必须看召回率。
第二个是概率校准。Logistic回归输出的概率不一定是真实概率,需要做校准检验。最简单的做法是把样本按预测概率分成10组,每组算实际误报率,画一条校准曲线。如果曲线接近对角线,说明概率校准良好;如果偏离大,可以考虑用Platt缩放或保序回归调整。WOE优化本质上也起到了部分校准作用,因为它改变了自变量分布,让回归系数更贴近真实的对数几率比。
另外还有一个细节:附件三里那些概率低于1%的样本,不要急着删掉。它们虽然被判定为误报,但可以用来做误报原因分析——是哪类探测器、哪个大队、什么时间段的误报最集中。这些信息对问题四的维护建议很有价值,比如误报集中在某个大队的某类探测器上,就可以针对性地检查那片区域的安装环境。
做这个项目最大的教训是:数据清洗和指标方向检查花费的时间,远超建模本身。从那以后每次做评价类或二分类题目,我都强制走一遍“方向检查-归一化-参照组确认-结果反推”这套流程,宁可多花半小时,也不在提交前才发现排名读反或权重算错。希望这篇笔记能帮你少踩几个坑,复现时少走些弯路。
本文还有配套的精品资源,点击获取