Разрешение мошеннических сообществ с помощью разрешения сущностей и обнаружения сообществ

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

Для этого мы определим некоторые правила разрешения сущностей (ER), которые позволят нам установить отношения между пользователями, которые, по нашему мнению, принадлежат к одному и тому же основному сообществу. Затем мы будем использовать алгоритм слабо связанных компонентов (WCC) для разрешения сообществ. И, наконец, мы пометим всех пользователей в сообществах, которые включают помеченные учетные записи, как подверженных риску мошенничества.

Технические ресурсы для воспроизведения этого анализа и анализа во всех других частях этой серии содержатся в этом репозитории GitHub, который включает записную книжку iPython и ссылку на набор данных.

Бизнес-правила разрешения юридических лиц (ER)

Теперь мы будем применять Entity Resolution (ER) для разрешения групп лиц за наборами учетных записей пользователей. Для этого анализа мы будем использовать довольно простую бизнес-логику ER. Если одно из двух приведенных ниже условий выполняется, мы разрешим две учетные записи пользователей, связав их вместе с новым типом отношений.

  1. Один пользователь отправил деньги другому пользователю, использующему ту же кредитную карту.
  2. Два пользователя совместно используют карту или устройство, подключенное к менее или равному 10 учетным записям, и эти два пользователя также имеют как минимум два других идентификатора типа кредитной карты, устройства или IP-адреса.

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

Для набора данных P2P мы не обязательно хотим помечать всех отправителей/получателей помеченных пользовательских транзакций как мошеннические, поскольку некоторые схемы мошенничества включают транзакции с жертвами. Кроме того, дополнительные идентификаторы, такие как IP, могут быть неточными, а карты и устройства могут контролироваться/использоваться мошенническим образом без разрешения владельца. Поэтому я использовал несколько строгие правила, соответствующие шаблонам, отмеченным в части 1. Мы можем применить отношения ER с Cypher:

# P2P with shared card rule
run(driver, '''
 MATCH (u1:User)-[r:P2P]->(u2)
 WITH u1, u2, count(r) AS cnt
 MATCH (u1)-[:HAS_CC]->(n)<-[:HAS_CC]-(u2)
 WITH u1, u2, count(DISTINCT n) AS cnt
 MERGE(u1)-[s:P2P_WITH_SHARED_CARD]->(u2)
 RETURN count(DISTINCT s) AS cnt
''')

[<Record cnt=6240>]

# Shared ids rule
run(driver, '''
 MATCH (u1:User)-[:HAS_CC|USED]->(n)<-[:HAS_CC|USED]-(u2)
 WHERE n.degree <= 10 AND id(u1) < id(u2)
 WITH u1, u2, count(DISTINCT n) as cnt
 MATCH (u1)-[:HAS_CC|USED|HAS_IP]->(m)<-[:HAS_CC|USED|HAS_IP]-(u2)
 WITH u1, u2, count(DISTINCT m) as cnt
 WHERE cnt > 2
 MERGE(u1)-[s:SHARED_IDS]->(u2)
 RETURN count(DISTINCT s) AS cnt
''')

[<Record cnt=5316>]

Использование компонентов слабой связи (WCC) для разрешения сообществ

Слабо связанные компоненты (WCC) — это практичный и хорошо масштабируемый алгоритм обнаружения сообществ. Это также детерминировано и вполне объяснимо. Он определяет сообщество просто как набор узлов, связанных подмножеством типов отношений в графе. Это делает WCC хорошим выбором для официального назначения сообщества в условиях обнаружения мошенничества в производственной среде.

Ниже мы запускаем WCC для пользователей через отношения ER, созданные выше:

clear_graph(driver, 'comm-projection')
run(driver, '''
    CALL gds.graph.create('comm-projection',
        ['User'],
        {
            SHARED_IDS: {orientation: 'UNDIRECTED'},
            P2P_WITH_SHARED_CARD: {orientation: 'UNDIRECTED'}
        }
    )
''')

run(driver, '''
    CALL gds.wcc.write('comm-projection', {
        writeProperty: 'wccId'
    }) YIELD writeMillis,
        nodePropertiesWritten,
        componentCount,
        componentDistribution
''')
[<Record writeMillis=104 nodePropertiesWritten=33732 componentCount=28203 componentDistribution={'p99': 3, 'min': 1, 'max': 175, 'mean': 1.196042974151686, 'p90': 2, 'p50': 1, 'p999': 8, 'p95': 2, 'p75': 1}>]

Было создано 28203 компонента. Большинство компонентов имеют размер 1, представляющий собой компонент только с одним пользователем, не разрешенным ни к какому другому. Максимальный размер компонента составляет 175 пользователей, что означает, что в самом большом сообществе 175 пользователей.

Маркировка учетных записей пользователей с риском мошенничества

Поскольку эти сообщества предназначены для маркировки основных групп лиц, если в сообществе есть хотя бы одна помеченная учетная запись, мы пометим все учетные записи пользователей в группе как риски мошенничества:

run(driver, '''
    MATCH (f:FlaggedUser)
    WITH collect(DISTINCT f.wccId) AS flaggedCommunities
    MATCH(u:User) WHERE u.wccId IN flaggedCommunities
    SET u:FraudRiskUser
    SET u.fraudRisk=1
    RETURN count(u)
''')

[<Record count(u)=452>]

Это дает нам в общей сложности 452 аккаунта с риском мошенничества, что означает, что если мы вычтем 241 уже помеченный аккаунт, мы идентифицируем 211 новыхаккаунтов пользователей с риском мошенничества.

Статистика сообщества WCC

Разбивка сообществ по размеру приведена ниже. Большинство из них представляют собой однопользовательские сообщества. Только небольшая часть имеет несколько пользователей, и из них размер сообщества в основном составляет 2 и 3. Большие сообщества встречаются редко. Однако, если мы посмотрим на учетные записи fraudUser, мы увидим, что большинство из них находятся в многопользовательских сообществах. 118 мошеннических учетных записей в сообществах с одним пользователем являются помеченными пользователями (через первоначальную логику возврата платежей), которые еще не были разрешены для сообщества.

result = run(driver, '''
    MATCH (u:User)
    WITH u.wccId AS community, count(u) AS cSize, sum(u.fraudRisk) AS cFraudSize
    WITH community, cSize, cFraudSize,
    CASE
    WHEN cSize=1 THEN ' 1'
    WHEN cSize=2 THEN ' 2'
    WHEN cSize=3 THEN ' 3'
    WHEN cSize>3 AND cSize<=10 THEN ' 4-10'
    WHEN cSize>10 AND cSize<=50 THEN '11-50'
    WHEN cSize>10 THEN '>50' END AS componentSize
    RETURN componentSize, 
        count(*) as numberOfComponents, 
        sum(cSize) AS totalUserCount, 
        sum(cFraudSize) AS fraudUserCount 
    ORDER BY componentSize
''')
pd.DataFrame([dict(record) for record in result])

Ниже приведены несколько примеров мошеннических сообществ, визуализированных в Neo4j Bloom. Пользователи, которые были помечены логикой первоначального возврата платежа, окрашены в красный цвет с заголовком = 1, а другие пользователи окрашены в оранжевый цвет с заголовком = 0. В целом вы заметите высокую степень перекрытия связности идентификаторов и транзакций P2P между пользователями, чего и следовало ожидать, учитывая наши правила ER.

Результаты маркировки риска мошенничества

Маркировка рисков мошенничества помогла выявить дополнительные 211 новыхаккаунтов пользователей с риском мошенничества,почти удвоив количество известных пользователей мошенников (увеличение на 87,5%). Мы также видим, что 65 процентов денег, поступающих на/с ранее помеченных счетов и других пользователей, могут быть отнесены к вновь выявленным счетам с риском:

run(driver, '''
    MATCH (:FlaggedUser)-[r:P2P]-(u)  WHERE NOT u:FlaggedUser
    WITH toFloat(sum(r.totalAmount)) AS p2pTotal
    MATCH (u:FraudRiskUser)-[r:P2P]-(:FlaggedUser) 
    WHERE NOT u:FlaggedUser
    WITH p2pTotal,  toFloat(sum(r.totalAmount)) AS fraudRiskP2pTotal
    RETURN round((fraudRiskP2pTotal)/p2pTotal,3) AS p
''')[0].get('p')

0.652

Кроме того, несмотря на то, что 211 вновь выявленных учетных записей составляют менее 1 процента от общего числа пользователей в выборке, 12,7 процента от общей суммы P2P в выборке включали вновь выявленные учетные записи в качестве отправителей или получателей:

run(driver, '''
    MATCH (:User)-[r:P2P]->()
    WITH toFloat(sum(r.totalAmount)) AS p2pTotal
    MATCH (u:FraudRiskUser)-[r:P2P]-() WHERE NOT u:FlaggedUser
    WITH p2pTotal, toFloat(sum(r.totalAmount)) AS fraudRiskP2pTotal
    RETURN round((fraudRiskP2pTotal)/p2pTotal,3) AS p
''')[0].get('p')
0.127

Наконец, мы видим улучшение в различении карт и устройств, поскольку гораздо больше карт и устройств используются исключительно учетными записями с риском мошенничества.

Совокупная статистика P2P в сочетании с улучшениями в показателях карт и устройств имеет большое значение, учитывая ограниченный масштаб ранее выявленного мошенничества, которое было сосредоточено на возвратных платежах. Эти результаты убедительно свидетельствуют о том, что за возвратными платежами стоят более сложные сети мошеннических денежных потоков, а не за возвратными платежами.

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