Анализ бизнес-процессов на основе данных с Process Mining

Process mining примеры курсы обучение, бизнес-анализ на основе данных, обучение бизнес-аналитиков

Что такое Process Mining или как из системных логов получить данные для оптимизации бизнес-процессов. Ликбез и практический пример процессной аналитики c Python-библиотекой PM4PY.

Что такое Process Mining

Для продвижения моего нового курса для бизнес-аналитиков и руководителем по управлению продуктами и процессами на основе данных, сегодня расскажу, что такое Process Mining и покажу практический пример анализа логов с помощью Python-библиотеки PM4PY.

Хотя термин Process Mining (PM) появился уже более 20 лет назад, этот подход к анализу и улучшению бизнес-процессов на основе системных логов, до сих пор реализован только в отдельных компаниях. Во многом это связано с недостаточным уровнем процессной зрелости и высокой долей ручных операций. Дополнительным препятствием для практического внедрения процессной аналитики может стать отсутствие дата-инженеров и корпоративных хранилищ данных.

Исходными данными для процессной аналитики являются логи прикладных информационных систем, где фиксируются все события пользовательского поведения и действия пользователей. Впрочем, PM-системы могут получать исходные данные не только из DWH, но и непосредственно из прикладных систем, если необходим мониторинг процессов в реальном времени. Результаты анализа обычно визуализируются на дэшбордах, показывая графы выполнения пользовательских действий и статистику событий. Также многие системы формируют список рекомендаций для улучшения исследованной деятельности.

Принцип работы систем класса Process Mining
Принцип работы систем класса Process Mining

К системам класса Process Mining относятся Proceset, Minit, ARIS Process Performance Manager, ProM, Celonis Process Mining. Также для процессной аналитики можно использовать специализированные библиотеки, например, Python-пакет интеллектуального анализа процессов PM4Py. Как работает, рассмотрим далее на примере XES-файла с событиями пользовательского поведения в процессе обработки заявки.

Практический пример анализа логов пользовательского поведения

В качестве входных данных для интеллектуального анализа процессов Python-пакет PM4Py принимает файлы форматов CSV и XES, который специально разработан для хранения событийных логов процессной аналитики. Формат XES (eXtensible Event Stream) основан на XML и более предпочтителен по сравнению с CSV — простым табличным форматом без иерархической структуры. XES поддерживает вложенные структуры, позволяя моделировать сложные процессы с различными атрибутами событий, легко расширяется новыми атрибутами и элементами без нарушения общей структуры файла. Также XES позволяет включать метаданные о самом логе: описание процесса, источник данных и прочие важные характеристики.

Кроме того, XES поддерживает различные типы данных для атрибутов событий (строки, числа, даты), что повышает точность и надежность анализа. Также XES эффективно обрабатывает временные метки и последовательности событий, что критично для анализа процессов. Наконец, многие специализированные PM-инструменты оптимизированы для работы с XES-файлами, хотя поддерживают и CSV.

Структура XES-файла состоит из следующих основных элементов:

  • Трейсы (Traces) — последовательности событий, связанных с конкретными экземплярами процесса. Каждый трейс начинается с уникального идентификатора.
  • События (Events) — отдельные шаги или действия внутри трейса. Каждое событие может содержать различные атрибуты: название события, временные метки, ответственные ресурсы и другие данные.
  • Глобальные атрибуты (Global Attributes) — общие свойства, применяемые ко всему журналу, например, информация о модели или источнике данных.

Для рассматриваемого примера я сгенерировала такой XES-файл:

<?xml version="1.0" encoding="UTF-8"?>
<log>
  <trace>
    <string key="concept:name" value="Трасса_1" />
    <event>
      <string key="concept:name" value="принять заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-01T09:00:00" />
      <date key="timestamp:end" value="2025-02-01T09:30:00" />
      <date key="time:timestamp" value="2025-02-01T09:00:00" />
    </event>
    <!-- XOR-разветвление -->
    <event>
      <string key="concept:name" value="взять заявку в работу" />
      <string key="concept:position" value="пресейл-аналитик" />
      <date key="timestamp:start" value="2025-02-01T09:31:00" />
      <date key="timestamp:end" value="2025-02-01T09:45:00" />
      <date key="time:timestamp" value="2025-02-01T09:31:00" />
    </event>
    <event>
      <string key="concept:name" value="открыть карточку клиента" />
      <string key="concept:position" value="пресейл-аналитик" />
      <date key="timestamp:start" value="2025-02-01T09:46:00" />
      <date key="timestamp:end" value="2025-02-01T10:00:00" />
      <date key="time:timestamp" value="2025-02-01T09:46:00" />
    </event>
    <event>
      <string key="concept:name" value="завершить заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-01T10:01:00" />
      <date key="timestamp:end" value="2025-02-01T10:15:00" />
      <date key="time:timestamp" value="2025-02-01T10:01:00" />
    </event>
  </trace>

  <trace>
    <string key="concept:name" value="Трасса_2" />
    <event>
      <string key="concept:name" value="принять заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-02T09:00:00" />
      <date key="timestamp:end" value="2025-02-02T09:30:00" />
      <date key="time:timestamp" value="2025-02-02T09:00:00" />
    </event>
    <!-- XOR-разветвление -->
    <event>
      <string key="concept:name" value="отклонить заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-02T09:31:00" />
      <date key="timestamp:end" value="2025-02-02T09:45:00" />
      <date key="time:timestamp" value="2025-02-02T09:31:00" />
    </event>
    <event>
      <string key="concept:name" value="завершить заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-02T09:46:00" />
      <date key="timestamp:end" value="2025-02-02T10:00:00" />
      <date key="time:timestamp" value="2025-02-02T09:46:00" />
    </event>
  </trace>

  <!-- Трасса с AND-разветвлением -->
  <trace>
    <string key="concept:name" value="Трасса_3" />
    <event>
      <string key="concept:name" value="принять заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-03T09:00:00" />
      <date key="timestamp:end" value="2025-02-03T09:30:00" />
      <date key="time:timestamp" value="2025-02-03T09:00:00" />
    </event>
    <!-- AND-разветвление: параллельные действия -->
    <event>
      <string key="concept:name" value="проверить документы" />
      <string key="concept:position" value="менеджер проекта" />
      <date key="timestamp:start" value="2025-02-03T09:31:00" />
      <date key="timestamp:end" value="2025-02-04T09:45:00" />
      <date key="time:timestamp" value="2025-02-03T09:31:00" />
    </event>
    <event>
      <string key="concept:name" value="согласовать бюджет" />
      <string key="concept:position" value="менеджер проекта" />
      <date key="timestamp:start" value="2025-02-03T09:31:00" />
      <date key="timestamp:end" value="2025-02-13T09:50:00" />
      <date key="time:timestamp" value="2025-02-03T09:31:00" />
    </event>
    <!-- Слияние после параллельных действий -->
    <event>
      <string key="concept:name" value="завершить заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-03T09:51:00" />
      <date key="timestamp:end" value="2025-02-03T10:00:00" />
      <date key="time:timestamp" value="2025-02-03T09:51:00" />
    </event>
  </trace>

  <!-- Трасса с OR-разветвлением -->
  <trace>
    <string key="concept:name" value="Трасса_4" />
    <event>
      <string key="concept:name" value="принять заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-04T09:00:00" />
      <date key="timestamp:end" value="2025-02-04T09:30:00" />
      <date key="time:timestamp" value="2025-02-04T09:00:00" />
    </event>
    <!-- OR-разветвление: выбор нескольких опций -->
    <event>
      <string key="concept:name" value="провести анализ рисков" />
      <string key="concept:position" value="бизнес-аналитик" />
      <date key="timestamp:start" value="2025-02-04T09:31:00" />
      <date key="timestamp:end" value="2025-02-09T09:50:00" />
      <date key="time:timestamp" value="2025-02-04T09:31:00" />
    </event>
    <event>
      <string key="concept:name" value="провести исследование рынка" />
      <string key="concept:position" value="бизнес-аналитик" />
      <date key="timestamp:start" value="2025-02-07T09:31:00" />
      <date key="timestamp:end" value="2025-02-11T09:45:00" />
      <date key="time:timestamp" value="2025-02-04T09:31:00" />
    </event>
    <!-- Объединение после OR-разветвления -->
    <event>
      <string key="concept:name" value="завершить заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-04T09:51:00" />
      <date key="timestamp:end" value="2025-02-04T10:00:00" />
      <date key="time:timestamp" value="2025-02-04T09:51:00" />
    </event>
  </trace>

  <!-- Дополнительные трассы для полноты логики процесса -->
  <trace>
    <string key="concept:name" value="Трасса_5" />
    <event>
      <string key="concept:name" value="принять заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-05T09:00:00" />
      <date key="timestamp:end" value="2025-02-05T09:20:00" />
      <date key="time:timestamp" value="2025-02-05T09:00:00" />
    </event>
    <event>
      <string key="concept:name" value="открыть карточку заявки" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-05T09:21:00" />
      <date key="timestamp:end" value="2025-02-05T09:40:00" />
      <date key="time:timestamp" value="2025-02-05T09:21:00" />
    </event>
    <event>
      <string key="concept:name" value="взять заявку в работу" />
      <string key="concept:position" value="пресейл-аналитик" />
      <date key="timestamp:start" value="2025-02-05T09:41:00" />
      <date key="timestamp:end" value="2025-02-05T10:00:00" />
      <date key="time:timestamp" value="2025-02-05T09:41:00" />
    </event>
    <event>
      <string key="concept:name" value="завершить заявку" />
      <string key="concept:position" value="клиентский менеджер" />
      <date key="timestamp:start" value="2025-02-05T10:01:00" />
      <date key="timestamp:end" value="2025-02-05T10:20:00" />
      <date key="time:timestamp" value="2025-02-05T10:01:00" />
    </event>
  </trace>
</log>

Предположим, это сырая выгрузка из CRM-системы, где работают различные специалисты, принимая, маршрутизируя и выполняя пользовательские заявки. Регламент процесса отсутствует или неактуален. Поэтому получим BPMN-диаграмму процесса на основе реальных данных, построив ее с помощью Python-библиотеки PM4Py из событий этого лог-файла.

Чтобы вы могли повторить это упражнение без установки дополнительного ПО, в качестве среды разработки можно использовать Google Colab.

Сперва установим библиотеки и импортируем модули.

!pip install pm4py pandas
import pm4py
from pm4py.objects.log.importer.xes import importer as xes_importer
from collections import defaultdict
import statistics

Далее загрузим исходный XES-файл в пользовательскую директорию.

Импорт исследуемого лог-файла в Google Colab
Импорт исследуемого лог-файла в Google Colab

Наконец, напишем и запустим код для анализа логов и построения BPMN-диаграммы:

# Функция для форматирования длительности
def format_duration(minutes):
    if minutes > 90:
        days = minutes // (24 * 60)
        minutes_rem = minutes % (24 * 60)
        hours = minutes_rem // 60
        minutes_final = minutes_rem % 60
        parts = []
        if days > 0:
            parts.append(f"{int(days)} дн.")
        if hours > 0:
            parts.append(f"{int(hours)} ч.")
        if minutes_final > 0:
            parts.append(f"{int(minutes_final)} мин.")
        return ' '.join(parts)
    else:
        return f"{round(minutes, 2)} мин"

# Импорт XES-лога
log = xes_importer.apply('/content/log_4_article.xes')

# Вычислим среднюю длительность каждого действия
activity_durations = defaultdict(list)

for trace in log:
    for event in trace:
        start_time = event.get('time:timestamp')
        # есть отдельные атрибуты для начала и конца события
        end_time = event.get('timestamp:end')
        if end_time:
            duration = (end_time - start_time).total_seconds() / 60  # в минутах
            activity_durations[event['concept:name']].append(duration)

average_durations = {activity: statistics.mean(durations) 
                     for activity, durations in activity_durations.items()}

# Определим исполнителей для каждого действия
activity_performers = defaultdict(set)

for trace in log:
    for event in trace:
        performer = event.get('concept:position', 'Неизвестно')
        activity_performers[event['concept:name']].add(performer)

# Дополняем названия действий
for trace in log:
    for event in trace:
        activity = event['concept:name']
        performers = ", ".join(activity_performers[activity])
        avg_duration_minutes = average_durations[activity]
        formatted_duration = format_duration(avg_duration_minutes)
        # Обновляем название действия с форматированной длительностью
        event['concept:name'] = (
            f"Задача: {activity}\n\n"
            f"Исполнитель: {performers}\n"
            f"Средняя длительность: {formatted_duration}"
        )

# Создаем BPMN-модель и визуализируем её
bpmn_model = pm4py.discover_bpmn_inductive(log)
pm4py.view_bpmn(bpmn_model)

В результате выполнения кода получим BPMN-диаграмму.

Запуск Python-скрипта в Google Colab
Запуск Python-скрипта в Google Colab

К сожалению, PM4Py не поддерживает весь многообразный алфавит нотации BPMN, не позволяя показать промежуточные события, различные шлюзы, кроме XOR, пулы и дорожки. Однако, полученная диаграмма довольно наглядно показывает логику выполнения процесса, позволяя сформировать гипотезы о возможностях его улучшения.

BPMN-диаграмма бизнес-процесса, полученная из системного лога
BPMN-диаграмма бизнес-процесса, полученная из системного лога

Как это сделать, а также какие еще возможности для процессного анализа и совершенствования предоставляет подход Process Mining и его реализация в PM4Py, вы узнаете на моем новом курсе Школы прикладного бизнес-анализа и проектирования информационных систем в нашем лицензированном учебном центре обучения и повышения квалификации системных и бизнес-аналитиков в Москве: