AI机器人Chappie和大唐判官狄仁杰有个共同点:头上都插着全频段高增益天线,此事必有蹊跷......
警告:本篇涉及AI算法,部分段落过度烧脑,文科生慎入
Erik Hollnagel在《Safety I and Safety II》一书指出,安全生产中人们往往只关注哪里出错了,而不太关注那些顺利实施的;监管部门致力于仔细检查不良事件,建立大量模型和方法来分析原因,但是占总量99.99%的正常运行数据,却很少有人问津;他还指出,即使有人想研究正常运行,也很难找到数据,这是国外的情况,国内的民航正常数据,咱可都留着呢。
本篇介绍一种计算机方法,利用正常航班的数据,快速查找不安全事件原因的线索。
人脑分析机制
元芳,你怎么看?这句话大家都不陌生,我们来分析一下它的深层含义:
1、这句话是有前情提要的,可以假设狄仁杰和元芳已经听取了30个证人的证词,或者勘察了50个物证;
2、这些证词有些是虚假的,有些是真实的,更多的是无关的废话;狄仁杰希望发挥分析的专长,但不想在废话上浪费时间,因此需要元芳进行初筛;
3、元芳需要回答的是,哪些证词是可能有用的,哪些显然是无关的;元芳的压力在于,需要遍历这些证词,如果有遗漏,可能会错过关键信息而被狄仁杰教诲;
4、要推断哪些是有用的还是无关的,元芳需要回顾日常经验,例如,一份证词说嫌疑人如厕一个时辰,根据日常经验,这极不正常,因此算有效线索;另一份证词说嫌疑人花了几文钱买了几个桃子吃,根据日常经验,这个买桃子的钱可以算无关线索;
5、基于元芳处理后提供的线索,狄仁杰再行断案,例如,发现墙头的某处没有草,基于此线索调查后,发现是一只猫经常路过,排除此线索;发现大米有异味,调查后发现下过药,此线索成为破案关键证据。
元芳的作用:遍历所有数据,根据日常经验,初筛出不合情理的地方作为线索。
狄仁杰的作用:分析每个线索,排除合理存在,找出不合理存在。
这个过程用计算机角度描绘,将会是这个样子:
1、我们有30个正常航班的QAR数据,还有1份不安全事件QAR数据;
2、大部分数据和事件原因无关,需要初筛剔除;
3、所有数据需要遍历,才能找出线索,不能落下一个;
4、30个正常航班的数据构成了“日常经验”,用问题航班的数据逐条比对,可以初筛出线索;
5、基于线索数据,进一步分析其合理性,如果合理,则认为不是肇因,如果不合理,则很可能是肇因,需要专家做最后的分析。
所以,元芳之于狄仁杰,展昭之于包拯,根本就是服务器和前端的关系。这就不难理解头上那个增益天线的存在了。
算法分析
上述过程中,关键词是遍历、初筛、日常经验。
遍历是计算机的特长,人的弱项,目前的事故调查工作这项工作基本靠人,在算法的加持下从今以后应该交给计算机;
初筛是将事件参数和正常参数对比,找出异常数据,办法有两个:靠人的感觉,或者为数据建立标准。相信没有团队用后者,因为:
这是不可能做到的。为每一列QAR数据建立标准,最大多少,最小多少,哪些阈值需要告警,哪些阈值可以容忍;机型这么多,数据格式也不一样,尤其是各飞行阶段的同类数据(例如发动机EGT)可能大相径庭,建标准是个事倍功半的活儿。
那只能靠人的感觉了,实际上人的感觉,就是特定事件和日常经验的对比,和元芳的工作没有区别。使用算法,利用多个正常航班(越近似越好)数据本身,即可以构建航班飞行的“日常经验”,再用这个日常经验去对比不安全事件数据,来获取调查线索,而根本不需要建立标准。
其算法是AI基础算法中的聚类算法,前文曾描述过其基本原理,请参看:
简单地讲,想在班级里找出熊孩子,不能看分数和排名,要看聚类结果;同样的,数据是不是异常,看聚类结果,如果不安全事件的某条数据和正常航班聚类后,是大类中的一员,就说明正常;如果是小类中的一员,且小类中只有一员,那一定是断案线索,可以交给狄仁杰了。
因此,把元芳的活儿(遍历+聚类)交给计算机,可大幅缩减初筛线索的时间,从而大幅提高断案效率。
以下为核心代码,作用是将不同航班的同列数据进行聚类,输出的大类就是日常经验。验证方法:你可以在某次航班的五边拉一下减速板,回来后把本次航班的五边减速板角度数据列找出来,再找30个其他航班的同列数据,用这个方法算一下,结果将是:其他航班的数据堆在一堆,你的航班孤零零的在另一堆。
def Get_Clustering(cluster, n): # 欧几里何聚类函数(多列数据搓堆)
s = int(len(cluster) / n) # 均分切片
clu = []
for i in range(n - 1):
slide = cluster[s * i:s * (i + 1)] # 切分出簇
clu.append(slide) # 将簇列入组
slide = cluster[s * (n - 1):] # 最后一簇
clu.append(slide) # 所有簇的集合
while True: # 聚类过程
k = 0
ave = [Get_Average(clu[i]) for i in range(n)] # 计算各簇质心
for i in range(n): # 遍历各簇
for pos in clu[i]: # 遍历各点
posdis = [dist(pos, ave[m]) for m in range(n)] # 该点和各簇质心距离
posdis0 = dist(pos, ave[i]) # 该点和本簇质心距离
dismin = min(posdis) # 找到最小值
minindex = posdis.index(dismin) # 最小值所在位置
if minindex != i and posdis0 >dismin>0: # 如果距离本簇质心大于到其他质心距离
k = k + 1 # k值计数
clu[minindex].append(pos)
clu[i].remove(pos)
if k == 0: # 如果各簇不再变化,则输出结果
return (clu,ave)
小本本算大数据
我们知道,QAR、FDR的数据量是比较大的,通常在3000列上下,几千到几万行不等。一个航班这么大,31个航班,运算起来必须靠服务器了,身边的笔记本能不能玩呢?
答案是可以的,服务器胃口大,一次可以塞进全部数据;笔记本胃口小,可以少吃多餐啊!
QAR原始数据是csv格式,一列列非常整齐,可以把数据做预处理,读入一个航班的数据后,把每列数据做成单独的csv文件存入同一个文件夹,3000列的数据变为3000个csv,31个航班则变为31个文件夹。分析数据的时候每次从31个文件夹分别读取一个csv,这样的运算笔记本完全胜任。
切分文件可以用强大的Pandas来实现:
targetdf.to_csv(csvname, ',') # 目标数据表格存入csv
非数字的处理
QAR数据还包含了大量的文字信息,例如“ON”、“OFF”、“ARM”等等。
Matplotlib是支持直接按字串作图的,下图自动油门即为非数字格式:
然而,非数字格式不能用来聚类分析,所以需要全部转为数字。
还有一个问题:有些航段数据可能包含有ON、OFF,不包含ARM,有些则三种都包括,所以转为数字的时候要考虑所有数据包的同列数据内容,而不是只考虑本数据包。
具体方法如下:
1、读取所有数据包的同列数据;
2、去重;
list(set(list))
3、用去重后的列表的索引值取代同列数据中的原值;
4、重新保存各列csv覆盖原csv文件。
数据清洗的其他问题
做了几次试算后发现还有几个小问题,在这里一并描述:
1、部分数据存在杂质,跟踪后发现实际上不超过10种,把它们做进列表,碰到杂质即清除即可;
2、同一个数据,可能有多个传感器,此时可以分组查看而不是一个一个查看,这样可提高效率;处理手法上空客和波音的数据略有不同;
3、可能有的数据多几列或少几列,需要预先处理掉,确保所有数据包的表头一致。
工具的使用
估计很多人不太关心代码,却关心能不能用,这里提供打包好的工具和样例数据供下载试用。
执行顺序:
1、cut-wash.exe(仅一次)
2、preprocess.exe(仅一次)
3、QARMaster1.1.exe(可以反复运行,以观察结果)
数据说明:
q0:目标航班
q1-q9:正常航班
面板说明:
1、二簇和三簇的区别:相当于把孩子们分三堆还是两堆来分析;
2、关联度调整:目标数据包的结尾应该是不安全事件发生的那几秒,但是肇因通常会提前出现数据异常,因此可以逐步去掉数据包最后几秒的数据,以便更容易的发现问题线索。
下载方式:
1、链接:https://pan.baidu.com/s/1vD4Yh9LXRMT88wZg0ceNIw
2、提取码:83ib
本篇介绍的方法除了用于高效查找不安全事件原因的线索,还可以用于对正常航班的分析,例如新机型入列,每次航班后可以快速分析正常飞行中可能存在的异常数据,然后用分析结果来快速迭代,实现新机型的光速升级。
深入了解民航,请进入下列链接: