Анализ процессов, Графы

Расширяем информативность связей графа в NetworkX

Время прочтения: 3 мин.

Рассмотрим пример обнаружения мошенничества.
У нас есть база данных клиентов, и мы хотим знать, как они связаны друг с другом. Мы знаем, что некоторые клиенты участвуют в сложной структуре мошенничества и если мы будем рассматривать таких клиентов индивидуально, то можем не увидеть признаков, доказывающих факт мошенничества. Такие мошенники могут быть похожи на обычных клиентов.
Работа со связями между пользователями может быть более информативна, чем анализ каждого клиента в отдельности. Например, некоторые признаки не считаются рискованными для обычной оценки (номер телефона, адрес электронной почты, домашний адрес), но могут стать критичными при анализе на основе графа.
Приведём пример: четыре человека с повторяющимися номерами телефонов. Некоторые из них связаны с другими клиентами по одному адресу электронной почты. Как мы понимаем, номер телефона сам по себе даёт мало информации если использовать классические методы анализа, но при анализе с помощью графов мы видим, что люди связаны между собой через одни и те же значения телефонных номеров или значения адресов электронной почты, и это может нести риски.

IDNamePhone numberEmail
1Степан Иванов+111 12 34 56 78феликс@gmail.com
2Евгений Демьянов+111 00 00 00 00дюран@gmail.com
3Иван Кузнецов+111 12 34 56 78кастом@gmail.com
4Юлия Попова+123 99 99 99 99Null
5Светлана Брилова+123 0123 4567кастом@gmail.com
6Кирилл Устинин+123 0123 4567Null

Для построения графа мы настроим связи между клиентами по номеру телефона:

IDID_2Phone number
13+111 12 34 56 78
56+123 0123 4567

И по электронной почте:

IDID_2Email
35кастом@gmail.com

Теперь построим граф с помощью простейшей функции nx.draw (G):

%matplotlib inline

nx.draw(G)

Простой граф отражает связи в общем смысле. Для наибольшей информативность мы добавим разные типы ссылок между клиентами и подписи самих клиентов:

def draw(f):
    stnd = nx.spring_layout(f, scale=0.5)
    nod_lab = dict((m,h['Name']) for m,h in f.nodes(data=True))
    nx.draw(f, pos=stnd, width=e_sizes(f), edge_color=e_colors(f), alpha=0.8, arrows=True,                           node_color='lightgrey', node_size=400,labels=nod_lab, font_color='black', font_size=8, font_weight='bold')  
    labels_e = dict(((b,d),list(e.values())[0]) for b,d,e in G.edges(data=True))
    nx.draw_networkx_edge_labels(G, stnd, edge_labels = labels_e, font_size=8)

Пример графа с большим количеством вершин с применением созданной функции визуализации: Draw(G)

Как мы видим, представление всего графа при большом количестве вершин может быть не всегда удобным для анализа. В этом случае рекомендуется выделять подграфы с помощью функции ego_graph. На вход в n подается ID ноды (клиент) от которого исследуется связь и в radius – расстояние в нодах от n:

Draw(nx.ego_graph(G=G, n=int(df1[df1['Name'] == 'Степан Иванов'].ID), radius=3))

Благодаря нашей дополнительной функции мы видим какие клиенты связаны и по каким признакам связаны друг с другом.

В нашем случае интересны не клиенты сами по себе, а то как они связаны друг с другом. Визуализация при помощи графа помогает нам с этой задачей.

Советуем почитать