AI-Powered AML: Combining Rules and Machine Learning

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1All 1564 services
AI-Powered AML: Combining Rules and Machine Learning
Complex
~2-4 weeks
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1347
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    948
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1183
  • image_logo-advance_0.webp
    B2B Advance company logo design
    642
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    921

Anti-Money Laundering (AML) is an area where the cost of error is critical. Missing a suspicious transfer (false negative) risks fines of up to 5% of turnover under Federal Law 115. Blocking a legitimate customer (false positive) leads to reputational damage and lawsuits. Traditional rule-based systems only detect known patterns, generating up to 95% false alerts. Our AI AML system excels at money laundering detection using machine learning AML models. We develop hybrid AI systems that reduce FPR by 20–40% without sacrificing detection recall. Our track record: 10+ years in financial ML for banks and fintechs. A typical implementation costs between $50,000 and $200,000, with ROI realized within 6 months through reduced manual review. Banks typically save $1,000,000 annually by reducing manual review workload.

The core is a combination of deterministic rules (for typical scenarios) and ML models (for uncovering latent non-linear patterns). Below we cover the architecture, models, and implementation stages.

In this article, we break down the key components: transaction monitoring, graph analysis, and KYC integration. We'll see how a hybrid approach reduces the compliance department's workload while meeting FATF requirements. Rules automatically handle 80% of transactions, leaving 20% for ML review, cutting manual effort by 60%. Our hybrid system reduces false positives by 2-5 times compared to rule-only systems. Our hybrid AML system is up to 3 times more effective than pure rule-based systems.

Why ML outperforms rule-based systems for AML

Characteristic Rules ML Model
Detecting new schemes No – only known patterns Yes – uncovers hidden correlations
False positive rate (FPR) 5–10% 2–4% (2–5x reduction)
Adapting to changes Manual update Automatic retraining
Explainability Full (if rule is explicit) Via SHAP/LIME
Scalability Linear with number of rules Parallel processing

Money laundering typologies

Structuring (Smurfing): Large sums split into smaller transactions below the reporting threshold (as defined locally).

Layering: Multi-level transfers through a chain of accounts and jurisdictions to hide the source.

Integration: Laundered funds are introduced into legitimate business—affiliated services, real estate.

Red flags:

  • Transactions round amounts (e.g., just below the threshold) – below threshold but suspicious.
  • Activity spike: no operations → suddenly 50 in a day.
  • Geographic mismatches: client from Saratov, transfers to Singapore.
  • Throwaway account: new account, large turnover, quick withdrawal, then closure.

Feature engineering

The key to ML quality are features capturing customer behavior. We use two classes:

Transactional features (volume, timing, amounts near thresholds, counterparty concentration):

def extract_transaction_features(transaction_history, lookback_days=90):
    """Features based on the customer's transaction history."""
    df = transaction_history.copy()
    features = {
        # Transaction volume
        '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(),
        # Temporal patterns
        '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),
        # Amounts near thresholds
        'near_threshold_pct': (df['amount'].between(550000, 610000)).mean(),
        'round_amount_pct': (df['amount'] % 1000 == 0).mean(),
        # Counterparties
        '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(),
        # Geographic
        '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):
    """Transactions as graph: nodes = accounts, edges = transfers."""
    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)
    }

Network features (PageRank, betweenness, clustering) – help detect complex layering schemes where an account acts as a transit node.

Machine learning models

LightGBM tuned for 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 chosen so that 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)]

This LightGBM AML classifier is optimized for transaction monitoring.

Graph neural network (GNN) for network analysis

import torch
from torch_geometric.nn import SAGEConv

class AMLGraphNN(torch.nn.Module):
    """GNN for analyzing transaction networks."""
    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))

Our graph neural network AML models analyze transaction networks.

How the hybrid AML architecture works

The hybrid system combines rules and ML into a single pipeline. Rules quickly filter out obvious legitimate operations and flag clear violations (limit breaches, forbidden jurisdictions). ML models analyze attributes that cannot be encoded in rules: anomalous behavior, hidden connections, non-linear dependencies. Result: each transfer gets a unified risk score that incorporates both rules and 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)
            )

What's included in the engagement

  • Documentation: architecture diagram, model card, admin guide
  • ML pipeline: feature extraction, training, validation, A/B testing
  • Integration: with KYC system, core banking, CRM
  • Real-time API: HTTP/gRPC endpoint for risk scoring each transaction
  • Dashboards: metric monitoring, SAR reporting, SHAP explanations
  • Deployment: on-premises or cloud
  • Support: 1 month post-production, team training

Development process

  1. Analysis – gather requirements, audit current logs, review regulations (Federal Law 115, FATF)
  2. Design – select architecture, define features, configure pilot
  3. Development – write code, train models, set up pipeline
  4. Testing – cross-validation on historical data, scenario testing
  5. Deployment – deploy, integrate, load test

Timeline: from 6–8 weeks for a basic version (rules + LightGBM + SAR) to 4–5 months for a full system (with GNN, real-time, graph analysis). The system processes over 10,000 transactions per second in real-time.

Model comparison: LightGBM vs GNN

Characteristic LightGBM GNN (SAGEConv)
Data type Tabular features (transactions) Graph data (account network)
Detects Anomalies in customer behavior Complex transfer chains (layering)
Trainability Fast training, works with little data Requires more data and GPU
Interpretability SHAP, feature importance Graph visualization, attention

Regulatory compliance

Federal Law 115 (Russia): mandatory control of transactions above a certain threshold, submission of SAR to Rosfinmonitoring within 3 business days.

FATF/EU AMLD: KYC on onboarding, continuous monitoring, enhanced due diligence (EDD) for high-risk clients. Regulatory requirements are described in the FATF Recommendations (Wikipedia).

How we ensure explainability

Each suspicious decision comes with a SHAP explanation. Consider an example: a transfer of a large amount from Saratov to Singapore. SHAP values show that foreign_transaction_ratio increased risk by 0.34, near_threshold_pct by 0.28, new_counterparty_ratio by 0.21, transaction_count_30d by 0.15, and avg_transaction_amount by 0.10. The final risk of 0.87 exceeds the threshold of 0.5, generating a SAR report.

import shap

def explain_sar_decision(model, features, feature_names):
    """Regulators require justification for each 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}: {'increased' if val > 0 else 'decreased'} risk by {abs(val):.2f}"
        for name, val in top_factors
    ])
    return explanation

This approach not only satisfies audits but also gives operators clear reasons for blocking.

Our AML development services cover end-to-end solutions including KYC AML integration and SAR reporting. We have expertise in graph neural network AML models, transaction monitoring, and hybrid AML systems. Our team holds certifications in AML and data science, and we guarantee a minimum 20% reduction in false positives.

Ready to evaluate your project? Request AML system development tailored to your data — get a consultation on architecture and timelines. Contact us to discuss your case.

Anomaly Detection: Autoencoders, Isolation Forest, PyOD

Server monitoring shows CPU 85%, memory 91% — is this the start of an attack or normal peak load? A classifier won’t help: anomalies are by definition rare, diverse, and not pre-labeled. Supervised learning requires examples of anomalies in the training set — so it fails on what you haven’t seen yet. Without an unsupervised approach, detection turns into guesswork.

Why Does Anomaly Detection Require an Unsupervised Approach?

The main problem: no labels and extreme class imbalance. Fraud transactions account for 0.01–0.1% of total volume, production defects 0.5–3%. With such ratios, a naive “all normal” classifier gives 99.9% accuracy but recall for the anomalous class near zero. Supervised models are powerless.

Second: “normality” is always contextual. A login at 3 AM may be normal for a night‑shift user but suspicious for a day‑worker. Bearing vibration at 2.3 mm/s depends on operating mode and machine age. So we embed context via feature engineering and time windows.

Third: quality assessment without ground truth. No standard test set — AUC‑ROC is possible only if a few labeled examples exist. For fully unlabeled data, only domain expert validation and indirect metrics work.

How to Distinguish an Anomaly from Noise in Real Time?

With adaptive thresholds and continuous monitoring of model statistics. In the case section we show how.

Method Data Type Training Speed Typical Application
Isolation Forest Tabular, categorical High Baseline for initial hypotheses
Autoencoder Images, time series, logs Medium Unstructured data
LSTM-AE Multivariate time series Low Industrial telemetry
PyOD (ensemble) Tabular High Quick comparison of 40+ methods

Isolation Forest is the standard baseline for tabular data. Idea: anomalies are isolated faster by random partitioning of the feature space. Works well at contamination=0.01–0.1, robust to feature scale, no normalization required. Implementation in sklearn.ensemble.IsolationForest.

Typical mistake: setting contamination='auto' without understanding the data. Auto mode assumes a threshold of -0.5, which may not match the actual anomaly proportion. Better: estimate expected anomaly percentage through domain knowledge and set it explicitly. We guarantee contamination tuning for your case.

PyOD (Python Outlier Detection) is a library with 40+ algorithms under a unified API — OCSVM, LOF, COPOD, ECOD, DeepSVDD, AutoEncoder. Useful for quickly comparing methods on the same data.

Autoencoders are the main method for unstructured data (time series, images, logs). Train the network to reconstruct normal data; anomalies yield high reconstruction error. Anomaly threshold is the 95th or 99th percentile of error on a validation set of normal data.

Practical problem with autoencoders: overfitting on “normal” patterns that are still rare. If the training set contains even a few anomalies, the model may learn to reconstruct them well. Solution: thorough cleaning of training data or using a Variational Autoencoder (VAE), which generalizes better.

LSTM‑AE for time series captures temporal dependencies better than a regular AE. Especially effective for multivariate time series (10+ sensors simultaneously). Implementation via PyTorch, training with MSELoss on sliding windows.

In Detail: Anomaly Detection in Industrial Time Series

Problem: vibration sensors on 12 pumps at a chemical plant, 6 sensors per pump, frequency 100 Hz. Need to warn of impending failure 4–24 hours in advance.

Solution architecture: raw data → feature extraction (RMS, kurtosis, peak factor, FFT amplitudes at resonant frequencies) → normalization by 24‑hour sliding window → LSTM‑AE → reconstruction error → threshold logic + alerting.

LSTM window size: 60 seconds (6000 points at 100 Hz). Too small a window misses slow patterns, too large loses sensitivity to rapid changes.

Anomaly threshold: not fixed, but adaptive. threshold = mean(errors_last_7d) + 3 * std(errors_last_7d). As normal state drifts (planned wear), the threshold adapts, avoiding false positives.

Result over a 6‑month pilot: detected 4 out of 5 real pre‑failure conditions (recall 0.8), with 2 false alarms over 6 months (precision 0.67). Before implementation: 3 unplanned shutdowns. After implementation: cost savings verified in the pilot report.

What Specifics Does Fraud Detection Face?

Financial transactions have several features that complicate detection:

  • Concept drift: fraud patterns change faster than normal behavior. A model trained six months ago becomes obsolete.
  • Adversarial adaptation: advanced fraudsters adapt — making transactions resemble normal ones.
  • Temporal dependency: a series of normal transactions followed by one unusual transfer is a sequence anomaly, not a single point.

Practical stack for fraud detection: LightGBM with SMOTE oversampling for the supervised part (known fraud cases) + Isolation Forest for unsupervised (new patterns). Both signals combined in an ensemble; final decision via thresholds tuned for acceptable FPR (0.1–1% of transactions sent to manual review).

How to Evaluate Quality Without Labels?

When ground truth is absent, we evaluate using:

  • Synthetic anomaly injection: add artificial anomalies (spike, level shift, point outlier) and check if the model detects them.
  • Expert validation: random sample of top‑K anomalies → expert review → precision.
  • Business metric: did the number of missed incidents / false alarms decrease after deployment?

Technical detail: the adaptive threshold is computed as mean(errors) + k * std(errors) on a 7‑day sliding window. Coefficient k is tuned on a validation set with synthetic anomalies to achieve FPR < 0.1%. When features drift, the window automatically shifts.

Process

  1. Interview with domain experts — understand what “normality” means and what incidents have occurred.
  2. EDA and data preparation — cleaning, feature creation, time windows.
  3. Baseline (Isolation Forest) — fast validation on known incidents.
  4. Model selection and customization — Autoencoder / LSTM‑AE / ensemble.
  5. Training, validation with synthetic anomalies.
  6. Deployment to production — pipeline on Kafka + Flink / Airflow, alerting to Telegram/Slack, drift monitoring.
  7. Post‑deployment support — monitor model metrics, update thresholds.

What's Included

  • Audit of current data and processes
  • Development and training of models (Isolation Forest / Autoencoder / LSTM‑AE / ensemble)
  • Configuration of adaptive thresholds and alerting
  • Anomaly monitoring dashboard (Grafana / Streamlit)
  • Model card and pipeline documentation
  • Training for your team (2–3 sessions)
  • 3‑month warranty support

Timeline: baseline system with one method — 2–4 weeks. Production system with adaptive thresholds, alerting, and monitoring — 2–5 months. Pricing is calculated individually for your case.

Our team has 8+ years of experience in industrial analytics and 15+ successful projects in anomaly detection for telemetry, finance, and IT monitoring. Get a consultation — we’ll tell you how to solve your problem. Contact us to discuss your data and receive a preliminary architecture proposal.