help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
fraud-detection
RSK World
fraud-detection
Fraud Detection Dataset - Financial Fraud ML + Anti-Fraud AI + Fraud Detection Deep Learning
fraud-detection
  • __pycache__
  • .gitignore866 B
  • ADVANCED_FEATURES.md10.6 KB
  • ERROR_CHECK_REPORT.md1.8 KB
  • GITHUB_RELEASE_GUIDE.md4.6 KB
  • LICENSE1.6 KB
  • README.md8.2 KB
  • RELEASE_NOTES.md2.8 KB
  • advanced_feature_engineering.py9.5 KB
  • feature_engineering.py9.2 KB
  • fraud_detection_analysis.ipynb12.8 KB
  • fraud_detection_dataset.csv2.3 MB
  • generate_data.py9.8 KB
  • hyperparameter_tuning.py9.8 KB
  • index.html12.3 KB
  • model_evaluation_advanced.py9.9 KB
  • predict_pipeline.py8.1 KB
  • requirements.txt462 B
  • shap_explainability.py7.4 KB
  • test_imports.py2.6 KB
  • train_model.py12.4 KB
  • verify_dataset.py1 KB
train_model.pygenerate_data.pyhyperparameter_tuning.py
train_model.py
Raw Download
Find: Go to:
"""
Fraud Detection Model Training Script

Developer: Molla Samser
Designer & Tester: Rima Khatun
Website: https://rskworld.in
Email: help@rskworld.in, support@rskworld.in, info@rskworld.com
Phone: +91 93305 39277
Company: RSK World
Description: Trains machine learning models for fraud detection
"""

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_score, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score, roc_curve, precision_recall_curve, average_precision_score
from imblearn.over_sampling import SMOTE
import matplotlib.pyplot as plt
import seaborn as sns
import joblib
import warnings
warnings.filterwarnings('ignore')

# Advanced models
try:
    import xgboost as xgb
    XGBOOST_AVAILABLE = True
except ImportError:
    XGBOOST_AVAILABLE = False
    print("XGBoost not available. Install with: pip install xgboost")

try:
    import lightgbm as lgb
    LIGHTGBM_AVAILABLE = True
except ImportError:
    LIGHTGBM_AVAILABLE = False
    print("LightGBM not available. Install with: pip install lightgbm")

try:
    import shap
    SHAP_AVAILABLE = True
except ImportError:
    SHAP_AVAILABLE = False
    print("SHAP not available. Install with: pip install shap")

# Set style for plots
try:
    plt.style.use('seaborn-v0_8-darkgrid')
except OSError:
    try:
        plt.style.use('seaborn-darkgrid')
    except OSError:
        plt.style.use('default')
sns.set_palette("husl")

def load_data(file_path='fraud_detection_dataset.csv'):
    """
    Load the fraud detection dataset
    
    Parameters:
    -----------
    file_path : str
        Path to the CSV file
    
    Returns:
    --------
    pd.DataFrame
        Loaded dataset
    """
    print("Loading dataset...")
    df = pd.read_csv(file_path)
    print(f"Dataset loaded: {len(df)} records")
    return df

def preprocess_data(df, use_advanced_features=True):
    """
    Preprocess the data for machine learning with advanced feature engineering
    
    Parameters:
    -----------
    df : pd.DataFrame
        Raw dataset
    use_advanced_features : bool
        Whether to use advanced feature engineering
    
    Returns:
    --------
    tuple
        Features (X) and target (y)
    """
    print("\nPreprocessing data...")
    
    # Import feature engineering module
    if use_advanced_features:
        try:
            from advanced_feature_engineering import engineer_advanced_features
            print("Using advanced feature engineering...")
            df_processed = engineer_advanced_features(df)
        except ImportError:
            print("Advanced feature engineering module not found, using basic preprocessing...")
            df_processed = df.copy()
    else:
        df_processed = df.copy()
    
    # Convert timestamp to datetime if it's string
    if 'timestamp' in df_processed.columns:
        df_processed['timestamp'] = pd.to_datetime(df_processed['timestamp'])
        if 'day_of_week' not in df_processed.columns:
            df_processed['day_of_week'] = df_processed['timestamp'].dt.dayofweek
        if 'month' not in df_processed.columns:
            df_processed['month'] = df_processed['timestamp'].dt.month
        df_processed = df_processed.drop('timestamp', axis=1)
    
    # Encode categorical variables
    label_encoders = {}
    categorical_cols = ['merchant_category', 'location', 'device_type', 'user_id']
    
    for col in categorical_cols:
        if col in df_processed.columns:
            le = LabelEncoder()
            df_processed[col] = le.fit_transform(df_processed[col].astype(str))
            label_encoders[col] = le
    
    # Drop transaction_id (not useful for prediction)
    if 'transaction_id' in df_processed.columns:
        df_processed = df_processed.drop('transaction_id', axis=1)
    
    # Separate features and target
    X = df_processed.drop('is_fraud', axis=1)
    y = df_processed['is_fraud']
    
    print(f"Features shape: {X.shape}")
    print(f"Target distribution:\n{y.value_counts()}")
    
    return X, y, label_encoders

def handle_imbalance(X, y):
    """
    Handle class imbalance using SMOTE
    
    Parameters:
    -----------
    X : pd.DataFrame
        Features
    y : pd.Series
        Target variable
    
    Returns:
    --------
    tuple
        Balanced X and y
    """
    print("\nHandling class imbalance with SMOTE...")
    smote = SMOTE(random_state=42)
    X_balanced, y_balanced = smote.fit_resample(X, y)
    print(f"After SMOTE - Features shape: {X_balanced.shape}")
    print(f"After SMOTE - Target distribution:\n{pd.Series(y_balanced).value_counts()}")
    return X_balanced, y_balanced

def train_advanced_models(X, y, use_smote=True):
    """
    Train multiple advanced models for fraud detection
    
    Parameters:
    -----------
    X : pd.DataFrame
        Features
    y : pd.Series
        Target variable
    use_smote : bool
        Whether to use SMOTE for balancing
    
    Returns:
    --------
    dict
        Dictionary of trained models and their results
    """
    print("\nTraining advanced models...")
    
    # Handle imbalance if requested
    if use_smote:
        X_train, y_train = handle_imbalance(X, y)
        X_train, X_test, y_train, y_test = train_test_split(
            X_train, y_train, test_size=0.2, random_state=42, stratify=y_train
        )
    else:
        X_train, X_test, y_train, y_test = train_test_split(
            X, y, test_size=0.2, random_state=42, stratify=y
        )
    
    models = {}
    results = {}
    
    # 1. Random Forest
    print("\n" + "="*50)
    print("Training Random Forest...")
    print("="*50)
    rf_model = RandomForestClassifier(
        n_estimators=200,
        max_depth=25,
        min_samples_split=5,
        min_samples_leaf=2,
        random_state=42,
        n_jobs=-1,
        class_weight='balanced'
    )
    rf_model.fit(X_train, y_train)
    models['RandomForest'] = rf_model
    
    # 2. XGBoost
    if XGBOOST_AVAILABLE:
        print("\n" + "="*50)
        print("Training XGBoost...")
        print("="*50)
        xgb_model = xgb.XGBClassifier(
            n_estimators=200,
            max_depth=6,
            learning_rate=0.1,
            subsample=0.8,
            colsample_bytree=0.8,
            random_state=42,
            eval_metric='logloss',
            scale_pos_weight=(y_train == 0).sum() / (y_train == 1).sum()
        )
        xgb_model.fit(X_train, y_train)
        models['XGBoost'] = xgb_model
    
    # 3. LightGBM
    if LIGHTGBM_AVAILABLE:
        print("\n" + "="*50)
        print("Training LightGBM...")
        print("="*50)
        lgb_model = lgb.LGBMClassifier(
            n_estimators=200,
            max_depth=7,
            learning_rate=0.1,
            subsample=0.8,
            colsample_bytree=0.8,
            random_state=42,
            class_weight='balanced',
            verbose=-1
        )
        lgb_model.fit(X_train, y_train)
        models['LightGBM'] = lgb_model
    
    # Evaluate all models
    print("\n" + "="*70)
    print("MODEL COMPARISON")
    print("="*70)
    
    for model_name, model in models.items():
        print(f"\n{model_name} Evaluation:")
        print("-" * 50)
        
        y_pred = model.predict(X_test)
        y_pred_proba = model.predict_proba(X_test)[:, 1]
        
        # Metrics
        roc_auc = roc_auc_score(y_test, y_pred_proba)
        avg_precision = average_precision_score(y_test, y_pred_proba)
        
        print(f"ROC AUC Score: {roc_auc:.4f}")
        print(f"Average Precision: {avg_precision:.4f}")
        print("\nClassification Report:")
        print(classification_report(y_test, y_pred))
        
        results[model_name] = {
            'model': model,
            'y_pred': y_pred,
            'y_pred_proba': y_pred_proba,
            'roc_auc': roc_auc,
            'avg_precision': avg_precision
        }
    
    # Find best model
    best_model_name = max(results.keys(), key=lambda x: results[x]['roc_auc'])
    print(f"\n{'='*70}")
    print(f"Best Model: {best_model_name} (ROC AUC: {results[best_model_name]['roc_auc']:.4f})")
    print(f"{'='*70}")
    
    # Plot comparison
    plot_model_comparison(results, y_test, X.columns)
    
    return models, results, X_test, y_test, best_model_name

def plot_model_comparison(results, y_test, feature_names):
    """Plot comparison of different models"""
    
    # ROC Curves Comparison
    plt.figure(figsize=(12, 5))
    
    plt.subplot(1, 2, 1)
    for model_name, result in results.items():
        fpr, tpr, _ = roc_curve(y_test, result['y_pred_proba'])
        plt.plot(fpr, tpr, label=f"{model_name} (AUC = {result['roc_auc']:.3f})")
    plt.plot([0, 1], [0, 1], 'k--', label='Random Classifier')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('ROC Curves Comparison')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    # Precision-Recall Curves
    plt.subplot(1, 2, 2)
    for model_name, result in results.items():
        precision, recall, _ = precision_recall_curve(y_test, result['y_pred_proba'])
        plt.plot(recall, precision, label=f"{model_name} (AP = {result['avg_precision']:.3f})")
    plt.xlabel('Recall')
    plt.ylabel('Precision')
    plt.title('Precision-Recall Curves Comparison')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('model_comparison.png', dpi=300, bbox_inches='tight')
    print("\nModel comparison plots saved to model_comparison.png")
    
    # Feature importance for best model
    best_model_name = max(results.keys(), key=lambda x: results[x]['roc_auc'])
    best_model = results[best_model_name]['model']
    
    if hasattr(best_model, 'feature_importances_'):
        feature_importance = pd.DataFrame({
            'feature': feature_names,
            'importance': best_model.feature_importances_
        }).sort_values('importance', ascending=False)
        
        plt.figure(figsize=(10, 8))
        top_features = feature_importance.head(20)
        sns.barplot(data=top_features, y='feature', x='importance')
        plt.title(f'Top 20 Feature Importances - {best_model_name}')
        plt.xlabel('Importance')
        plt.tight_layout()
        plt.savefig('feature_importance_advanced.png', dpi=300, bbox_inches='tight')
        print(f"Feature importance plot saved to feature_importance_advanced.png")
        
        print(f"\nTop 15 Most Important Features ({best_model_name}):")
        print(feature_importance.head(15))

def train_model(X, y, use_smote=True):
    """
    Train Random Forest model for fraud detection (backward compatibility)
    
    Parameters:
    -----------
    X : pd.DataFrame
        Features
    y : pd.Series
        Target variable
    use_smote : bool
        Whether to use SMOTE for balancing
    
    Returns:
    --------
    sklearn.estimator
        Trained model
    """
    models, results, X_test, y_test, best_model_name = train_advanced_models(X, y, use_smote)
    return results[best_model_name]['model'], X_test, y_test

def save_model(model, filename='fraud_detection_model.pkl'):
    """
    Save the trained model
    
    Parameters:
    -----------
    model : sklearn.estimator
        Trained model
    filename : str
        Output filename
    """
    joblib.dump(model, filename)
    print(f"\nModel saved to {filename}")

def main():
    """Main function"""
    print("="*50)
    print("FRAUD DETECTION MODEL TRAINING")
    print("Developer: Molla Samser")
    print("Website: https://rskworld.in")
    print("="*50)
    
    # Load data
    df = load_data()
    
    # Preprocess with advanced features
    X, y, label_encoders = preprocess_data(df, use_advanced_features=True)
    
    # Train advanced models
    models, results, X_test, y_test, best_model_name = train_advanced_models(X, y, use_smote=True)
    model = results[best_model_name]['model']
    
    # Save model
    save_model(model)
    
    print("\n" + "="*50)
    print("Training completed successfully!")
    print("="*50)

if __name__ == "__main__":
    main()

405 lines•12.4 KB
python
generate_data.py
Raw Download
Find: Go to:
"""
Fraud Detection Dataset Generator

Developer: Molla Samser
Designer & Tester: Rima Khatun
Website: https://rskworld.in
Email: help@rskworld.in, support@rskworld.in, info@rskworld.com
Phone: +91 93305 39277
Company: RSK World
Description: Generates synthetic fraud detection dataset with transaction records
"""

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import random

# Set random seed for reproducibility
np.random.seed(42)
random.seed(42)

def generate_fraud_dataset(n_samples=10000, fraud_ratio=0.05):
    """
    Generate synthetic fraud detection dataset
    
    Parameters:
    -----------
    n_samples : int
        Total number of transactions to generate
    fraud_ratio : float
        Ratio of fraudulent transactions (for imbalanced dataset)
    
    Returns:
    --------
    pd.DataFrame
        Dataset with transaction features and fraud labels
    """
    
    n_fraud = int(n_samples * fraud_ratio)
    n_normal = n_samples - n_fraud
    
    # Merchant categories
    merchant_categories = ['Retail', 'Grocery', 'Restaurant', 'Gas', 'Online', 
                          'Pharmacy', 'Travel', 'Entertainment', 'Utilities', 'Other']
    
    # Device types
    device_types = ['Mobile', 'Desktop', 'Tablet', 'ATM', 'POS']
    
    # Location codes
    locations = ['US', 'UK', 'CA', 'AU', 'FR', 'DE', 'IT', 'ES', 'NL', 'BE']
    
    data = []
    
    # Generate normal transactions
    for i in range(n_normal):
        user_id = np.random.randint(1, 5000)
        amount = np.random.lognormal(mean=3.5, sigma=1.2)
        amount = min(amount, 10000)  # Cap at 10000
        
        transaction = {
            'transaction_id': f'TXN_{i+1:06d}',
            'user_id': f'USER_{user_id:04d}',
            'amount': round(amount, 2),
            'merchant_category': np.random.choice(merchant_categories),
            'location': np.random.choice(locations),
            'timestamp': datetime.now() - timedelta(days=np.random.randint(0, 365), 
                                                    hours=np.random.randint(0, 24),
                                                    minutes=np.random.randint(0, 60)),
            'device_type': np.random.choice(device_types),
            'user_age': np.random.randint(18, 80),
            'account_age_days': np.random.randint(1, 3650),
            'transaction_count_24h': np.random.poisson(2),
            'avg_transaction_amount': round(np.random.lognormal(mean=3.5, sigma=1.0), 2),
            'is_foreign_transaction': np.random.choice([0, 1], p=[0.7, 0.3]),
            'is_weekend': np.random.choice([0, 1], p=[0.7, 0.3]),
            'hour_of_day': np.random.randint(0, 24),
            'is_fraud': 0
        }
        data.append(transaction)
    
    # Generate fraudulent transactions (with different patterns)
    for i in range(n_fraud):
        user_id = np.random.randint(1, 5000)
        # Fraud transactions tend to be larger
        amount = np.random.lognormal(mean=4.5, sigma=1.5)
        amount = min(amount, 50000)  # Higher cap for fraud
        
        # Fraud more likely at unusual hours
        unusual_hours = [0, 1, 2, 3, 4, 5, 22, 23]
        normal_hours = list(range(6, 22))
        all_hours = unusual_hours + normal_hours
        # Create probabilities: 0.12 for unusual hours, rest distributed among normal hours
        p_unusual = 0.12
        total_unusual_prob = len(unusual_hours) * p_unusual
        p_normal = (1 - total_unusual_prob) / len(normal_hours)
        probs = [p_unusual] * len(unusual_hours) + [p_normal] * len(normal_hours)
        hour = np.random.choice(all_hours, p=probs)
        
        transaction = {
            'transaction_id': f'TXN_{n_normal+i+1:06d}',
            'user_id': f'USER_{user_id:04d}',
            'amount': round(amount, 2),
            'merchant_category': np.random.choice(merchant_categories),
            'location': np.random.choice(locations),  # Fraud more likely foreign
            'timestamp': datetime.now() - timedelta(days=np.random.randint(0, 365), 
                                                    hours=int(hour),
                                                    minutes=np.random.randint(0, 60)),
            'device_type': np.random.choice(device_types),
            'user_age': np.random.randint(18, 80),
            'account_age_days': np.random.randint(1, 365),  # Newer accounts more risky
            'transaction_count_24h': np.random.poisson(5),  # More transactions
            'avg_transaction_amount': round(np.random.lognormal(mean=4.0, sigma=1.2), 2),
            'is_foreign_transaction': np.random.choice([0, 1], p=[0.3, 0.7]),  # More foreign
            'is_weekend': np.random.choice([0, 1], p=[0.6, 0.4]),
            'hour_of_day': hour,
            'is_fraud': 1
        }
        data.append(transaction)
    
    # Create DataFrame
    df = pd.DataFrame(data)
    
    # Convert timestamp to datetime
    df['timestamp'] = pd.to_datetime(df['timestamp'])
    df = df.sort_values(['user_id', 'timestamp']).reset_index(drop=True)
    
    # Advanced Feature Engineering
    print("Generating advanced features...")
    
    # Time-based features
    df['day_of_week'] = df['timestamp'].dt.dayofweek
    df['month'] = df['timestamp'].dt.month
    df['is_month_end'] = (df['timestamp'].dt.day > 25).astype(int)
    df['is_month_start'] = (df['timestamp'].dt.day <= 5).astype(int)
    
    # Transaction velocity features
    df['time_since_last_transaction'] = df.groupby('user_id')['timestamp'].diff().dt.total_seconds() / 3600  # hours
    df['time_since_last_transaction'] = df['time_since_last_transaction'].fillna(24)  # First transaction assumed 24h ago
    
    # Transaction count features (simplified - count previous transactions)
    df['transaction_count_7d'] = df.groupby('user_id').cumcount() + 1
    df['transaction_count_30d'] = df.groupby('user_id').cumcount() + 1
    
    # Amount-based features
    df['amount_zscore'] = df.groupby('user_id')['amount'].transform(lambda x: (x - x.mean()) / x.std() if x.std() > 0 else 0)
    df['amount_zscore'] = df['amount_zscore'].fillna(0)
    df['amount_percentile'] = df.groupby('user_id')['amount'].transform(lambda x: x.rank(pct=True))
    df['amount_percentile'] = df['amount_percentile'].fillna(0.5)
    
    # Rolling statistics (using expanding window for simplicity)
    df['amount_rolling_mean_7d'] = df.groupby('user_id')['amount'].transform(lambda x: x.expanding(min_periods=1).mean())
    df['amount_rolling_std_7d'] = df.groupby('user_id')['amount'].transform(lambda x: x.expanding(min_periods=1).std())
    df['amount_rolling_std_7d'] = df['amount_rolling_std_7d'].fillna(0)
    
    # Location change indicator
    df['location_changed'] = (df.groupby('user_id')['location'].shift() != df['location']).astype(int)
    df['location_changed'] = df['location_changed'].fillna(0)
    
    # Device change indicator
    df['device_changed'] = (df.groupby('user_id')['device_type'].shift() != df['device_type']).astype(int)
    df['device_changed'] = df['device_changed'].fillna(0)
    
    # Merchant category change
    df['merchant_category_changed'] = (df.groupby('user_id')['merchant_category'].shift() != df['merchant_category']).astype(int)
    df['merchant_category_changed'] = df['merchant_category_changed'].fillna(0)
    
    # Risk score based on multiple factors
    df['risk_score'] = (
        (df['is_foreign_transaction'] * 0.2) +
        (df['transaction_count_24h'] > 5).astype(int) * 0.15 +
        (df['amount'] > df.groupby('user_id')['amount'].transform('quantile', 0.95)).astype(int) * 0.2 +
        (df['account_age_days'] < 30).astype(int) * 0.15 +
        (df['hour_of_day'].isin([0, 1, 2, 3, 4, 5, 22, 23])).astype(int) * 0.1 +
        (df['time_since_last_transaction'] < 1).astype(int) * 0.1 +
        (df['location_changed'] * 0.1)
    )
    
    # Interaction features
    df['amount_x_transaction_count'] = df['amount'] * df['transaction_count_24h']
    df['amount_x_is_foreign'] = df['amount'] * df['is_foreign_transaction']
    df['transaction_count_x_is_foreign'] = df['transaction_count_24h'] * df['is_foreign_transaction']
    
    # Time patterns
    df['is_rush_hour'] = df['hour_of_day'].isin([7, 8, 9, 17, 18, 19]).astype(int)
    df['is_off_hours'] = df['hour_of_day'].isin([0, 1, 2, 3, 4, 5, 22, 23]).astype(int)
    
    # User behavior patterns
    df['avg_amount_ratio'] = df['amount'] / (df['avg_transaction_amount'] + 1)
    df['transaction_velocity'] = df['transaction_count_24h'] / (df['time_since_last_transaction'] + 0.1)
    
    # Fill NaN values
    df = df.fillna(0)
    
    # Shuffle the dataset
    df = df.sample(frac=1, random_state=42).reset_index(drop=True)
    
    return df

if __name__ == "__main__":
    print("Generating fraud detection dataset...")
    print("Developer: Molla Samser")
    print("Website: https://rskworld.in")
    print("-" * 50)
    
    # Generate dataset
    df = generate_fraud_dataset(n_samples=10000, fraud_ratio=0.05)
    
    # Save to CSV
    df.to_csv('fraud_detection_dataset.csv', index=False)
    print(f"Dataset saved to fraud_detection_dataset.csv")
    print(f"Total transactions: {len(df)}")
    print(f"Fraudulent transactions: {df['is_fraud'].sum()}")
    print(f"Normal transactions: {(df['is_fraud'] == 0).sum()}")
    print(f"Fraud ratio: {df['is_fraud'].mean():.2%}")
    
    # Save to Excel (optional)
    try:
        df.to_excel('fraud_detection_dataset.xlsx', index=False)
        print(f"Dataset saved to fraud_detection_dataset.xlsx")
    except Exception as e:
        print(f"Note: Excel file not generated ({str(e)}). CSV file is available.")
    
    # Display sample
    print("\nSample data:")
    print(df.head(10))
    print("\nDataset statistics:")
    print(df.describe())

229 lines•9.8 KB
python
hyperparameter_tuning.py
Raw Download
Find: Go to:
"""
Hyperparameter Tuning for Fraud Detection Models

Developer: Molla Samser
Designer & Tester: Rima Khatun
Website: https://rskworld.in
Email: help@rskworld.in, support@rskworld.in, info@rskworld.com
Phone: +91 93305 39277
Company: RSK World
Description: Hyperparameter tuning using GridSearchCV and RandomizedSearchCV
"""

import pandas as pd
import numpy as np
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import make_scorer, roc_auc_score, f1_score, precision_score, recall_score
from sklearn.preprocessing import LabelEncoder
from imblearn.over_sampling import SMOTE
import joblib
import warnings
warnings.filterwarnings('ignore')

# Advanced models
try:
    import xgboost as xgb
    XGBOOST_AVAILABLE = True
except ImportError:
    XGBOOST_AVAILABLE = False

try:
    import lightgbm as lgb
    LIGHTGBM_AVAILABLE = True
except ImportError:
    LIGHTGBM_AVAILABLE = False

def load_and_preprocess_data(file_path='fraud_detection_dataset.csv', use_advanced_features=False):
    """
    Load and preprocess data
    
    Parameters:
    -----------
    file_path : str
        Path to dataset
    use_advanced_features : bool
        Whether to use advanced feature engineering
    
    Returns:
    --------
    tuple
        X, y
    """
    print("Loading and preprocessing data...")
    df = pd.read_csv(file_path)
    
    if use_advanced_features:
        from advanced_feature_engineering import engineer_advanced_features
        df = engineer_advanced_features(df)
    
    # Preprocess
    df_model = df.copy()
    
    # Encode categorical variables
    categorical_cols = ['merchant_category', 'location', 'device_type', 'user_id']
    label_encoders = {}
    
    for col in categorical_cols:
        if col in df_model.columns:
            le = LabelEncoder()
            df_model[col] = le.fit_transform(df_model[col].astype(str))
            label_encoders[col] = le
    
    # Drop unnecessary columns
    drop_cols = ['transaction_id', 'is_fraud', 'timestamp']
    X = df_model.drop([col for col in drop_cols if col in df_model.columns], axis=1)
    y = df_model['is_fraud']
    
    # Handle imbalance with SMOTE
    smote = SMOTE(random_state=42)
    X_balanced, y_balanced = smote.fit_resample(X, y)
    
    print(f"Data shape: {X_balanced.shape}")
    return X_balanced, y_balanced

def tune_random_forest(X, y, cv=3, n_iter=50):
    """
    Tune Random Forest hyperparameters
    
    Parameters:
    -----------
    X : pd.DataFrame
        Features
    y : pd.Series
        Target
    cv : int
        Number of CV folds
    n_iter : int
        Number of iterations for RandomizedSearch
    
    Returns:
    --------
    sklearn.model_selection.RandomizedSearchCV
        Best model
    """
    print("\n" + "="*50)
    print("Tuning Random Forest...")
    print("="*50)
    
    param_grid = {
        'n_estimators': [100, 200, 300],
        'max_depth': [10, 20, 30, None],
        'min_samples_split': [2, 5, 10],
        'min_samples_leaf': [1, 2, 4],
        'max_features': ['sqrt', 'log2', None],
        'class_weight': ['balanced', 'balanced_subsample']
    }
    
    rf = RandomForestClassifier(random_state=42, n_jobs=-1)
    
    # Use RandomizedSearchCV for faster tuning
    random_search = RandomizedSearchCV(
        rf, param_grid, 
        n_iter=n_iter,
        cv=StratifiedKFold(n_splits=cv, shuffle=True, random_state=42),
        scoring='roc_auc',
        n_jobs=-1,
        random_state=42,
        verbose=1
    )
    
    random_search.fit(X, y)
    
    print(f"\nBest parameters: {random_search.best_params_}")
    print(f"Best CV score: {random_search.best_score_:.4f}")
    
    return random_search

def tune_xgboost(X, y, cv=3, n_iter=50):
    """
    Tune XGBoost hyperparameters
    
    Parameters:
    -----------
    X : pd.DataFrame
        Features
    y : pd.Series
        Target
    cv : int
        Number of CV folds
    n_iter : int
        Number of iterations
    
    Returns:
    --------
    sklearn.model_selection.RandomizedSearchCV
        Best model
    """
    if not XGBOOST_AVAILABLE:
        print("XGBoost not available. Skipping...")
        return None
    
    print("\n" + "="*50)
    print("Tuning XGBoost...")
    print("="*50)
    
    param_grid = {
        'n_estimators': [100, 200, 300],
        'max_depth': [3, 5, 7, 10],
        'learning_rate': [0.01, 0.1, 0.2],
        'subsample': [0.6, 0.8, 1.0],
        'colsample_bytree': [0.6, 0.8, 1.0],
        'min_child_weight': [1, 3, 5],
        'gamma': [0, 0.1, 0.2]
    }
    
    xgb_model = xgb.XGBClassifier(
        random_state=42,
        eval_metric='logloss',
        scale_pos_weight=(y == 0).sum() / (y == 1).sum()
    )
    
    random_search = RandomizedSearchCV(
        xgb_model, param_grid,
        n_iter=n_iter,
        cv=StratifiedKFold(n_splits=cv, shuffle=True, random_state=42),
        scoring='roc_auc',
        n_jobs=-1,
        random_state=42,
        verbose=1
    )
    
    random_search.fit(X, y)
    
    print(f"\nBest parameters: {random_search.best_params_}")
    print(f"Best CV score: {random_search.best_score_:.4f}")
    
    return random_search

def tune_lightgbm(X, y, cv=3, n_iter=50):
    """
    Tune LightGBM hyperparameters
    
    Parameters:
    -----------
    X : pd.DataFrame
        Features
    y : pd.Series
        Target
    cv : int
        Number of CV folds
    n_iter : int
        Number of iterations
    
    Returns:
    --------
    sklearn.model_selection.RandomizedSearchCV
        Best model
    """
    if not LIGHTGBM_AVAILABLE:
        print("LightGBM not available. Skipping...")
        return None
    
    print("\n" + "="*50)
    print("Tuning LightGBM...")
    print("="*50)
    
    param_grid = {
        'n_estimators': [100, 200, 300],
        'max_depth': [3, 5, 7, 10, -1],
        'learning_rate': [0.01, 0.1, 0.2],
        'subsample': [0.6, 0.8, 1.0],
        'colsample_bytree': [0.6, 0.8, 1.0],
        'min_child_samples': [20, 30, 50],
        'num_leaves': [31, 50, 100]
    }
    
    lgb_model = lgb.LGBMClassifier(
        random_state=42,
        class_weight='balanced',
        verbose=-1
    )
    
    random_search = RandomizedSearchCV(
        lgb_model, param_grid,
        n_iter=n_iter,
        cv=StratifiedKFold(n_splits=cv, shuffle=True, random_state=42),
        scoring='roc_auc',
        n_jobs=-1,
        random_state=42,
        verbose=1
    )
    
    random_search.fit(X, y)
    
    print(f"\nBest parameters: {random_search.best_params_}")
    print(f"Best CV score: {random_search.best_score_:.4f}")
    
    return random_search

def compare_tuned_models(models_dict, X_test, y_test):
    """
    Compare tuned models on test set
    
    Parameters:
    -----------
    models_dict : dict
        Dictionary of model names and tuned models
    X_test : pd.DataFrame
        Test features
    y_test : pd.Series
        Test target
    """
    print("\n" + "="*50)
    print("MODEL COMPARISON ON TEST SET")
    print("="*50)
    
    results = []
    
    for name, model in models_dict.items():
        if model is None:
            continue
        
        y_pred = model.predict(X_test)
        y_pred_proba = model.predict_proba(X_test)[:, 1]
        
        auc = roc_auc_score(y_test, y_pred_proba)
        f1 = f1_score(y_test, y_pred)
        precision = precision_score(y_test, y_pred)
        recall = recall_score(y_test, y_pred)
        
        results.append({
            'Model': name,
            'ROC-AUC': auc,
            'F1-Score': f1,
            'Precision': precision,
            'Recall': recall
        })
        
        print(f"\n{name}:")
        print(f"  ROC-AUC: {auc:.4f}")
        print(f"  F1-Score: {f1:.4f}")
        print(f"  Precision: {precision:.4f}")
        print(f"  Recall: {recall:.4f}")
    
    results_df = pd.DataFrame(results)
    results_df = results_df.sort_values('ROC-AUC', ascending=False)
    
    print("\n" + "="*50)
    print("RANKED MODELS:")
    print("="*50)
    print(results_df.to_string(index=False))
    
    return results_df

def main():
    """Main function"""
    print("="*50)
    print("HYPERPARAMETER TUNING FOR FRAUD DETECTION")
    print("Developer: Molla Samser")
    print("Website: https://rskworld.in")
    print("="*50)
    
    # Load and preprocess data
    X, y = load_and_preprocess_data(use_advanced_features=True)
    
    # Split into train and test
    from sklearn.model_selection import train_test_split
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42, stratify=y
    )
    
    # Tune models
    tuned_models = {}
    
    tuned_models['RandomForest'] = tune_random_forest(X_train, y_train, cv=3, n_iter=30)
    tuned_models['XGBoost'] = tune_xgboost(X_train, y_train, cv=3, n_iter=30)
    tuned_models['LightGBM'] = tune_lightgbm(X_train, y_train, cv=3, n_iter=30)
    
    # Compare models
    results_df = compare_tuned_models(tuned_models, X_test, y_test)
    
    # Save best model
    best_model_name = results_df.iloc[0]['Model']
    best_model = tuned_models[best_model_name].best_estimator_
    
    joblib.dump(best_model, f'best_tuned_model_{best_model_name.lower()}.pkl')
    print(f"\nBest model ({best_model_name}) saved to best_tuned_model_{best_model_name.lower()}.pkl")
    
    # Save results
    results_df.to_csv('hyperparameter_tuning_results.csv', index=False)
    print("Results saved to hyperparameter_tuning_results.csv")

if __name__ == "__main__":
    main()

356 lines•9.8 KB
python

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer