-
Notifications
You must be signed in to change notification settings - Fork 419
时间语义解析 说明文档
- NLP 发展至今,始终都在做复杂规律与特征学习,从未真正做到理解文本的语义。想要真正做到语义级别的 NLP 系统,理解现实世界的时空至关重要。
- jionlp 时间语义解析即针对汉语时间文本,做规则解析,初步实现真正理解时间。
-
抛开相对论,人类使用时间几乎都属于线性时间串,所有时间点均匀排列
-
几乎所有具体时间的表达,均以某个时间点为基点进行表达。例如:“去年春节期间”,即以当下时间“2021年6月14日1点28分12秒”为基点做时间描述。
-
距离该时间基点越近,时间准确度越高,反之亦然。例如:“9000万年前”、“十多年前”等时间表达,时间距离当下时间基点往往很含糊,“昨天19点28分”则是准确、清晰的时间表达。
-
时间类型主要分为time_point(时间点)、time_span(时间范围)、time_period(周期性时间)、time_delta(时间段)
-
时间点描述某一个时间节点,例如“9月15号23点23分”、“前年腊月初八”等。
-
根据人的使用经验,时间点往往限制在日、时、分、秒(不绝对)。
-
时间点重点描述在该时间点发生了某件事。例如:“18时32分,歹徒袭击了南非议会大楼”。
-
时间点的判断往往要根据文本前后信息进行判断。特例如:“他在9月给菲菲过了个生日”。其中,9月持续时间较长,为时间范围,但在本句中,生日是9月的某一天,即句子的完整表达为“他在9月的某一天给菲菲过了个生日”。因此,此处对具体时间点的不确定,导致了“9月”的判定错误。
-
时间范围描述具体的一段时间,例如“三年前第一个季度”、“2020年4月1号到10月1号”等。
-
时间范围侧重描述该范围内持续发生了某件事。例如:“麦克从2004年9月到2007年6月在蒙卡私立中学读高中”。
-
同样地,时间范围往往带有模糊性,需要根据前后文进行判定。特例如:“阪神地震持续时间为1995年4月12日2时2分-4分”。本句中,尽管持续时间较短,长度为2分钟,但仍表达一段时间。
-
由上可知,time_point 和 time_span 本质上是相同的,由于人的主观理解而产生了区分。 基于以上考虑,本功能中,由于上下文的缺失,对于 time_point 和 time_span 的区分,仅根据时间字符串本身做区分,并不完全准确严格。
-
时间周期描述周期性的时间,例如“每年端午节”、“每隔30秒”、“9月6日-16日早上8点-中午12点”等。
-
时间周期的描述要素有三个,时间周期的频率,时间周期的持续时长,时间周期的起始点,例如:“每5分钟”,描述时间的出现频率为
5分钟
;而“每年9月至10月”,则在描述了时间频率为1年
的同时,还描述了持续时长为2个月
,以及起始点为9月1日
;“每年中秋节”,描述了时间周期的起始点为中秋节的0点0分
,持续时长为1天
时间。 -
频率、持续时长、起始点 在星期日期上难以描述。例如:“每周三下午5点”,起始点为 time_point 类型,但是 time_point 一般格式为
年月日时分秒
,不存在周
。 -
根据以上情况,我们对时间周期的解析,返回结果包括一个
delta
指明时间频率,point
指明一个具体的time_point
,它说明了时间的起始点和持续时长。
-
时间段描述抽象的一段时间,例如 “7天时间”、“24个小时零8分钟。”
-
时间段往往表述不确切的时间长度,因此与时间基点无关。但现实使用时,有大量的 time_delta 被转换为 time_span 使用。例如:“过半个小时”、“三十年前”、“两个月以后”、“前俩月”、“未来三天”、“第三周周日”、“90分钟以内”、“五年以来”等等。均需针对性进行解析。
输入时间表达字符串,返回其解析结果,包括type(时间类型)
、definition(准确度)
、time(详细解析结果)
。
>>> import time
>>> import jionlp as jio
>>> time_text_list = ['2021年前两个季度', '从2018年12月九号到十五号', '2019年感恩节', '每周六上午9点到11点', '30~90日']
>>> for time_text in time_text_list:
... print(jio.parse_time(time_text, time_base=time.time()))
# {'type': 'time_span', 'definition': 'accurate', 'time': ['2021-01-01 00:00:00', '2021-06-30 23:59:59']}
# {'type': 'time_span', 'definition': 'accurate', 'time': ['2018-12-09 00:00:00', '2018-12-15 23:59:59']}
# {'type': 'time_point', 'definition': 'accurate', 'time': ['2019-11-28 00:00:00', '2019-11-28 23:59:59']}
# {'type': 'time_period', 'definition': 'accurate',
'time': {'delta': {'day': 7}, 'point': {'time': ['2021-06-19 09:00:00', '2021-06-19 11:59:59'], 'string': '周六上午9点到11点'}}}
# {'type': 'time_delta', 'definition': 'blur', 'time': [{'day': 30.0}, {'day': 90.0}]}
-
type
指定了时间的类型,包括上述四种类型 -
definition
表示时间的准确度,取值包括[accurate|blur]
两种 -
输入参数除时间字符串外,还包括
time_base
,其指解析时间时指定的时间基点,可支持多种类型,包括time.time类型
、int时间戳
、arrow.arrow.Arrow类型
、float时间戳
、datetime.datetime类型
、list类型:[2017, 9, 12, 23, 12, 59]
、dict类型:{'year':1998, 'month':7, 'day':31, 'hour':6}
。 -
当前支持解析的时间字符串类型:(模糊、清晰)年月日、(模糊清晰)时分秒、星期、世纪、年代、月旬、节日、季节、季度、节气、农历月日、时间周期、时间段、法律时间、模糊时间代词等。
-
所有支持的测试用例见测试用例
-
parse_time
工具依赖正则,仅用于解析完整的时间字符串,保证解析的准确率,而不负责召回率。因此使用工具方法,首先需要使用【时间类型实体识别】将所有的文本中的时间实体抽取出来,然后一一进行解析。
7月15日 time_point ['2021-07-15 00:00:00', '2021-07-15 23:59:59']
今年上半年 time_span ['2021-01-01 00:00:00', '2021-06-30 23:59:59']
两年 time_delta {'year': 2.0}
一季度 time_span ['2021-01-01 00:00:00', '2021-03-31 23:59:59']
二季度 time_span ['2021-04-01 00:00:00', '2021-06-30 23:59:59']
上半年 time_span ['2021-01-01 00:00:00', '2021-06-30 23:59:59']
春节 time_point ['2021-02-12 00:00:00', '2021-02-12 23:59:59']
五一 time_point ['2021-05-01 00:00:00', '2021-05-01 23:59:59']
端午 time_point ['2021-06-14 00:00:00', '2021-06-14 23:59:59']
6月份 time_point ['2021-06-01 00:00:00', '2021-06-30 23:59:59']
16个月 time_delta {'month': 16.0}
从2018年至今 time_span ['2018-01-01 00:00:00', '2021-07-15 09:03:47']
每年 time_period {'delta': {'year': 1}, 'point': None}
1-5月份 time_span ['2021-01-01 00:00:00', '2021-05-31 23:59:59']
2020年1-5月份 time_span ['2020-01-01 00:00:00', '2020-05-31 23:59:59']
2021-07-15 09:03:47 time_point ['2021-07-15 09:03:47', '2021-07-15 09:03:47']
- 时分秒针对不同 time_base 的转换。
- ...