A production-grade, machine learning-driven pipeline for detecting financial money laundering transactions β featuring unsupervised behavioral profiling, XGBoost classification, and incremental continuous learning.
Developed by Abdulrahman Hattem Mohammed
- Overview
- Pipeline Architecture
- Dataset
- Project Structure
- Installation
- Usage
- Phase Breakdown
- Results & Metrics
- Key Design Decisions
- Continuous Learning
- License
Financial institutions process millions of transactions daily. Traditional rule-based AML systems flood investigators with false positives, while missing real threats exposes banks to massive regulatory fines. Regulators enforce strict deadlines β e.g., 45 business days to close every alert.
This project replaces static rule-based systems with a 5-phase ML pipeline that:
- Learns normal vs. abnormal behavioral patterns from unlabeled transaction data
- Classifies transactions as illicit or legitimate with high recall
- Continuously adapts to new criminal tactics via incremental batch learning β without retraining from scratch
Raw Transaction Logs
β
βΌ
βββββββββββββββββββββββ
β Phase 1 β ββ Drop leaky columns, encode categoricals,
β Data Preprocessing β StandardScaler normalization
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Phase 2 β ββ PCA on all continuous features
β Dimensionality β Retain components explaining 95% variance
β Reduction (PCA) β
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Phase 3 β ββ K-Means clustering (k=6, Elbow Method)
β Behavioral β Append `behavioral_segment` as new feature
β Segmentation β
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Phase 4 β ββ XGBoost with scale_pos_weight for imbalance
β XGBoost Classifier β Evaluate on Precision, Recall, F1-Score
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Phase 5 β ββ Incremental batch update via xgb_model param
β Continuous β No historical data re-used
β Learning β
βββββββββββββββββββββββ
β
βΌ
Fraud Predictions + Updated Model
This project uses the PaySim Synthetic Financial Dataset β a simulation of mobile money transactions based on a real dataset from a financial company, with injected money laundering behavior.
| Feature | Description |
|---|---|
step |
Time step (1 step = 1 hour) |
type |
Transaction type (CASH-IN, CASH-OUT, DEBIT, PAYMENT, TRANSFER) |
amount |
Transaction amount |
nameOrig |
Customer initiating the transaction |
oldbalanceOrg |
Initial balance of origin account |
newbalanceOrig |
New balance of origin account |
nameDest |
Recipient of the transaction |
oldbalanceDest |
Initial balance of destination account |
newbalanceDest |
New balance of destination account |
isFraud |
β Target label (1 = fraud, 0 = legitimate) |
isFlaggedFraud |
Rule-based flag (dropped β data leakage risk) |
Download: Place
paysim.csvin the project root before running notebooks.
aml-detection-pipeline/
β
βββ notebooks/
β βββ 01_preprocessing.ipynb # Phase 1: Data cleaning & feature engineering
β βββ 02_pca.ipynb # Phase 2: PCA dimensionality reduction
β βββ 03_kmeans_clustering.ipynb # Phase 3: Behavioral segmentation
β βββ 04_xgboost_classifier.ipynb # Phase 4: Supervised fraud classification
β βββ 05_continuous_learning.ipynb # Phase 5: Incremental batch training
β
βββ src/
β βββ preprocessing.py # Reusable preprocessing functions
β βββ pca_utils.py # PCA helpers & scree plot generation
β βββ clustering.py # K-Means pipeline utilities
β βββ model.py # XGBoost training & evaluation
β βββ continuous_learning.py # Batch update logic
β
βββ outputs/
β βββ models/ # Saved XGBoost model files
β βββ figures/ # Generated plots (scree, elbow, confusion matrix)
β βββ reports/ # Classification reports
β
βββ paysim.csv # Dataset (download from Kaggle β not tracked by git)
βββ requirements.txt
βββ .gitignore
βββ README.md
git clone https://github.com/your-username/aml-detection-pipeline.git
cd aml-detection-pipelinepython -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windowspip install -r requirements.txtDownload paysim.csv from Kaggle and place it in the project root.
Run the notebooks sequentially, or execute the full pipeline via script:
# Run full pipeline end-to-end
python src/pipeline.py --data paysim.csv
# Or open notebooks in order
jupyter notebook notebooks/01_preprocessing.ipynbEach notebook is self-contained and outputs artifacts consumed by the next phase.
- Drops
nameOrig,nameDest(identifiers, not signals) andisFlaggedFraud(data leakage) - Handles null values via
dropna() - One-hot encodes
typecolumn (drop_first=Trueto avoid dummy variable trap) - Applies
StandardScalerto all numerical features
df = df.drop(['nameOrig', 'nameDest', 'isFlaggedFraud'], axis=1)
df = pd.get_dummies(df, columns=['type'], drop_first=True)
X_scaled = StandardScaler().fit_transform(X)- Fits PCA across all components
- Selects the minimum number of components explaining β₯95% cumulative variance
- Produces scree plot and cumulative variance curve
pca = PCA()
cumulative_variance = pca.fit(X_scaled).explained_variance_ratio_.cumsum()
n_components = np.argmax(cumulative_variance >= 0.95) + 1Why 95%? It retains nearly all signal while removing noise and correlated dimensions that would distort K-Means distance calculations.
- Samples 10,000 rows for fast Elbow Method computation
- Selects
k=6clusters based on inertia inflection point - Fits K-Means on the full PCA-reduced dataset
- Appends
behavioral_segmentto the main dataframe as an engineered feature
kmeans = KMeans(n_clusters=6, init='k-means++', random_state=42, n_init=10)
df_final['behavioral_segment'] = kmeans.fit_predict(X_pca_final)Why cluster before classifying? Behavioral context (e.g., "this account type typically bursts CASHOUT transactions") is a stronger fraud signal than any single transaction attribute alone.
- Trains on original scaled features +
behavioral_segment - Uses
scale_pos_weight=99to address ~1:99 class imbalance - Evaluates with Precision, Recall, and F1-Score
model = XGBClassifier(
n_estimators=100,
max_depth=6,
learning_rate=0.1,
scale_pos_weight=99,
eval_metric='logloss'
)
model.fit(X_train, y_train)
β οΈ Why not Accuracy? With ~0.13% fraud rate, a model predicting all legitimate achieves 99.87% accuracy β while catching zero fraud cases. Recall and F1-Score expose this failure.
- Simulates a new monthly transaction batch arriving
- Updates the existing model using only the new batch β no historical data re-used
- Uses XGBoost's native
xgb_modelparameter for true incremental learning
# Update existing model with new batch only
model.fit(
X_new, y_new,
xgb_model=model.get_booster() # β Extends existing trees
)Strict constraint: combining old + new data and retraining from scratch is explicitly forbidden β this violates data retention compliance and defeats the purpose of online learning.
| Metric | Score |
|---|---|
| Recall | ~93% |
| Precision | ~88% |
| F1-Score | ~90% |
| Accuracy | ~99.9% (misleading β see above) |
Exact results vary by random seed and train/test split. The focus metric is Recall β minimizing missed fraud cases.
| Decision | Reason |
|---|---|
Drop isFlaggedFraud |
Prevents data leakage from existing rule-based system |
| PCA before K-Means | Denoised space produces more stable, meaningful clusters |
| 95% variance threshold | Retains signal, removes noise, justified by scree plot |
scale_pos_weight over SMOTE |
Avoids synthetic sample generation; faster and cleaner |
| Recall-optimized evaluation | A missed fraud is costlier than a false alarm in AML |
| Incremental batch update | Adapts to new patterns; respects data retention regulations |
The continuous learning module simulates a real-world production scenario where new transaction data arrives monthly. Instead of:
β Combining all historical + new data β retrain from scratch
The pipeline does:
β Load saved model β fit on new batch only β save updated model
This approach is:
- Computationally efficient β no full retraining cost
- Regulatory compliant β old data is never re-processed
- Adaptive β model weights shift toward emerging fraud patterns