File size: 3,410 Bytes
408a9b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
"""
Module 8: Generate Architecture Diagram
System architecture visualization.
"""
import os, sys
sys.path.insert(0, '/app/fraud_detection')
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import numpy as np

from config import FIGURES_DIR, FIG_DPI, FIG_BG


def draw_architecture():
    """Draw the system architecture diagram."""
    fig, ax = plt.subplots(1, 1, figsize=(16, 10), facecolor=FIG_BG)
    ax.set_xlim(0, 16)
    ax.set_ylim(0, 10)
    ax.axis('off')
    
    # Colors
    c_input = '#3498db'
    c_process = '#2ecc71'
    c_model = '#e74c3c'
    c_output = '#f39c12'
    c_storage = '#9b59b6'
    
    def box(x, y, w, h, text, color, fontsize=9):
        rect = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.1",
                             facecolor=color, edgecolor='black', linewidth=1.5, alpha=0.85)
        ax.add_patch(rect)
        ax.text(x + w/2, y + h/2, text, ha='center', va='center',
               fontsize=fontsize, fontweight='bold', color='white',
               multialignment='center')
    
    def arrow(x1, y1, x2, y2):
        ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                   arrowprops=dict(arrowstyle='->', color='black', lw=2))
    
    # Title
    ax.text(8, 9.5, 'Fraud Detection System Architecture', ha='center',
           fontsize=16, fontweight='bold', color='#2c3e50')
    
    # Layer 1: Data Input
    box(0.5, 7.5, 3, 1, 'Transaction\nStream', c_input, 10)
    box(4, 7.5, 3, 1, 'Feature\nEngineering\n(12 features)', c_process, 9)
    box(7.5, 7.5, 3, 1, 'RobustScaler\n(Fit on Train)', c_process, 9)
    
    arrow(3.5, 8, 4, 8)
    arrow(7, 8, 7.5, 8)
    
    # Layer 2: Models
    box(0.5, 5, 2.2, 1.2, 'Logistic\nRegression', c_model, 8)
    box(3, 5, 2.2, 1.2, 'Random\nForest', c_model, 8)
    box(5.5, 5, 2.2, 1.2, 'XGBoost\n(Best)', c_model, 8)
    box(8, 5, 2.2, 1.2, 'LightGBM', c_model, 8)
    box(10.5, 5, 2.2, 1.2, 'MLP\nNeural Net', c_model, 8)
    box(13, 5, 2.5, 1.2, 'Autoencoder\n(Anomaly)', c_model, 8)
    
    # Arrows from preprocessing to models
    for x in [1.6, 4.1, 6.6, 9.1, 11.6, 14.25]:
        arrow(9, 7.5, x, 6.2)
    
    # Layer 3: Ensemble & Optimization
    box(3, 2.8, 4, 1.2, 'Voting Ensemble\n(XGB + LGBM + RF)', c_output, 10)
    box(8, 2.8, 4, 1.2, 'Optuna Tuning\n(Hyperparameter Opt)', c_storage, 9)
    
    arrow(5, 5, 5, 4)
    arrow(10, 5, 10, 4)
    arrow(8, 3.4, 7, 3.4)
    
    # Layer 4: Output
    box(3, 0.5, 4, 1.5, 'FastAPI\nPOST /predict\n< 10ms latency', c_input, 9)
    box(8, 0.5, 4, 1.5, 'Decision\nFraud Prob + Risk Level\n+ Top Risk Factors', c_output, 9)
    
    arrow(5, 2.8, 5, 2)
    arrow(7, 1.25, 8, 1.25)
    
    # Monitoring box
    box(12.5, 7.5, 3, 1, 'Monitoring\nDrift Detection\nRetraining', c_storage, 9)
    arrow(10.5, 8, 12.5, 8)
    
    # SHAP/LIME
    box(12.5, 2.8, 3, 1.2, 'Explainability\nSHAP + LIME', c_process, 9)
    arrow(12, 5, 14, 4)
    
    plt.tight_layout()
    plt.savefig(os.path.join(FIGURES_DIR, "architecture_diagram.png"), dpi=FIG_DPI, bbox_inches='tight', facecolor=FIG_BG)
    plt.savefig(os.path.join(FIGURES_DIR, "architecture_diagram.pdf"), bbox_inches='tight', facecolor=FIG_BG)
    plt.close()
    print("Saved: architecture_diagram.png/pdf")


if __name__ == "__main__":
    draw_architecture()