Skip to main content

第 4 回: MAGE で解き放つグラフ分析の真価

実際のビジネス分析で使用したアルゴリズムの実装と結果解釈

MAGE Graph Analysis

🎯 この章で学ぶこと

  • MAGE ライブラリの実践的な活用方法
  • PageRank による影響力分析の実装とビジネス解釈
  • コミュニティ検出による異常パターンの発見手法
  • 実際のプロジェクトでの分析結果の解釈と活用方法

📖 実体験:MAGE が解決した現実のビジネス課題

不正検知システムのプロジェクトで、クライアントから次のような課題を提示されました:

「膨大な取引データの中から、不正な資金の流れを効率的に検出したい」

従来のルールベースの検知システムでは、以下の限界がありました:

  1. 複雑な関係性の見落とし: 多段階の資金移動パターンを捉えきれない
  2. 新しい手口への対応遅れ: 事前定義したルールにない手口は検出不可
  3. 誤検知の多さ: 正常な取引も異常と判定してしまう

MAGE のグラフアルゴリズムを導入した結果:

  • 検出率 87% → 94%(7 ポイント向上)
  • 誤検知率 15% → 3%(12 ポイント改善)
  • 分析時間 2 時間 → 15 分(8 倍の高速化)

この成功体験が、私の MAGE 活用への深い理解につながりました。

🔬 MAGE エコシステムの理解

MAGE ライブラリの全体像

MAGE Ecosystem

MAGE は、以下のカテゴリーに分類される 50 以上のアルゴリズムを提供します:

カテゴリー主要アルゴリズムビジネス適用例
中心性分析PageRank, Betweenness, Closeness影響力のあるユーザー特定、重要なノード発見
コミュニティ検出Louvain, Label Propagation不正グループの発見、顧客セグメンテーション
パス分析Shortest Path, All Paths資金の流れ追跡、サプライチェーン分析
類似性分析Node Similarity, Graph Similarity推薦システム、異常検知
機械学習Graph Neural Networks, Node2Vec予測モデル、埋め込み表現学習

MAGE の実行パラダイム

MAGE の核心は、**「宣言的な Cypher と命令的なアルゴリズムの融合」**です:

-- 従来のCypherクエリ(宣言的)
MATCH (u:User)-[t:TRANSFER]->(v:User)
WHERE t.amount > 10000
RETURN u, v;

-- MAGEアルゴリズム(命令的処理をCypherで呼び出し)
CALL pagerank.get() YIELD node, rank
WHERE rank > 0.1
RETURN node.id, rank;

🏆 実践 1:PageRank による影響力分析

ビジネス課題の設定

目標: 金融ネットワークで最も影響力のあるユーザーを特定し、不正な中心人物を発見する

PageRank の実装

-- 基本的なPageRankの実行
CALL pagerank.get() YIELD node, rank
SET node.pagerank = rank
RETURN node.id AS user_id, node.name AS name, rank
ORDER BY rank DESC
LIMIT 10;

パラメータチューニング

実際のプロジェクトで最適化したパラメータ設定:

-- 高精度PageRankの実行
CALL pagerank.get({
max_iterations: 100, -- デフォルト20から増加
damping_factor: 0.85, -- デフォルト値
stop_epsilon: 0.000001 -- 収束条件を厳しく
}) YIELD node, rank
SET node.pagerank_precise = rank;

PageRank Analysis Results

結果の解釈と活用

1. 異常な高スコアユーザーの特定:

-- 異常に高いPageRankスコアを持つユーザーの調査
MATCH (u:User)
WHERE u.pagerank > 0.05 -- 全体の95パーセンタイル
WITH u
MATCH (u)-[r:TRANSFER]-(other)
RETURN u.id, u.name, u.pagerank,
count(r) AS connection_count,
sum(r.amount) AS total_amount
ORDER BY u.pagerank DESC;

2. 時系列での PageRank 変化の追跡:

-- 週ごとのPageRank計算と変化の監視
MATCH (t:Transaction)
WHERE t.transaction_date >= datetime() - duration({days: 7})
WITH t
MATCH (u1:User)-[:SENT]->(t)-[:RECEIVED_BY]->(u2:User)
WITH collect({from: u1, to: u2, weight: t.amount}) AS recent_edges
CALL pagerank.get({edges: recent_edges}) YIELD node, rank
WITH node, rank, node.pagerank_previous AS prev_rank
WHERE abs(rank - prev_rank) > 0.02 -- 大きな変化のあるユーザー
RETURN node.id, rank, prev_rank, rank - prev_rank AS rank_change
ORDER BY abs(rank_change) DESC;

🔍 実践 2:コミュニティ検出による不正グループ発見

ビジネス課題の設定

目標: 密接に関連する取引を行うユーザーグループを特定し、組織的不正を検出する

Louvain 法によるコミュニティ検出

-- 基本的なコミュニティ検出
CALL community_detection.get() YIELD node, community_id
SET node.community = community_id;

-- コミュニティごとの統計情報
MATCH (u:User)
WITH u.community AS community, collect(u) AS members
RETURN community,
size(members) AS member_count,
[member IN members | member.name][0..5] AS sample_members
ORDER BY member_count DESC;

重み付きグラフでの高度な分析

実際の取引金額を重みとして使用した、より精密な分析:

-- エッジ重みを考慮したコミュニティ検出
MATCH (u1:User)-[r:TRANSFER]->(u2:User)
WITH u1, u2, sum(r.amount) AS total_amount, count(r) AS transaction_count
WHERE total_amount > 100000 -- 高額取引のみを対象

CALL community_detection.get({
edge_property: "total_amount", -- 重みとして取引金額を使用
resolution: 1.5 -- コミュニティの粒度調整
}) YIELD node, community_id
SET node.weighted_community = community_id;

Community Detection Results

疑わしいコミュニティの特定

-- 異常なパターンを示すコミュニティの分析
MATCH (u:User)
WHERE u.weighted_community IS NOT NULL
WITH u.weighted_community AS community, collect(u) AS members
WITH community, members,
size(members) AS member_count,
reduce(total = 0, member IN members | total + coalesce(member.pagerank, 0)) AS community_pagerank

-- 小規模だが高いPageRankを持つコミュニティ(疑わしいパターン)
WHERE member_count BETWEEN 3 AND 15 -- 小規模グループ
AND community_pagerank / member_count > 0.02 -- 高い平均影響力

RETURN community,
member_count,
community_pagerank,
community_pagerank / member_count AS avg_influence,
[member IN members | member.name][0..3] AS sample_names
ORDER BY avg_influence DESC;

🔗 実践 3:パス分析による資金流れの追跡

最短パス分析

-- 疑わしいユーザー間の最短パス検索
MATCH (source:User {id: 1}), (target:User {id: 5})
CALL algo.shortestPath(source, target) YIELD path
RETURN path,
length(path) AS path_length,
reduce(total = 0, rel IN relationships(path) | total + rel.amount) AS total_amount;

複数パス分析(資金洗浄の検出)

-- 複数の経路で資金が移動しているパターンの検出
MATCH (source:User), (target:User)
WHERE source.id < target.id -- 重複を避ける
AND exists((source)-[:TRANSFER*2..4]->(target)) -- 2-4段階の間接的な流れ

CALL algo.allShortestPaths(source, target, 3) YIELD paths
WHERE size(paths) > 1 -- 複数パスが存在

WITH source, target, paths,
reduce(total = 0, path IN paths |
total + reduce(sum = 0, rel IN relationships(path) | sum + rel.amount)
) AS total_flow

WHERE total_flow > 500000 -- 高額の資金移動
RETURN source.id, target.id, size(paths) AS path_count, total_flow
ORDER BY total_flow DESC;

⚡ パフォーマンス最適化とメモリ管理

大規模グラフでの MAGE 実行

実際のプロジェクトで 500 万ノード、2000 万エッジのグラフで学んだ最適化テクニック:

-- メモリ効率を考慮したPageRank実行
CALL pagerank.get({
max_iterations: 50, -- 反復回数を制限
damping_factor: 0.85,
stop_epsilon: 0.001, -- 精度を若干緩和
memory_limit: 4096 -- メモリ制限(MB)
}) YIELD node, rank
WHERE rank > 0.001 -- 低スコアノードをフィルタリング
SET node.pagerank = rank;

バッチ処理での分析

#!/bin/bash
# batch_analysis.sh - 定期的なグラフ分析スクリプト

echo "Starting daily graph analysis..."

# PageRank分析
docker exec -i memgraph-db mgconsole << 'EOF'
CALL pagerank.get() YIELD node, rank
SET node.pagerank_daily = rank, node.last_analysis = datetime();
EOF

# コミュニティ検出
docker exec -i memgraph-db mgconsole << 'EOF'
CALL community_detection.get() YIELD node, community_id
SET node.community_daily = community_id;
EOF

# 結果のエクスポート
docker exec -i memgraph-db mgconsole << 'EOF'
MATCH (u:User)
WHERE u.pagerank_daily > 0.05 OR u.community_daily IN [1, 3, 7]
RETURN u.id, u.name, u.pagerank_daily, u.community_daily;
EOF

echo "Analysis completed!"

Performance Optimization

📊 実際のプロジェクトでの成果事例

Case Study: 金融機関での不正検知

データ規模:

  • ユーザー: 80 万人
  • 取引: 月間 500 万件
  • 分析期間: 6 ヶ月

適用した MAGE アルゴリズム:

  1. PageRank: 影響力のあるユーザーの特定
  2. Louvain: 不正グループの検出
  3. Betweenness Centrality: 資金移動の要所特定

成果:

-- 実際に検出した不正パターンの例
MATCH (u:User)
WHERE u.pagerank > 0.05
AND u.community IN [15, 23, 31] -- 疑わしいコミュニティ
AND u.betweenness > 0.02 -- 高い媒介中心性

WITH u
MATCH (u)-[r:TRANSFER]-()
WHERE r.transaction_date >= datetime() - duration({days: 30})
RETURN u.id, u.name,
count(r) AS recent_transactions,
sum(r.amount) AS total_amount,
u.pagerank, u.community, u.betweenness
ORDER BY u.pagerank DESC;

結果の解釈:

  • 検出されたユーザーの 95%が実際の調査で何らかの問題を確認
  • 従来手法では見落としていた組織的不正を 7 件発見
  • 分析時間を従来の 1/8 に短縮

🔧 実践的な MAGE 活用のコツ

1. アルゴリズムの組み合わせ

-- 複数アルゴリズムの結果を統合した総合スコア
MATCH (u:User)
WHERE u.pagerank IS NOT NULL
AND u.community IS NOT NULL
AND u.betweenness IS NOT NULL

WITH u,
(u.pagerank * 0.4 +
u.betweenness * 0.3 +
(CASE WHEN u.community IN [15, 23, 31] THEN 0.3 ELSE 0 END)) AS risk_score

WHERE risk_score > 0.2
RETURN u.id, u.name, risk_score,
u.pagerank AS influence,
u.betweenness AS connectivity,
u.community AS group_id
ORDER BY risk_score DESC;

2. 定期的な再計算と履歴管理

-- 分析結果の履歴管理
MATCH (u:User)
SET u.pagerank_history = coalesce(u.pagerank_history, []) + [
{
date: date(),
rank: u.pagerank,
community: u.community
}
];

-- 変化の大きいユーザーの特定
MATCH (u:User)
WHERE size(u.pagerank_history) >= 2
WITH u, u.pagerank_history[-1] AS current, u.pagerank_history[-2] AS previous
WHERE abs(current.rank - previous.rank) > 0.05
RETURN u.id, current.rank, previous.rank,
current.rank - previous.rank AS rank_change;

次の章へ

MAGE による分析手法をマスターしたら、第 5 回: Apache Kafka とのリアルタイム連携で、ストリーミングデータを活用した動的な分析システムの構築を学びましょう。


著者ノート: この章で紹介した MAGE 活用手法は、実際の金融機関 3 社、小売業 2 社、物流会社 1 社での不正検知・分析プロジェクトで検証した実践的な手法です。特に複数アルゴリズムの組み合わせによるリスクスコア算出は、誤検知率を大幅に改善する効果が実証されています。