This service provides real-time fraud detection for financial transactions using a trained XGBoost/Random Forest model (based on the PaySim dataset).
Files included:
fraud_detection_service.pyβ Core service class (standalone use)fraud_detection_api.pyβ Flask REST API (production deployment)README.mdβ This guide
Your trained model files from the notebook:
fraud_detection_model.pklβ Trained XGBoost or Random Forest modelscaler.pklβ StandardScaler for feature normalizationfeature_list.pklβ List of feature names used by the model
Python dependencies:
pip install pandas numpy scikit-learn flask flask-cors joblibOptional for XGBoost support:
pip install xgboostUse fraud_detection_service.py directly in your Python code:
from fraud_detection_service import FraudDetectionService
# Initialize
service = FraudDetectionService(
model_path='fraud_detection_model.pkl',
scaler_path='scaler.pkl',
feature_path='feature_list.pkl'
)
# Process a transaction
transaction = {
'step': 5,
'type': 'TRANSFER',
'amount': 5000.00,
'oldbalanceOrg': 5000.0,
'newbalanceOrig': 0.0,
'oldbalanceDest': 0.0,
'newbalanceDest': 5000.0
}
result = service.process_transaction(transaction)
print(result)
# Output:
# {
# 'status': 'FRAUD',
# 'decision': 'BLOCK',
# 'fraud_probability': 0.95,
# 'risk_score': 95.0,
# 'actions': ['BLOCK_TRANSACTION', 'ALERT_SECURITY', ...]
# }Run the demo:
python fraud_detection_service.pyRun the Flask API server:
python fraud_detection_api.pyServer starts on http://localhost:5000
GET /healthResponse:
{
"status": "healthy",
"service": "Fraud Detection API",
"model_loaded": true,
"timestamp": "2024-01-15T10:30:00.000000"
}POST /predict
Content-Type: application/json
{
"transaction_id": "TXN_001",
"step": 1,
"type": "TRANSFER",
"amount": 5000.00,
"oldbalanceOrg": 5000.0,
"newbalanceOrig": 0.0,
"oldbalanceDest": 0.0,
"newbalanceDest": 5000.0,
"nameOrig": "C1305486145",
"nameDest": "C553264065"
}Response (Legitimate):
{
"transaction_id": "TXN_001",
"status": "LEGITIMATE",
"decision": "APPROVE",
"fraud_detected": false,
"fraud_probability": 0.02,
"confidence": 0.98,
"risk_score": 2.0,
"reason": "Low fraud probability: 2.00%",
"actions": ["APPROVE_TRANSACTION"],
"timestamp": "2024-01-15T10:30:00.000000"
}Response (Fraudulent):
{
"transaction_id": "TXN_002",
"status": "FRAUD",
"decision": "BLOCK",
"fraud_detected": true,
"fraud_probability": 0.98,
"confidence": 0.97,
"risk_score": 98.0,
"reason": "High fraud probability: 98.00%",
"actions": [
"BLOCK_TRANSACTION",
"ALERT_SECURITY",
"LOG_INCIDENT",
"FREEZE_ACCOUNT",
"NOTIFY_CUSTOMER"
],
"recommended_review_priority": "HIGH",
"timestamp": "2024-01-15T10:30:00.000000"
}POST /predict-batch
Content-Type: application/json
{
"transactions": [
{transaction_data_1},
{transaction_data_2},
...
]
}Response:
{
"total": 3,
"fraudulent": 1,
"legitimate": 2,
"errors": 0,
"results": [
{result_1},
{result_2},
{result_3}
],
"timestamp": "2024-01-15T10:30:00.000000"
}GET /model-infoResponse:
{
"model_type": "XGBClassifier",
"features": ["step", "type_encoded", "amount", ...],
"num_features": 13,
"scaler_type": "StandardScaler",
"timestamp": "2024-01-15T10:30:00.000000"
}curl http://localhost:5000/healthcurl -X POST http://localhost:5000/predict \
-H "Content-Type: application/json" \
-d '{
"step": 5,
"type": "TRANSFER",
"amount": 5000,
"oldbalanceOrg": 5000,
"newbalanceOrig": 0,
"oldbalanceDest": 0,
"newbalanceDest": 5000
}'curl -X POST http://localhost:5000/predict \
-H "Content-Type: application/json" \
-d '{
"step": 1,
"type": "PAYMENT",
"amount": 150,
"oldbalanceOrg": 1000,
"newbalanceOrig": 850,
"oldbalanceDest": 500,
"newbalanceDest": 650
}'curl -X POST http://localhost:5000/predict-batch \
-H "Content-Type: application/json" \
-d '{
"transactions": [
{
"step": 1,
"type": "PAYMENT",
"amount": 150,
"oldbalanceOrg": 1000,
"newbalanceOrig": 850,
"oldbalanceDest": 500,
"newbalanceDest": 650
},
{
"step": 5,
"type": "TRANSFER",
"amount": 5000,
"oldbalanceOrg": 5000,
"newbalanceOrig": 0,
"oldbalanceDest": 0,
"newbalanceDest": 5000
}
]
}'| Field | Type | Range | Description |
|---|---|---|---|
step |
int | β₯ 0 | Time step of transaction |
type |
str | PAYMENT, TRANSFER, CASH_OUT, DEBIT, CASH_IN | Transaction type |
amount |
float | > 0 | Transaction amount |
oldbalanceOrg |
float | β₯ 0 | Origin account balance before |
newbalanceOrig |
float | β₯ 0 | Origin account balance after |
oldbalanceDest |
float | β₯ 0 | Destination balance before |
newbalanceDest |
float | β₯ 0 | Destination balance after |
| Field | Type | Description |
|---|---|---|
transaction_id |
str | Unique transaction identifier (for logging) |
nameOrig |
str | Origin account ID |
nameDest |
str | Destination account ID |
- LEGITIMATE β Transaction passed fraud checks, safe to approve
- FRAUD β High fraud probability, should be blocked
- ERROR β Model prediction failed, manual review needed
- REJECTED β Input validation failed
- APPROVE β Accept transaction
- BLOCK β Reject transaction
- MANUAL_REVIEW β Escalate for human review
- 0.0 - 0.3 β Very unlikely to be fraud β
- 0.3 - 0.6 β Moderate risk
β οΈ - 0.6 - 0.9 β High risk π¨
- 0.9 - 1.0 β Very likely fraud β
- errorOrig β Balance mismatch at origin (40%)
- is_transfer_or_cashout β Transaction type (13%)
- oldbalanceOrg β Origin balance (12%)
- orig_zero_after β Account emptied (7%)
- log_amount β Transaction amount patterns (5%)
Fraud Probability Action
βββββββββββββββββββββββββββββ
0.0 - 0.5 APPROVE
0.5 - 0.8 MONITOR
0.8 - 0.95 BLOCK + FLAG
0.95 - 1.0 BLOCK + FREEZE + ALERT
All decisions are logged to fraud_detection.log:
- Timestamp
- Transaction ID
- Amount
- Decision (APPROVE/BLOCK)
- Fraud probability
- Actions taken
For production, add rate limiting to API:
from flask_limiter import Limiter
limiter = Limiter(app, key_func=lambda: request.remote_addr)
app.route('/predict')(limiter.limit("100 per minute")(predict))Add API key validation:
@app.before_request
def check_api_key():
if request.path != '/health':
api_key = request.headers.get('X-API-Key')
if api_key != os.getenv('FRAUD_API_KEY'):
return jsonify({'error': 'Unauthorized'}), 401| Metric | Value |
|---|---|
| ROC-AUC | 0.9987 |
| PR-AUC | 0.9452 |
| Fraud Recall | 0.8267 |
| Fraud Precision | 0.8981 |
| Accuracy | 0.9991 |
- Ensure model files are in the same directory as the scripts
- Or update paths in the code:
MODEL_PATH = Path('/path/to/fraud_detection_model.pkl')
- Ensure
feature_list.pklmatches the features used in training - Check that feature engineering code matches the notebook
# Find what's using port 5000
lsof -i :5000
# Or use a different port
python fraud_detection_api.py --port 5001- Check that scaler is correctly loaded
- Verify feature engineering matches training code
- Check for NaN values in input data
To retrain with new data:
-
Run your Jupyter notebook with latest data
-
Ensure it saves artifacts to same paths:
joblib.dump(model, 'fraud_detection_model.pkl') joblib.dump(scaler, 'scaler.pkl') joblib.dump(FEATURES, 'feature_list.pkl')
-
Restart the API server:
# Kill existing process pkill -f fraud_detection_api.py # Start new instance python fraud_detection_api.py
Create Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY fraud_detection_service.py .
COPY fraud_detection_api.py .
COPY fraud_detection_model.pkl .
COPY scaler.pkl .
COPY feature_list.pkl .
EXPOSE 5000
CMD ["python", "fraud_detection_api.py"]Build and run:
docker build -t fraud-detection .
docker run -p 5000:5000 fraud-detection- Check logs:
fraud_detection.logorfraud_api.log - Test API:
curl http://localhost:5000/health - Review examples: See "cURL Examples" section above
Internal use only. Based on PaySim dataset (Kaggle).