程式紀錄

【Neo4j】Fraud Detection實作

Neo4j Sandbox

看一下圖架構

CALL db.schema.visualization()

看label的數量

看關聯的數量

了解數據

Module #1: First-party Fraud

Synthetic identity fraud and first party fraud can be identified by performing entity link analysis to detect identities linked to other identities via shared PII.

There are three types of personally identifiable information (PII) in this dataset – SSN, Email and Phone Number

Our hypothesis is that clients who share identifiers are suspicious and have a higher potential to commit fraud. However, all shared identifier links are not suspicious, for example, two people sharing an email address. Hence, we compute a fraud score based on shared PII relationships and label the top X percentile clients as fraudsters.

We will first identify clients that share identifiers and create a new relationship between clients that share identifiers

Fraud detection workflow in Neo4j GDS

We will construct a workflow with graph algorithms to detect fraud rings, score clients based on the number of common connections and rank them to select the top few suspicious clients and label them as fraudsters.

  1. Identify clusters of clients sharing PII using a community detection algorithm (Weakly Connected Components)
  2. Find similar clients within the clusters using pairwise similarity algorithms (Node Similarity)
  3. Calculate and assign fraud score to clients using centrality algorithms (Degree Centrality) and
  4. Use computed fraud scores to label clients as potential fraudsters

創建投影圖

使用Native Projection

CALL gds.graph.project('wcc',// 投影圖的名稱
    // 投影客戶節點
    {
        Client: {
            label: 'Client'
        }
    },
    {
        SHARED_IDENTIFIERS:{
            type: 'SHARED_IDENTIFIERS', // 邊
            orientation: 'UNDIRECTED',  // 無向
            // 加入屬性至投影圖節點
            properties: {
                count: {
                    property: 'count'
                }
            }
        }
    }
) YIELD graphName,nodeCount,relationshipCount,projectMillis;

call gds.graph.drop(‘wcc’) 移除內存圖

Memory Estimation and Graph Projection

It is a good practice to run memory estimates before creating your graph to make sure you have enough memory to create an in-memory graph. For more information, click here: Memory Estimation

Named graphs can be created using either a Native projection or a Cypher projection. Native projections provide the best performance by reading from the Neo4j store files. Using Cypher projections is a more flexible and expressive approach with diminished focus on performance compared to the native projections. For more information, click here: Native and Cypher Projection

找到同社區的

CALL gds.wcc.stream('wcc',
    {
        nodeLabels: ['Client'],
        relationshipTypes: ['SHARED_IDENTIFIERS'],
        consecutiveIds: true
    }
)
YIELD componentId, nodeId
WITH componentId AS cluster, gds.util.asNode(nodeId) AS client
WITH cluster, collect(client.id) AS clients
WITH cluster, clients, size(clients) AS clusterSize WHERE clusterSize > 1
UNWIND clients AS client
MATCH (c:Client) WHERE c.id = client
SET c.firstPartyFraudGroup=cluster;

超過9個人共享信息

// 找到所有客戶,使用Cypher寫入
MATCH(c:Client) WHERE c.firstPartyFraudGroup is not NULL
WITH collect(c) as clients
MATCH(n) WHERE n:Email OR n:Phone OR n:SSN
WITH clients, collect(n) as identifiers
WITH clients + identifiers as nodes

// 客戶指向email phone ssn,
MATCH(c:Client) -[:HAS_EMAIL|:HAS_PHONE|:HAS_SSN]->(id)
WHERE c.firstPartyFraudGroup is not NULL
WITH nodes, collect({source: c, target: id}) as relationships

// 使用cyhper運行我投影的內存圖(4類節點)
CALL gds.graph.project.cypher('similarity',
    "UNWIND $nodes as n RETURN id(n) AS id,labels(n) AS labels",
    "UNWIND $relationships as r RETURN id(r['source']) AS source, id(r['target']) AS target, 'HAS_IDENTIFIER' as type",
    { parameters: {nodes: nodes, relationships: relationships}}
)
YIELD graphName, nodeCount, relationshipCount, projectMillis
RETURN graphName, nodeCount, relationshipCount, projectMillis

欺詐客戶跟交易人員

MATCH (c1:FirstPartyFraudster)-[]->(t:Transaction)-[]->(c2:Client)
WHERE NOT c2:FirstPartyFraudster
WITH c1, c2, sum(t.amount) AS totalAmount
SET c2:SecondPartyFraudSuspect
CREATE (c1)-[:TRANSFER_TO {amount:totalAmount}]->(c2);
MATCH (c1:FirstPartyFraudster)<-[]-(t:Transaction)<-[]-(c2:Client)
WHERE NOT c2:FirstPartyFraudster
WITH c1, c2, sum(t.amount) AS totalAmount
SET c2:SecondPartyFraudSuspect
CREATE (c1)<-[:TRANSFER_TO {amount:totalAmount}]-(c2);

Second-party Fraud

Our objective is to find out clients who may have supported the first party fraudsters and were not identified as potential first party fraudsters.

Our hypothesis is that clients who perform transactions of type Transfer where they either send or receive money from first party fraudsters are flagged as suspects for second party fraud.

To identify such clients, make use of TRANSFER_TO relationships and use this recipe:

  1. Use WCC (community detection) to identify networks of clients who are connected to first party fraudsters
  2. Use PageRank (centrality) to score clients based on their influence in terms of the amount of money transferred to/from fraudsters
  3. Assign risk score (secondPartyFraudScore) to these clients

CALL gds.wcc.stream('SecondPartyFraudNetwork')
YIELD nodeId, componentId
WITH gds.util.asNode(nodeId) AS client, componentId AS clusterId
WITH clusterId, collect(client.id) AS cluster
WITH clusterId, size(cluster) AS clusterSize, cluster
WHERE clusterSize > 1
UNWIND cluster AS client
MATCH(c:Client {id:client})
SET c.secondPartyFraudGroup=clusterId;
CALL gds.pageRank.stream('SecondPartyFraudNetwork',
    {relationshipWeightProperty:'amount'}
)YIELD nodeId, score
WITH gds.util.asNode(nodeId) AS client, score AS pageRankScore

WHERE client.secondPartyFraudGroup IS NOT NULL
        AND pageRankScore > 0 AND NOT client:FirstPartyFraudster

MATCH(c:Client {id:client.id})
SET c:SecondPartyFraud
SET c.secondPartyFraudScore = pageRankScore;

drop 內存圖

End of Module #2

In this module we accomplished the following tasks:

  1. Identified clusters of clients and first-party fraudsters transferring money between them
  2. Calculated second-party fraud score and identified second-party fraudsters

Unresolved directive in fraud-detection.adoc – include::scripts-end.txt[]