Anti-Money Laundering (AML) — антиотмывочная система, область где цена ошибки критична. Пропуск подозрительного перевода (false negative) грозит штрафами до 5% оборота по ФЗ-115. Ложная блокировка добросовестного клиента (false positive) — репутационные потери и иски. Традиционные правиловые системы детектируют только известные паттерны, генерируя до 95% ложных срабатываний. Мы разрабатываем гибридные AI-системы, которые снижают FPR на 20–40% без потери полноты обнаружения. Наш опыт — 10+ лет в финансовом ML для банков и финтехов.
В основе — комбинация детерминированных правил (для типовых сценариев) и ML-моделей (для выявления скрытых нелинейных паттернов). Ниже — архитектура, модели и этапы внедрения.
В этой статье мы разберём ключевые компоненты системы: транзакционный мониторинг, графовый анализ и интеграцию с KYC. Рассмотрим, как гибридный подход снижает нагрузку на комплаенс-отдел и соответствует требованиям FATF. Правила автоматически обрабатывают 80% операций, оставляя 20% на ML-проверку, что снижает ручной труд на 60%.
Почему ML лучше правиловых систем для AML?
| Характеристика | Правила | ML-модель |
|---|---|---|
| Обнаружение новых схем | Нет — только известные паттерны | Да — выявляет скрытые корреляции |
| Ложные срабатывания (FPR) | 5–10% | 2–4% (снижение в 2–5 раз) |
| Адаптация к изменениям | Ручное обновление | Автоматическое переобучение |
| Объяснимость | Полная (если правило задано явно) | Через SHAP/LIME |
| Масштабируемость | Линейно от числа правил | Параллельная обработка |
Типология схем отмывания
Структурирование (Smurfing): крупная сумма разбивается на мелкие транзакции ниже порога контроля (600 000 руб. в РФ).
Layering: многоуровневые переводы через цепочку счетов и юрисдикций для сокрытия источника.
Integration: отмытые средства вводятся в легальный бизнес — аффилированные услуги, недвижимость.
Red flags:
- Транзакции ровными суммами (999 000 руб.) — ниже порога, но подозрительно.
- Всплеск активности: нет операций → внезапно 50 за день.
- Географические несоответствия: клиент из Саратова, переводы в Сингапур.
- Счёт-однодневка: новый счёт, большой оборот, быстрый вывод, закрытие.
Feature Engineering
Ключ к качеству ML — признаки, отражающие поведение клиента. Мы используем два класса:
Транзакционные признаки (объём, время, суммы около порогов, концентрация контрагентов):
def extract_transaction_features(transaction_history, lookback_days=90):
"""Признаки на основе истории транзакций клиента."""
df = transaction_history.copy()
features = {
# Объём транзакций
'total_amount_30d': df[df['days_ago'] <= 30]['amount'].sum(),
'transaction_count_30d': len(df[df['days_ago'] <= 30]),
'avg_transaction_amount': df['amount'].mean(),
'amount_std': df['amount'].std(),
# Временные паттерны
'transactions_per_active_day': len(df) / df['date'].nunique(),
'max_transactions_single_day': df.groupby('date').size().max(),
'night_transaction_ratio': (df['hour'] < 6).mean(),
'weekend_activity_change': calculate_weekend_ratio(df),
# Суммы около порогов
'near_threshold_pct': (df['amount'].between(550000, 610000)).mean(),
'round_amount_pct': (df['amount'] % 1000 == 0).mean(),
# Контрагенты
'unique_counterparties': df['counterparty_id'].nunique(),
'counterparty_concentration': df.groupby('counterparty_id')['amount'].sum().max() / df['amount'].sum(),
'new_counterparty_ratio': (df['is_new_counterparty'] == True).mean(),
# Географические
'foreign_transaction_ratio': (df['country'] != 'RU').mean(),
'high_risk_jurisdiction_pct': df['country'].isin(HIGH_RISK_COUNTRIES).mean()
}
return features
def compute_network_features(account_id, transaction_graph):
"""Транзакции как граф: узлы = счета, рёбра = переводы."""
G = transaction_graph
pagerank = nx.pagerank(G, weight='amount')
betweenness = nx.betweenness_centrality(G, weight='amount')
communities = nx.community.greedy_modularity_communities(G.to_undirected())
community_risk = assess_community_risk(account_id, communities, G)
return {
'pagerank_score': pagerank.get(account_id, 0),
'betweenness_score': betweenness.get(account_id, 0),
'community_risk': community_risk,
'in_degree': G.in_degree(account_id),
'out_degree': G.out_degree(account_id)
}
Сетевые признаки (PageRank, betweenness, кластеризация) — помогают обнаруживать сложные layering-схемы, где счёт выступает транзитным узлом.
Модели машинного обучения
LightGBM с настройкой под AML
import lightgbm as lgb
from sklearn.metrics import roc_auc_score, average_precision_score
n_normal = (y_train == 0).sum()
n_sar = (y_train == 1).sum()
scale_pos_weight = n_normal / n_sar
model = lgb.LGBMClassifier(
n_estimators=500,
scale_pos_weight=scale_pos_weight,
learning_rate=0.05,
num_leaves=31,
min_child_samples=20,
feature_fraction=0.8
)
# Threshold подбирается так, чтобы recall >= 0.85
from sklearn.metrics import precision_recall_curve
precision, recall, thresholds = precision_recall_curve(y_val, y_scores)
optimal_threshold = thresholds[np.argmax(recall >= 0.85)]
Графовая нейронная сеть (GNN) для сетевого анализа
import torch
from torch_geometric.nn import SAGEConv
class AMLGraphNN(torch.nn.Module):
"""GNN для анализа транзакционных сетей."""
def __init__(self, node_features, edge_features, hidden_dim=64):
super().__init__()
self.conv1 = SAGEConv(node_features, hidden_dim)
self.conv2 = SAGEConv(hidden_dim, hidden_dim)
self.edge_mlp = torch.nn.Linear(edge_features, hidden_dim)
self.classifier = torch.nn.Linear(hidden_dim * 2, 1)
def forward(self, node_features, edge_index, edge_features):
x = torch.relu(self.conv1(node_features, edge_index))
x = torch.relu(self.conv2(x, edge_index))
edge_emb = self.edge_mlp(edge_features)
source_emb = x[edge_index[0]]
target_emb = x[edge_index[1]]
edge_repr = torch.cat([source_emb, target_emb], dim=1)
return torch.sigmoid(self.classifier(edge_repr))
Как устроена гибридная архитектура AML?
Гибридная система объединяет правила и ML в единый пайплайн. Правила быстро отсеивают очевидные легитимные операции и сигнализируют о явных нарушениях (превышение лимитов, запрещённые юрисдикции). ML-модели анализируют признаки, которые невозможно закодировать правилами: аномальное поведение, скрытые связи, нелинейные зависимости. Результат: каждый перевод получает единый риск-скор, который учитывает и правила, и ML.
class HybridAMLSystem:
def __init__(self, rule_engine, ml_model, threshold=0.5):
self.rules = rule_engine
self.model = ml_model
self.threshold = threshold
def evaluate_transaction(self, transaction, customer_history):
rule_alerts = self.rules.evaluate(transaction)
features = extract_transaction_features(customer_history)
ml_score = self.model.predict_proba([features])[0][1]
final_risk = max(rule_alerts.max_risk_score if rule_alerts else 0, ml_score)
if final_risk > self.threshold:
return SARCandidate(
transaction=transaction,
risk_score=final_risk,
triggered_rules=rule_alerts,
ml_explanation=shap_explain(self.model, features)
)
Что входит в работу
- Документация: архитектурная схема, model card, руководство администратора.
- ML-пайплайн: извлечение признаков, обучение, валидация, A/B-тестирование.
- Интеграция: с KYC-системой, core banking, CRM.
- Real-time API: HTTP/gRPC эндпоинт для оценки риска каждой транзакции.
- Дашборды: мониторинг метрик, отчётность SAR, SHAP-объяснения.
- Развёртывание: в контуре заказчика (on-prem) или в облаке.
- Поддержка: 1 месяц пост-продакшн, обучение команды.
Процесс разработки
- Аналитика — сбор требований, аудит текущих логов, нормативных актов (ФЗ-115, FATF).
- Проектирование — выбор архитектуры, определение признаков, конфигурация пилота.
- Разработка — написание кода, обучение моделей, настройка пайплайна.
- Тестирование — кросс-валидация на исторических данных, сценарное тестирование.
- Деплой — развёртывание, интеграция, нагрузочное тестирование.
Сроки: от 6–8 недель на базовую версию (правила + LightGBM + SAR) до 4–5 месяцев на полную (с GNN, real-time, графическим анализом).
Сравнение моделей: LightGBM vs GNN
| Характеристика | LightGBM | GNN (SAGEConv) |
|---|---|---|
| Тип данных | Табличные признаки (транзакции) | Графовые данные (сеть счетов) |
| Выявляет | Аномалии в поведении клиента | Сложные цепочки переводов (layering) |
| Обучаемость | Быстрое обучение, мало данных | Требует много данных и GPU |
| Интерпретация | SHAP, важность признаков | Визуализация графа, attention |
Регуляторное соответствие
ФЗ-115 (Россия): обязательный контроль операций >600 000 руб., передача SAR в Росфинмониторинг в течение 3 рабочих дней.
FATF/EU AMLD: KYC на онбординге, continuous monitoring, усиленная проверка (EDD) для high-risk клиентов. Регуляторные требования описаны в Рекомендациях FATF.
Как мы обеспечиваем объяснимость?
Каждое подозрительное решение сопровождается SHAP-объяснением. Рассмотрим пример: перевод 950 000 руб. из Саратова в Сингапур. SHAP-значения показывают, что foreign_transaction_ratio повысил риск на 0.34, near_threshold_pct — на 0.28, new_counterparty_ratio — на 0.21, transaction_count_30d — на 0.15, avg_transaction_amount — на 0.10. Итоговый риск 0.87 превышает порог 0.5, что генерирует SAR-отчёт.
import shap
def explain_sar_decision(model, features, feature_names):
"""Регулятор требует обоснования каждого SAR."""
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(features)
top_factors = sorted(
zip(feature_names, shap_values[0]),
key=lambda x: abs(x[1]), reverse=True
)[:5]
explanation = "\n".join([
f"- {name}: {'повысил' if val > 0 else 'снизил'} риск на {abs(val):.2f}"
for name, val in top_factors
])
return explanation
Такой подход позволяет не только пройти аудит, но и дать операторам понятные причины блокировок.
Готовы оценить ваш проект? Закажите разработку AML-системы под ваши данные — получите консультацию по архитектуре и срокам. Свяжитесь с нами для обсуждения.







