目录
- 1. 日志数据读取及预处理
- (1)查看case和event数量
- (2)查看起始事件和结束事件
- (3)时间戳格式的问题
- 2. 日志数据过滤
- 3. 流程发现
- 4. 模型转化
- 5. 模型可视化
1. 日志数据读取及预处理
通过 pandas库 读取csv文件,每一行代表一条活动记录,一般必须要有的信息是 case_id 事件id , activity_name 活动名称,time 时间戳,此外还可以包含 事件类型、活动成本等额外的信息以供进一步分析。pm4py官网提供了一个小样本数据集可用于探索该库的使用。
case_id;activity;timestamp;costs;resource
3;register request;2010-12-30 14:32:00+01:00;50;Pete
3;examine casually;2010-12-30 15:06:00+01:00;400;Mike
3;check ticket;2010-12-30 16:34:00+01:00;100;Ellen
3;decide;2011-01-06 09:18:00+01:00;200;Sara
3;reinitiate request;2011-01-06 12:18:00+01:00;200;Sara
(1)查看case和event数量
数据读取完成之后,可以获取该事件日志的一些基本信息。注意:这里 case/ trace 表示一个案例,即一次完整的流程,每个case_id 对应了很多可分隔的步骤(也即具体的 事件event / 活动activity) 。后面不再强调这一点,但都会按照这种方式进行叙述,因此需要明确区分 case 和 event 。
event_log = pandas.read_csv(file_path, sep=';') # 读取日志文件
num_events = len(event_log) # 获取日志文件的活动数目
num_cases = len(event_log.case_id.unique()) # 查看有多少次完整的案例记录
(2)查看起始事件和结束事件
此外,通过pm4py提供的函数还可以查看开始活动和结束活动都是哪些。
# 指定case_id,activity_key,timestamp_key分别对应哪个数据列
event_log = pm4py.format_dataframe(event_log, case_id='case_id', activity_key='activity',
timestamp_key='timestamp')
start_activities = pm4py.get_start_activities(event_log) # 起始事件
end_activities = pm4py.get_end_activities(event_log) # 结束事件
print("Start activities: {}\nEnd activities: {}".format(start_activities, end_activities))
pm4py.format_dataframe
将数据表转换为pm4py中的通用格式,它会创建事件日志的副本,并将分配的列重命名为pm4py中使用的标准列名,列case_id会重命名为case:concept:name
,activity 列重命名为concept:name
,timestamp列重命名为time:timestamp
。
pm4py.get_start_activities
和pm4py.get_end_activities
函数返回一个字典,给出起始事件及结束事件分别出现在第一个和最后一个的次数。
(3)时间戳格式的问题
PM4Py利用内置的panda函数自动检测输入数据中的时间戳格式。但是,pandas 会孤立地查看每一行中的时间戳值。这就存在一些问题,如果提供的值是2020-01-18,即,首先是年份,然后是月份,然后是日期,在某些情况下,2020-02-01的值可能被错误地解释为1月2日,即,而不是2月1日。为了解决这个问题,可以向format_dataframe()方法提供一个额外的参数 times_format 。在本例中,时间戳格式为%Y-%m-%d%H:%m:%S%z。通常建议指定时间戳格式。
2. 日志数据过滤
现实中的日志数据通常是复杂、多变、有噪声的,为了得到良好的过程模型,有必要对数据进行仔细的过滤,PM4Py中有各种预构建的过滤器来实现这个需求。
- filter_start_activities(log, activities, retain=True) :此函数根据给定的起点事件过滤事件日志对象。
activities
用于指定所关注的 起始事件 的集合;retain
设置为True 表示 保留所有以activities
中的事件开头的case,为 False 则删除所有以activities
中的事件开头的case。 activities 和 retain这两个参数在其他函数中也是一样的,因此后面不再介绍。 - filter_end_activities(log,activities,retain=True):根据给定的终点事件过滤事件日志对象。
- filter_event_attribute_values(log,attribute_key,values,level=“case”,retain=True):根据事件属性过滤事件日志。
attribute_key
是表示要筛选的属性键的字符串,values
参数指定一组允许的值。如果level
参数设置为“case”,表示在case-level进行属性值的过滤,一个case所包含的多个event中,至少一个event的属性值满足要求,那么整个case的所有事件都将被保留。如果level
参数值设置为“event”,则只保留属性为指定值的事件。 - filter_trace_attribute_values(log,attribute_key,values,retain=True):仅保留(如果retain设置为False,则删除)具有所提供attribute_key的属性值并列在相应值集合中的跟踪。
- filter_variants(log,variants,retain=True):保留 满足特定执行顺序 的轨迹。例如,在大型日志中,我们希望保留描述执行序列“a”、“b”、“c”的所有轨迹。
variations
参数是活动名称列表的集合,例如variations=[['a','b','c']]
。 - filter_directly_follows_relation(log,relationship,retain=True):此函数筛选包含指定“直接跟随关系”的所有轨迹。这样的关系只是一对活动,例如
('a', 'b')
表示在轨迹中’a’后面直接跟着 ‘b’ ,轨迹<'a','b','c','d'>
包含直接跟在后面的对(‘a’,‘b’),(‘b’,‘c’)和(‘c’,‘d’)。relationship
参数是一组元组,包含活动名称。 - filter_eventually_follows_relation(log,relationship,retain=True):此函数的跟随关系更宽松,允许两个活动之间有其他的活动,只需要这两个活动的前后关系满足要求即可。例如,当我们调用具有关系
(“a”, “b”)
的函数时,在某个点观察到活动“a”,在之后某个点观察到活动“b”即可。 - filter_time_range(log, dt1, dt2, mode=’events’) :根据时间戳 dt1 和 dt2 定义的给定时间范围过滤事件日志。时间戳的格式应为
datetime.datetime
。筛选器有三种模式(默认为“events”):‘events’
:保留在时间范围之内的事件‘traces_contained’
:保留完全在时间范围之内的轨迹‘traces_intersecting’
:保留至少有一个事件在时间范围之内的轨迹
filtered = pm4py.filter_start_activities(log, {'register request'})
filtered = pm4py.filter_start_activities(log, {'register request TYPO!'})
filtered = pm4py.filter_end_activities(log, {'pay compensation'})
filtered = pm4py.filter_event_attribute_values(log, 'org:resource', {'Pete', 'Mike'})
filtered = pm4py.filter_event_attribute_values(log, 'org:resource', {'Pete', 'Mike'}, level='event')
filtered = pm4py.filter_trace_attribute_values(log, 'concept:name', {'3', '4'})
filtered = pm4py.filter_trace_attribute_values(log, 'concept:name', {'3', '4'}, retain=False)
filtered = pm4py.filter_variants(log, [
['register request', 'check ticket', 'examine casually', 'decide', 'pay compensation']])
filtered = pm4py.filter_variants(log, [
['register request', 'check ticket', 'examine casually', 'decide', 'reject request']])
filtered = pm4py.filter_directly_follows_relation(log, [('check ticket', 'examine casually')])
filtered = pm4py.filter_eventually_follows_relation(log, [('examine casually', 'reject request')])
filtered = pm4py.filter_time_range(log, dt.datetime(2010, 12, 30), dt.datetime(2010, 12, 31), mode='events')
filtered = pm4py.filter_time_range(log, dt.datetime(2010, 12, 30), dt.datetime(2010, 12, 31),
mode='traces_contained')
filtered = pm4py.filter_time_range(log, dt.datetime(2010, 12, 30), dt.datetime(2010, 12, 31),
mode='traces_intersecting')
3. 流程发现
流程发现模块用于从事件日志中生成流程模型,pm4py实现了多种流程发现算法,并且可以生成不同种类的过程模型。PM4Py目前支持三种不同的流程建模符号,分别是:
- BPMN,即 Business Process Modeling Notation;
- Petri网,Petri网是一种更加数学化的建模表示,Petri网的行为通常更难理解,然而由于其数学性质,Petri网通常不那么模糊。在本教程中,我们将主要关注BPMN模型和流程树。
- 过程树 Process Tree,过程树表示Petri网的严格子集,并以分层的方式描述过程行为。
pm4py中的流程发现根据所使用的 算法 和 模型 对应着不同的函数,具体如下表所示(表中只是其中部分),然后本文会对这些函数的使用方法和参数进行具体的介绍:
- discover_petri_net_alpha()(这类函数一般都需要下面四个参数,因此后面省略不再介绍)
- log: Union[EventLog, DataFrame] 事件日志
- activity_key: str = ‘concept:name’ ,指定活动名称列
- timestamp_key: str = ‘time:timestamp’,指定表示时间的列
- case_id_key: str = ‘case:concept:name’) ,指定轨迹 id 列
- Return type:
Tuple[PetriNet, Marking, Marking]
- discover_petri_net_ilp()
- alpha(float):序列编码图 (sequence encoding graph)的噪声阈值,1.0=no filtering, 0.0=greatest filtering
- Return type:
Tuple[PetriNet, Marking, Marking]
- discover_petri_net_inductive()
- noise_threshold (float) :噪声阈值 (default: 0.0)
- multi_processing (bool) :boolean that enables/disables multiprocessing in inductive miner(?)
- discover_petri_net_heuristics()
- dependency_threshold (float) : dependency threshold (default: 0.5)
- and_threshold (float): AND threshold (default: 0.65)
- loop_two_threshold (float) :loop two threshold (default: 0.5)
- discover_process_tree_inductive()
- noise_threshold (float) : noise threshold (default: 0.0)
- multi_processing (bool) :boolean that enables/disables multiprocessing in inductive miner
- Return type:
ProcessTree
- discover_heuristics_net()
- dependency_threshold (float) : dependency threshold (default: 0.5)
- and_threshold (float): AND threshold (default: 0.65)
- loop_two_threshold (float) :loop two threshold (default: 0.5)
- min_act_count (int):活动的最小发生次数,大于该阈值才会纳入模型中
- min_dfg_occurrences (int):活动的最小发生次数,大于该阈值才会被作为DFG的一条弧
- decoration (str) :弧上的标注 可选 ‘frequency’ 频率 或 ‘performance’ 性能)
- Return type:
HeuristicsNet
- discover_bpmn_inductive()
- noise_threshold (float) : noise threshold (default: 0.0)
- multi_processing (bool) :boolean that enables/disables multiprocessing in inductive miner
- Return type:
BPMN
4. 模型转化
在介绍绘图之前,先介绍一下各个流程模型之间的转化。pm4py的convert模块提供了多种函数实现 petri 网,过程树,BPMN等模型的转换。
- convert_to_bpmn():输入 petri net 或process tree,返回BPMN
- convert_to_petri_net() :输入BPMN 或process tree,返回 petri net
- convert_to_process_tree():输入BPMN 或 petri net ,返回process tree
process_tree = pm4py.discover_process_tree_inductive(log) # 流程树
bpmn_model = pm4py.convert_to_bpmn(process_tree) # 将流程树转换为BPMN
5. 模型可视化
- view_petri_net()
- petri_net (PetriNet):传入要绘制的petri网
- initial_marking : Initial marking 起始标记 im
- final_marking:Final marking 终点标记 fm(im和fm在前面使用流程发现函数时会随着petri网一起生成三元组)
- format (str) :输出图片的格式
- bgcolor (str) :背景颜色,默认白色(default: white)
- decorations :与Petri网元素相关的装饰(颜色、标签)
- debug (bool):启用 / 禁用debug模式
- save_vis_petri_net()
- 参数同上,但是多了一个 file_path 用于指定文件保存位置
BPMN,过程树绘制的函数也都类似,view_xxxx() 用于模型可视化展示,save_vis_xxxx() 用于文件保存,一般可以设置 format 文件类型 和 bgcolor背景颜色。
net, im, fm = pm4py.discover_petri_net_inductive(dataframe, activity_key='concept:name',
case_id_key='case:concept:name',
timestamp_key='time:timestamp')
pm4py.view_petri_net(net, im, fm, format='svg')