File size: 6,613 Bytes
8349588
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488b3d4
8349588
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
"""
Death Legion Fraud Detection - Gradio Space
Real-time fraud detection interface powered by Best Teams.
"""
import os
import gradio as gr
import numpy as np
from safetensors.numpy import load_file
from huggingface_hub import hf_hub_download

# Death Legion Branding
TITLE = "🔥 Death Legion Fraud Detection System"
DESCRIPTION = """
### Powered by Best Teams | Elite ML Division

Real-time credit card fraud detection using advanced Random Forest technology.
**AUPRC: 0.8177** | **Model Size: 6.12 MB**

Enter transaction features (V1-V28, Time, Amount) to get instant fraud predictions.
"""

# Load model from Hub
REPO_ID = "Pnny13/fraud-detection-model"

class SafetensorsRFClassifier:
    """Random Forest classifier from Safetensors."""
    
    def __init__(self, tensors):
        self.n_estimators = int(tensors['metadata/n_estimators'][0])
        self.n_features = int(tensors['metadata/n_features'][0])
        self.n_classes = int(tensors['metadata/n_classes'][0])
        self.classes_ = tensors['metadata/classes']
        self.trees = []
        
        for i in range(self.n_estimators):
            prefix = f'tree_{i:03d}'
            tree = {
                'node_count': int(tensors[f'{prefix}/node_count'][0]),
                'children_left': tensors[f'{prefix}/children_left'],
                'children_right': tensors[f'{prefix}/children_right'],
                'feature': tensors[f'{prefix}/feature'],
                'threshold': tensors[f'{prefix}/threshold'],
                'value': tensors[f'{prefix}/value'],
                'value_shape': tensors[f'{prefix}/value_shape'],
            }
            self.trees.append(tree)
    
    def _predict_proba_tree(self, tree, X):
        n_samples = X.shape[0]
        probas = np.zeros((n_samples, self.n_classes), dtype=np.float32)
        
        for i in range(n_samples):
            node = 0
            while tree['children_left'][node] != tree['children_right'][node]:
                if X[i, tree['feature'][node]] <= tree['threshold'][node]:
                    node = tree['children_left'][node]
                else:
                    node = tree['children_right'][node]
            
            value_shape = tree['value_shape']
            value = tree['value'].reshape(value_shape)
            class_counts = value[node, 0]
            total = class_counts.sum()
            probas[i] = class_counts / total if total > 0 else [0.5, 0.5]
        
        return probas
    
    def predict_proba(self, X):
        X = np.asarray(X, dtype=np.float32)
        probas = np.zeros((X.shape[0], self.n_classes), dtype=np.float32)
        for tree in self.trees:
            probas += self._predict_proba_tree(tree, X)
        probas /= self.n_estimators
        return probas


class SafetensorsScaler:
    """RobustScaler from Safetensors."""
    
    def __init__(self, tensors):
        self.center_ = tensors['scaler/center']
        self.scale_ = tensors['scaler/scale']
    
    def transform(self, X):
        X = np.asarray(X, dtype=np.float32)
        X_scaled = X.copy()
        for i in range(len(self.center_)):
            X_scaled[:, i] = (X[:, i] - self.center_[i]) / self.scale_[i]
        return X_scaled


# Global model cache
_model = None
_scaler = None

def load_model():
    """Load model from Hugging Face Hub."""
    global _model, _scaler
    if _model is None:
        model_path = hf_hub_download(repo_id=REPO_ID, filename="model/fraud_detector.safetensors")
        tensors = load_file(model_path)
        _model = SafetensorsRFClassifier(tensors)
        _scaler = SafetensorsScaler(tensors)
    return _model, _scaler


def predict_fraud(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
                  v11, v12, v13, v14, v15, v16, v17, v18, v19, v20,
                  v21, v22, v23, v24, v25, v26, v27, v28, time, amount):
    """Make fraud prediction from input features."""
    try:
        model, scaler = load_model()
        
        # Build feature vector
        features = np.array([[v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
                             v11, v12, v13, v14, v15, v16, v17, v18, v19, v20,
                             v21, v22, v23, v24, v25, v26, v27, v28, time, amount]], 
                            dtype=np.float32)
        
        # Scale Time and Amount
        features_scaled = features.copy()
        features_scaled[:, 0] = (features[:, 0] - scaler.center_[0]) / scaler.scale_[0]  # Time
        features_scaled[:, 29] = (features[:, 29] - scaler.center_[1]) / scaler.scale_[1]  # Amount
        
        # Predict
        probas = model.predict_proba(features_scaled)[0]
        fraud_prob = probas[1]
        
        # Determine result
        is_fraud = fraud_prob > 0.5
        
        # Create result display
        if is_fraud:
            result = f"""
            ## 🚨 FRAUD DETECTED
            
            **Fraud Probability: {fraud_prob:.2%}**
            
            ⚠️ This transaction shows suspicious patterns consistent with fraudulent activity.
            
            **Recommendation:** Block transaction and flag for review.
            """
        else:
            result = f"""
            ## ✅ LEGITIMATE TRANSACTION
            
            **Fraud Probability: {fraud_prob:.2%}**
            
            ✓ This transaction appears normal and safe to process.
            
            **Recommendation:** Approve transaction.
            """
        
        return result, fraud_prob
        
    except Exception as e:
        return f"Error: {str(e)}", 0.0


# Create Gradio interface
inputs = [
    gr.Number(label=f"V{i}", value=0.0) for i in range(1, 29)
] + [
    gr.Number(label="Time (seconds)", value=0.0),
    gr.Number(label="Amount ($)", value=100.0)
]

outputs = [
    gr.Markdown(label="Prediction Result"),
    gr.Number(label="Fraud Probability", visible=False)
]

interface = gr.Interface(
    fn=predict_fraud,
    inputs=inputs,
    outputs=outputs,
    title=TITLE,
    description=DESCRIPTION,
    theme=gr.themes.Soft(),
    examples=[
        # Example 1: Normal transaction
        [0.1, -0.2, 0.5, 0.3, -0.1, 0.2, -0.3, 0.1, 0.0, 0.2,
         -0.1, 0.3, -0.2, 0.1, 0.0, 0.2, -0.1, 0.1, 0.0, 0.0,
         0.1, -0.1, 0.0, 0.0, 0.1, -0.1, 0.0, 0.1, 3600, 50.0],
        # Example 2: Suspicious transaction
        [-2.5, 3.2, -1.8, 2.1, -0.5, 1.2, -2.1, 0.8, -1.5, 2.3,
         -0.8, 1.5, -2.0, 0.5, -1.2, 2.0, -0.6, 1.8, -1.0, 0.3,
         -1.5, 2.2, -0.9, 1.1, -1.8, 0.4, -1.2, 0.8, 7200, 999.99],
    ],
    cache_examples=False,
)

if __name__ == "__main__":
    interface.launch()