d-e-e-k-11 commited on
Commit
08d6be3
·
verified ·
1 Parent(s): 93cb428

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ creditcard.csv filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use official Python base image
2
+ FROM python:3.10-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Copy requirements and install
8
+ COPY requirements.txt .
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ # Copy the rest of the application
12
+ COPY . .
13
+
14
+ # Expose the port Flask runs on
15
+ EXPOSE 7860
16
+
17
+ # Set environment variables for Flask
18
+ ENV FLASK_APP=app.py
19
+ ENV FLASK_RUN_HOST=0.0.0.0
20
+ ENV FLASK_RUN_PORT=7860
21
+
22
+ # Run the application
23
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify
2
+ import joblib
3
+ import pandas as pd
4
+ import numpy as np
5
+ import os
6
+
7
+ app = Flask(__name__)
8
+
9
+ # Load model and scalers
10
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
11
+ MODEL_PATH = os.path.join(BASE_DIR, 'fraud_model.joblib')
12
+ SCALER_AMOUNT_PATH = os.path.join(BASE_DIR, 'scaler_amount.joblib')
13
+ SCALER_TIME_PATH = os.path.join(BASE_DIR, 'scaler_time.joblib')
14
+ DATA_PATH = os.path.join(BASE_DIR, 'creditcard.csv')
15
+
16
+ model = joblib.load(MODEL_PATH)
17
+ scaler_amount = joblib.load(SCALER_AMOUNT_PATH)
18
+ scaler_time = joblib.load(SCALER_TIME_PATH)
19
+
20
+ # Cache some samples for the frontend
21
+ df_all = pd.read_csv(DATA_PATH)
22
+ fraud_samples = df_all[df_all['Class'] == 1].sample(10).to_dict('records')
23
+ normal_samples = df_all[df_all['Class'] == 0].sample(10).to_dict('records')
24
+
25
+ @app.route('/')
26
+ def index():
27
+ return render_template('index.html')
28
+
29
+ @app.route('/get_samples', methods=['GET'])
30
+ def get_samples():
31
+ return jsonify({
32
+ "fraud": fraud_samples,
33
+ "normal": normal_samples
34
+ })
35
+
36
+ @app.route('/predict', methods=['POST'])
37
+ def predict():
38
+ try:
39
+ data = request.json
40
+
41
+ # Prepare feature vector (V1-V28, scaled_amount, scaled_time)
42
+ v_features = [float(data.get(f'V{i}', 0)) for i in range(1, 29)]
43
+
44
+ amount = float(data.get('Amount', 0))
45
+ time = float(data.get('Time', 0))
46
+
47
+ scaled_amount = scaler_amount.transform([[amount]])[0][0]
48
+ scaled_time = scaler_time.transform([[time]])[0][0]
49
+
50
+ # Combine all features
51
+ # Training script Order: X = df.drop('Class', axis=1)
52
+ # df had columns in order: V1...V28, scaled_amount, scaled_time (since original were dropped)
53
+ feature_vector = np.array(v_features + [scaled_amount, scaled_time]).reshape(1, -1)
54
+
55
+ prediction = int(model.predict(feature_vector)[0])
56
+ probability = model.predict_proba(feature_vector)[0].tolist()
57
+
58
+ return jsonify({
59
+ "is_fraud": prediction == 1,
60
+ "confidence": max(probability) * 100,
61
+ "class": "Fraudulent" if prediction == 1 else "Legitimate"
62
+ })
63
+
64
+ except Exception as e:
65
+ return jsonify({"error": str(e)}), 400
66
+
67
+ if __name__ == '__main__':
68
+ # Use port 7860 for Hugging Face Spaces
69
+ port = int(os.environ.get("PORT", 7860))
70
+ app.run(debug=True, host='0.0.0.0', port=port)
class_distribution.png ADDED
create_hf_space.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from huggingface_hub import HfApi, create_repo
2
+
3
+ api = HfApi()
4
+ repo_id = "d-e-e-k-11/credit-card-fraud-detection"
5
+
6
+ try:
7
+ create_repo(
8
+ repo_id=repo_id,
9
+ repo_type="space",
10
+ space_sdk="docker",
11
+ private=False
12
+ )
13
+ print(f"Space created successfully: https://huggingface.co/spaces/{repo_id}")
14
+ except Exception as e:
15
+ print(f"Error creating space: {e}")
creditcard.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:76274b691b16a6c49d3f159c883398e03ccd6d1ee12d9d8ee38f4b4b98551a89
3
+ size 150828752
distributions.png ADDED
eda.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import matplotlib.pyplot as plt
3
+ import seaborn as sns
4
+
5
+ # Load dataset
6
+ df = pd.read_csv('c:/card/creditcard.csv')
7
+
8
+ # Basic info
9
+ print("Dataset Shape:", df.shape)
10
+ print("\nFirst 5 rows:")
11
+ print(df.head())
12
+
13
+ # Check for missing values
14
+ print("\nMissing values:")
15
+ print(df.isnull().sum().max())
16
+
17
+ # Class distribution
18
+ print("\nClass Distribution (0: Normal, 1: Fraud):")
19
+ print(df['Class'].value_counts())
20
+ print("\nPercentage:")
21
+ print(df['Class'].value_counts(normalize=True) * 100)
22
+
23
+ # Statistics
24
+ print("\nSummary Statistics:")
25
+ print(df.describe())
26
+
27
+ # Plotting class distribution
28
+ plt.figure(figsize=(8, 6))
29
+ sns.countplot(x='Class', data=df, palette='viridis')
30
+ plt.title('Class Distribution (0: Normal, 1: Fraud)')
31
+ plt.savefig('c:/card/class_distribution.png')
32
+
33
+ # Plotting distributions of Time and Amount
34
+ plt.figure(figsize=(12, 4))
35
+ plt.subplot(1, 2, 1)
36
+ sns.histplot(df['Amount'], bins=50, kde=True, color='blue')
37
+ plt.title('Transaction Amount Distribution')
38
+
39
+ plt.subplot(1, 2, 2)
40
+ sns.histplot(df['Time'], bins=50, kde=True, color='red')
41
+ plt.title('Transaction Time Distribution')
42
+ plt.savefig('c:/card/distributions.png')
fraud_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:71576f9d6260ca53b4c0df6561821ba0847ef38c25d8339c34a1af6a346f38ac
3
+ size 2047769
implementation_plan.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Implementation Plan - Credit Card Fraud Detection
2
+
3
+ ## Overview
4
+ Build a machine learning pipeline to detect fraudulent credit card transactions and provide a web interface for real-time inference.
5
+
6
+ ## Tech Stack
7
+ - **Dataset**: `creditcard.csv` (provided)
8
+ - **ML Framework**: Scikit-learn, Pandas, Numpy, Imbalanced-learn (SMOTE)
9
+ - **Model**: Random Forest or XGBoost
10
+ - **Backend**: Flask (Python)
11
+ - **Frontend**: HTML5, Vanilla CSS (Modern/Premium design), JavaScript
12
+
13
+ ## Steps
14
+
15
+ ### 1. Data Preparation & EDA
16
+ - Load `creditcard.csv`.
17
+ - Analyze class distribution (fraud vs. non-fraud).
18
+ - Visualize correlations and feature distributions.
19
+ - Check for missing values.
20
+
21
+ ### 2. Preprocessing
22
+ - Scale `Time` and `Amount` features (V1-V28 are already PCA-transformed).
23
+ - Split data into training and testing sets.
24
+ - Apply SMOTE (Synthetic Minority Over-sampling Technique) to handle class imbalance.
25
+
26
+ ### 3. Model Engineering
27
+ - Train multiple models (Logistic Regression, Random Forest).
28
+ - Evaluate using Precision-Recall curves and F1-score.
29
+ - Save the best model using `joblib`.
30
+
31
+ ### 4. Backend (Flask)
32
+ - Create an API endpoint `/predict`.
33
+ - Load the trained model and scaler.
34
+ - Handle POST requests with transaction data.
35
+
36
+ ### 5. Frontend (Web UI)
37
+ - Build a premium, glassmorphic UI.
38
+ - Form to input transaction details (or sample details).
39
+ - Display prediction result with a visual indicator (Safe vs. Fraud).
40
+
41
+ ### 6. Deployment Readiness
42
+ - Create `requirements.txt`.
43
+ - Ensure scripts are well-documented.
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ pandas
2
+ numpy
3
+ matplotlib
4
+ seaborn
5
+ scikit-learn
6
+ imbalanced-learn
7
+ joblib
8
+ flask
scaler.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:209e91b39c7def96a51d697fc57bb271a76d66abee000512fa2a166d3325ca11
3
+ size 623
scaler_amount.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d94e1a17e6e54764c3e296d299d861512708da0cf52fb610b8da63dbc9d792da
3
+ size 623
scaler_time.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:209e91b39c7def96a51d697fc57bb271a76d66abee000512fa2a166d3325ca11
3
+ size 623
static/style.css ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --primary: #6366f1;
3
+ --primary-hover: #4f46e5;
4
+ --danger: #ef4444;
5
+ --success: #10b981;
6
+ --bg-dark: #0f172a;
7
+ --glass-bg: rgba(255, 255, 255, 0.05);
8
+ --glass-border: rgba(255, 255, 255, 0.1);
9
+ }
10
+
11
+ body {
12
+ margin: 0;
13
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
14
+ background-color: var(--bg-dark);
15
+ color: #f8fafc;
16
+ min-height: 100vh;
17
+ display: flex;
18
+ justify-content: center;
19
+ align-items: center;
20
+ background-image:
21
+ radial-gradient(circle at 0% 0%, rgba(99, 102, 241, 0.15) 0%, transparent 50%),
22
+ radial-gradient(circle at 100% 100%, rgba(239, 68, 68, 0.1) 0%, transparent 50%);
23
+ }
24
+
25
+ .container {
26
+ width: 90%;
27
+ max-width: 1000px;
28
+ background: var(--glass-bg);
29
+ backdrop-filter: blur(12px);
30
+ -webkit-backdrop-filter: blur(12px);
31
+ border: 1px solid var(--glass-border);
32
+ border-radius: 24px;
33
+ padding: 2.5rem;
34
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
35
+ }
36
+
37
+ header {
38
+ text-align: center;
39
+ margin-bottom: 2.5rem;
40
+ }
41
+
42
+ header h1 {
43
+ font-size: 2.5rem;
44
+ margin: 0;
45
+ background: linear-gradient(to right, #818cf8, #f472b6);
46
+ -webkit-background-clip: text;
47
+ background-clip: text;
48
+ -webkit-text-fill-color: transparent;
49
+ font-weight: 800;
50
+ }
51
+
52
+ header p {
53
+ color: #94a3b8;
54
+ font-size: 1.1rem;
55
+ margin-top: 0.5rem;
56
+ }
57
+
58
+ .main-layout {
59
+ display: grid;
60
+ grid-template-columns: 1fr 1fr;
61
+ gap: 2rem;
62
+ }
63
+
64
+ .card {
65
+ background: rgba(255, 255, 255, 0.03);
66
+ border-radius: 16px;
67
+ padding: 1.5rem;
68
+ border: 1px solid var(--glass-border);
69
+ }
70
+
71
+ .card-title {
72
+ font-size: 1.25rem;
73
+ font-weight: 600;
74
+ margin-bottom: 1.25rem;
75
+ display: flex;
76
+ align-items: center;
77
+ gap: 0.75rem;
78
+ }
79
+
80
+ .samples-list {
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 0.75rem;
84
+ }
85
+
86
+ .sample-item {
87
+ background: rgba(255, 255, 255, 0.05);
88
+ padding: 1rem;
89
+ border-radius: 12px;
90
+ cursor: pointer;
91
+ transition: all 0.2s;
92
+ border: 1px solid transparent;
93
+ }
94
+
95
+ .sample-item:hover {
96
+ background: rgba(255, 255, 255, 0.08);
97
+ border-color: var(--primary);
98
+ transform: translateY(-2px);
99
+ }
100
+
101
+ .sample-item .meta {
102
+ display: flex;
103
+ justify-content: space-between;
104
+ font-size: 0.875rem;
105
+ color: #94a3b8;
106
+ }
107
+
108
+ .sample-item .amount {
109
+ font-weight: 700;
110
+ color: #fff;
111
+ font-size: 1rem;
112
+ }
113
+
114
+ .form-group {
115
+ margin-bottom: 1rem;
116
+ display: grid;
117
+ grid-template-columns: 1fr 1fr;
118
+ gap: 1rem;
119
+ }
120
+
121
+ .input-field {
122
+ background: rgba(0, 0, 0, 0.2);
123
+ border: 1px solid var(--glass-border);
124
+ border-radius: 8px;
125
+ padding: 0.75rem;
126
+ color: white;
127
+ width: 100%;
128
+ box-sizing: border-box;
129
+ }
130
+
131
+ .input-field:focus {
132
+ outline: none;
133
+ border-color: var(--primary);
134
+ }
135
+
136
+ .btn {
137
+ background: var(--primary);
138
+ color: white;
139
+ border: none;
140
+ padding: 1rem;
141
+ border-radius: 12px;
142
+ font-size: 1.1rem;
143
+ font-weight: 600;
144
+ cursor: pointer;
145
+ width: 100%;
146
+ transition: all 0.2s;
147
+ margin-top: 1rem;
148
+ }
149
+
150
+ .btn:hover {
151
+ background: var(--primary-hover);
152
+ box-shadow: 0 0 20px rgba(99, 102, 241, 0.4);
153
+ }
154
+
155
+ #result-area {
156
+ margin-top: 2rem;
157
+ padding: 1.5rem;
158
+ border-radius: 16px;
159
+ text-align: center;
160
+ display: none;
161
+ animation: fadeIn 0.3s ease-out;
162
+ }
163
+
164
+ .result-fraud {
165
+ background: rgba(239, 68, 68, 0.1);
166
+ border: 1px solid var(--danger);
167
+ color: #fca5a5;
168
+ }
169
+
170
+ .result-safe {
171
+ background: rgba(16, 185, 129, 0.1);
172
+ border: 1px solid var(--success);
173
+ color: #6ee7b7;
174
+ }
175
+
176
+ .result-title {
177
+ font-size: 1.5rem;
178
+ font-weight: 800;
179
+ margin-bottom: 0.5rem;
180
+ }
181
+
182
+ .result-conf {
183
+ font-size: 0.9rem;
184
+ opacity: 0.8;
185
+ }
186
+
187
+ @keyframes fadeIn {
188
+ from {
189
+ opacity: 0;
190
+ transform: translateY(10px);
191
+ }
192
+
193
+ to {
194
+ opacity: 1;
195
+ transform: translateY(0);
196
+ }
197
+ }
198
+
199
+ .tabs {
200
+ display: flex;
201
+ gap: 1rem;
202
+ margin-bottom: 1rem;
203
+ }
204
+
205
+ .tab {
206
+ padding: 0.5rem 1rem;
207
+ border-radius: 20px;
208
+ cursor: pointer;
209
+ background: rgba(255, 255, 255, 0.05);
210
+ font-size: 0.875rem;
211
+ transition: all 0.2s;
212
+ }
213
+
214
+ .tab.active {
215
+ background: var(--primary);
216
+ }
217
+
218
+ /* Scrollbar */
219
+ ::-webkit-scrollbar {
220
+ width: 8px;
221
+ }
222
+
223
+ ::-webkit-scrollbar-track {
224
+ background: rgba(0, 0, 0, 0.1);
225
+ }
226
+
227
+ ::-webkit-scrollbar-thumb {
228
+ background: rgba(255, 255, 255, 0.1);
229
+ border-radius: 4px;
230
+ }
231
+
232
+ ::-webkit-scrollbar-thumb:hover {
233
+ background: rgba(255, 255, 255, 0.2);
234
+ }
task.md ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # Tasks: End-to-End Credit Card Fraud Detection
2
+
3
+ - [x] Project Setup & Data Inspection <!-- id: 0 -->
4
+ - [x] Exploratory Data Analysis (EDA) <!-- id: 1 -->
5
+ - [x] Data Preprocessing & Balancing <!-- id: 2 -->
6
+ - [x] Model Selection & Training <!-- id: 3 -->
7
+ - [x] Model Evaluation & Saving <!-- id: 4 -->
8
+ - [x] Backend API Development (Flask) <!-- id: 5 -->
9
+ - [x] Frontend Web Interface Development <!-- id: 6 -->
10
+ - [x] Testing & Final Polish <!-- id: 7 -->
templates/index.html ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>FraudShield AI | Transaction Monitoring</title>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
8
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap" rel="stylesheet">
9
+ </head>
10
+ <body>
11
+ <div class="container">
12
+ <header>
13
+ <h1>FraudShield AI</h1>
14
+ <p>Advanced Real-time Credit Card Fraud Detection Pipeline</p>
15
+ </header>
16
+
17
+ <div class="main-layout">
18
+ <div class="card">
19
+ <div class="card-title">
20
+ <span>🔍</span> Sample Transactions
21
+ </div>
22
+ <div class="tabs">
23
+ <div class="tab active" id="tab-fraud">Fraud Cases</div>
24
+ <div class="tab" id="tab-normal">Legitimate</div>
25
+ </div>
26
+ <div class="samples-list" id="samples-container">
27
+ <!-- Samples will be injected here -->
28
+ <p style="text-align: center; color: #64748b;">Loading samples...</p>
29
+ </div>
30
+ </div>
31
+
32
+ <div class="card">
33
+ <div class="card-title">
34
+ <span>⚙️</span> Analysis Engine
35
+ </div>
36
+ <form id="prediction-form">
37
+ <div class="form-group">
38
+ <div>
39
+ <label style="font-size: 0.8rem; color: #94a3b8;">Amount ($)</label>
40
+ <input type="number" id="Amount" class="input-field" step="0.01" required placeholder="89.99">
41
+ </div>
42
+ <div>
43
+ <label style="font-size: 0.8rem; color: #94a3b8;">Time (Seconds)</label>
44
+ <input type="number" id="Time" class="input-field" required placeholder="0">
45
+ </div>
46
+ </div>
47
+
48
+ <div style="margin-bottom: 0.5rem; font-size: 0.8rem; color: #94a3b8;">PCA Components (V1 - V28)</div>
49
+ <div style="max-height: 200px; overflow-y: auto; padding-right: 5px;" id="v-inputs">
50
+ <!-- V1 to V28 inputs will be injected -->
51
+ </div>
52
+
53
+ <button type="submit" class="btn">Analyze Transaction</button>
54
+ </form>
55
+
56
+ <div id="result-area">
57
+ <div class="result-title" id="res-title">SAFE</div>
58
+ <div class="result-conf" id="res-conf">Confidence: 99.8%</div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+
64
+ <script>
65
+ let samples = { fraud: [], normal: [] };
66
+ let activeTab = 'fraud';
67
+
68
+ // Initialize V inputs
69
+ const vContainer = document.getElementById('v-inputs');
70
+ for (let i = 1; i <= 28; i++) {
71
+ const div = document.createElement('div');
72
+ div.className = 'form-group';
73
+ div.style.marginBottom = '0.5rem';
74
+ div.innerHTML = `
75
+ <div style="grid-column: span 2">
76
+ <input type="number" step="0.000001" id="V${i}" class="input-field" placeholder="V${i} component" value="0">
77
+ </div>
78
+ `;
79
+ vContainer.appendChild(div);
80
+ }
81
+
82
+ // Fetch samples
83
+ fetch('/get_samples')
84
+ .then(res => res.json())
85
+ .then(data => {
86
+ samples = data;
87
+ renderSamples();
88
+ });
89
+
90
+ function renderSamples() {
91
+ const container = document.getElementById('samples-container');
92
+ container.innerHTML = '';
93
+
94
+ const list = activeTab === 'fraud' ? samples.fraud : samples.normal;
95
+
96
+ list.forEach(item => {
97
+ const el = document.createElement('div');
98
+ el.className = 'sample-item';
99
+ el.innerHTML = `
100
+ <div class="amount">$${item.Amount.toFixed(2)}</div>
101
+ <div class="meta">
102
+ <span>Time: ${Math.floor(item.Time)}s</span>
103
+ <span>PCA: Mixed</span>
104
+ </div>
105
+ `;
106
+ el.onclick = () => fillForm(item);
107
+ container.appendChild(el);
108
+ });
109
+ }
110
+
111
+ function fillForm(item) {
112
+ document.getElementById('Amount').value = item.Amount;
113
+ document.getElementById('Time').value = item.Time;
114
+ for (let i = 1; i <= 28; i++) {
115
+ document.getElementById(`V${i}`).value = item[`V${i}`];
116
+ }
117
+ // Trigger animation
118
+ const card = document.querySelectorAll('.card')[1];
119
+ card.style.borderColor = 'var(--primary)';
120
+ setTimeout(() => card.style.borderColor = 'var(--glass-border)', 500);
121
+ }
122
+
123
+ // Tabs
124
+ document.getElementById('tab-fraud').onclick = () => {
125
+ activeTab = 'fraud';
126
+ document.getElementById('tab-fraud').classList.add('active');
127
+ document.getElementById('tab-normal').classList.remove('active');
128
+ renderSamples();
129
+ };
130
+ document.getElementById('tab-normal').onclick = () => {
131
+ activeTab = 'normal';
132
+ document.getElementById('tab-normal').classList.add('active');
133
+ document.getElementById('tab-fraud').classList.remove('active');
134
+ renderSamples();
135
+ };
136
+
137
+ // Form Submit
138
+ document.getElementById('prediction-form').onsubmit = async (e) => {
139
+ e.preventDefault();
140
+ const btn = e.target.querySelector('button');
141
+ btn.innerHTML = 'Processing...';
142
+ btn.disabled = true;
143
+
144
+ const data = {
145
+ Amount: document.getElementById('Amount').value,
146
+ Time: document.getElementById('Time').value
147
+ };
148
+ for (let i = 1; i <= 28; i++) {
149
+ data[`V${i}`] = document.getElementById(`V${i}`).value;
150
+ }
151
+
152
+ try {
153
+ const res = await fetch('/predict', {
154
+ method: 'POST',
155
+ headers: { 'Content-Type': 'application/json' },
156
+ body: JSON.stringify(data)
157
+ });
158
+ const result = await res.json();
159
+
160
+ const resArea = document.getElementById('result-area');
161
+ resArea.style.display = 'block';
162
+ resArea.className = result.is_fraud ? 'result-fraud' : 'result-safe';
163
+
164
+ document.getElementById('res-title').innerText = result.class;
165
+ document.getElementById('res-conf').innerText = `Confidence: ${result.confidence.toFixed(2)}%`;
166
+
167
+ } catch (err) {
168
+ alert('Analysis failed: ' + err.message);
169
+ } finally {
170
+ btn.innerHTML = 'Analyze Transaction';
171
+ btn.disabled = false;
172
+ }
173
+ };
174
+ </script>
175
+ </body>
176
+ </html>
train_model.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ from sklearn.model_selection import train_test_split
4
+ from sklearn.preprocessing import StandardScaler
5
+ from sklearn.ensemble import RandomForestClassifier
6
+ from sklearn.metrics import classification_report, confusion_matrix, precision_recall_curve, auc
7
+ from imblearn.over_sampling import SMOTE
8
+ import joblib
9
+ import os
10
+
11
+ # Load data
12
+ print("Loading data...")
13
+ df = pd.read_csv('c:/card/creditcard.csv')
14
+
15
+ # Preprocessing
16
+ print("Preprocessing...")
17
+ scaler_amount = StandardScaler()
18
+ scaler_time = StandardScaler()
19
+ df['scaled_amount'] = scaler_amount.fit_transform(df['Amount'].values.reshape(-1, 1))
20
+ df['scaled_time'] = scaler_time.fit_transform(df['Time'].values.reshape(-1, 1))
21
+
22
+ # Drop original Time and Amount
23
+ df.drop(['Time', 'Amount'], axis=1, inplace=True)
24
+
25
+ # Define X and y
26
+ X = df.drop('Class', axis=1)
27
+ y = df['Class']
28
+
29
+ # Split data
30
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
31
+
32
+ # Handle imbalance with SMOTE
33
+ print("Applying SMOTE to balance training data...")
34
+ sm = SMOTE(random_state=42)
35
+ X_train_res, y_train_res = sm.fit_resample(X_train, y_train)
36
+
37
+ print(f"Original training shape: {X_train.shape}")
38
+ print(f"Resampled training shape: {X_train_res.shape}")
39
+
40
+ # Train Model
41
+ print("Training Random Forest Classifier (this might take a minute)...")
42
+ model = RandomForestClassifier(n_estimators=50, max_depth=10, random_state=42, n_jobs=-1)
43
+ model.fit(X_train_res, y_train_res)
44
+
45
+ # Evaluate
46
+ print("Evaluating model...")
47
+ y_pred = model.predict(X_test)
48
+ print("\nConfusion Matrix:")
49
+ print(confusion_matrix(y_test, y_pred))
50
+ print("\nClassification Report:")
51
+ print(classification_report(y_test, y_pred))
52
+
53
+ # Save model and scalers
54
+ print("Saving model and scalers...")
55
+ joblib.dump(model, 'c:/card/fraud_model.joblib')
56
+ joblib.dump(scaler_amount, 'c:/card/scaler_amount.joblib')
57
+ joblib.dump(scaler_time, 'c:/card/scaler_time.joblib')
58
+
59
+ print("Done! Files saved to c:/card/")
upload_to_hf.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from huggingface_hub import HfApi
2
+ import os
3
+
4
+ api = HfApi()
5
+ repo_id = "d-e-e-k-11/credit-card-fraud-detection"
6
+ local_folder = "c:/card"
7
+
8
+ print(f"Uploading files from {local_folder} to {repo_id}...")
9
+
10
+ # Files to ignore
11
+ ignore_patterns = [
12
+ ".git*",
13
+ "eda.py",
14
+ "train_model.py",
15
+ "task.md",
16
+ "implementation_plan.md",
17
+ "create_hf_space.py",
18
+ "upload_to_hf.py",
19
+ "class_distribution.png",
20
+ "distributions.png",
21
+ "scaler.joblib", # Old scaler file
22
+ "__pycache__",
23
+ ".gemini*"
24
+ ]
25
+
26
+ try:
27
+ api.upload_folder(
28
+ repo_id=repo_id,
29
+ folder_path=local_folder,
30
+ repo_type="space",
31
+ ignore_patterns=ignore_patterns
32
+ )
33
+ print("Upload complete!")
34
+ print(f"Your space is live at: https://huggingface.co/spaces/{repo_id}")
35
+ except Exception as e:
36
+ print(f"Error uploading files: {e}")