用 Python 挖掘事故报告中的死亡人数#
今天用 Python 写一个函数,用来识别土木行业事故报告中的死亡人数。我的设计思路如下:
- 经过观察,80% 的事故报告中有关死亡人数的记录是有规律的,即 “XX 人死亡”,其中 XX 可能是汉语数字也可能是阿拉伯数字。
- 于是我设计出一个正则表达式,`pattern_death = r'([\d\w]+)(人死亡 | 名工人死亡)' 用以识别出这种模式。
- 对安徽省的几分调查报告的测试中,我发现这种识别模式会将 “XX 人死亡” 之前的文字也提取出来,比如 “该工程有 5 人死亡”,直到遇到标点符号,因为
([\d\w]+)
的含义是提取任意数量的汉字或数字。 - 于是我有设计出第二个正则表达式,
pattern_death_num = r'(\d+|[零一二两三四五六七八九十百千万]+)(人死亡|名工人死亡)'
,用以识别出上一种模式识别出的句子中的数字(无论是中文还是阿拉伯的)。 - 之后我又下载一个第三方库 cn2an ,将中文数字转换为数学数字。
- 将识别到的数字存放到字典中,没有识别到数字但文本中识别出 “死亡” 的做标记 “待确认”。
虽然我在这里描述的似乎很轻松,但是你无法知道的是,我从最开始的起点走到这个目的地用了多久,以及为了识别条件、避免报错、存放识别出的数据等而为函数设计的逻辑化了多久时间。
在报了许多次错误、迭代了多次之后,这个程序基本上能运行起来了,这个思路已经可以从 393 个事故报告中提取 393-56 份 死亡人数了。
你可能会好奇,图上显示的分明是 57 份文件 “待确认”,那么已提取到数据的数量不应该是 383-57 吗?
没错,这缺少的一份就是今天我要谈论的主角。
一字之差的工作量#
这一份数据一直在报错,我不得不在每个省份的文件之间依次测试,找出有问题的文件。
我发现出错的原因是:程序的确识别出了 “X 人死亡”,并且将 “X” 提取了出来,但报错的那份文件用的不是 “二人死亡”,而是是 “两人死亡”。cn2an 这个专门将表示数字的中文转化为阿拉伯数字的库,它只能识别 “二”,无法识别 “两”。
于是我又要设计出一个新的逻辑语句,如果识别出了 “两”,就将它改为 “二”,然后再用 cn2an
将其转化为阿拉伯数字。
我找到这个导致错误的原因并写出解决问题的语句,花了近半个小时。仅仅是一个字的偏差,为了使程序能够适应这种情况,却需要大量的测试。
我并非一个计算机专业的学生,我比较好奇的是,也许 “大量时间花费在解决报错上” 就是软件开发的常态?
言归正传,这是我们提取数据中很简单的一步,为了适配所有可能性,它的工作量并不小。
如果是从文本中提取 “事故性质” 这样的数据,也许描述 “事故性质” 的方式有多种多样(暂时我们不确定),不过它一定比数字要复杂,并且上下文可能没有特殊的格式,如果真是这样,单凭正则表达式可能已经无法完成目的了。
如果正则表达式无法解决这个问题,根据我目前掌握的信息来看,我们就需要复杂的 NLP 技术去识别出命名实体的词语、语义逻辑关系等,让机器理解句子,再将事故原因做分类。而这套规则,需要预设已知的数据库使代码能够理解。
如果我们真的使用 NLP 技术去提取所有事故报告中的 “事故原因”,那么为了做出一个适配所有情况的程序,其工作量一定非常大。
为什么这么费劲#
我们之所以在提取数据时这么费劲,是什么原因呢?
答案显而易见,事故报告中大部分信息的记录方式都没有统一的格式,如果格式能够统一,如果每个事故报告中都有一个统一的清单,那么每一种数据只需要一个正则表达式就能够提取出来了,并且对所有文件适配。
只可惜,在事故报告的格式上,没有像秦始皇统一六国的伟大节点。
现在 ChatGPT-4 应该可以自动提取出你所需的数据,只是需要充钱。而我们老师想让我们做一个自动识别的程序,只能说有点难,哈哈。
秦始皇统一六国#
秦始皇建立了中国历史上第一个统一的中央集权的封建国家,他不仅仅同意了中国,更重要的是他使书同文、车同轨、行同轮,统一文字、货币。
这些统一,不仅有利于信息的传递、规格的统一,也有助于我们中华文化的传承和发扬。
今天在写代码中遇到了这个 “两” 字引起的报错,以及对提取 “事故性质” 的工作量的思考,是否可以说明 ——统一的标准能在无形中解决许多问题呢?
我认为答案是肯定的。