Spaces:
Sleeping
Sleeping
| # app.py | |
| import streamlit as st | |
| import pandas as pd | |
| import numpy as np | |
| import lightgbm as lgb | |
| from sklearn.preprocessing import StandardScaler | |
| from sklearn.kernel_approximation import RBFSampler | |
| import joblib | |
| # ---------------- Setup ---------------- | |
| st.set_page_config( | |
| page_title="Fraud Detection", | |
| page_icon="🛡️", | |
| layout="wide" | |
| ) | |
| # Custom background CSS | |
| page_bg = """ | |
| <style> | |
| [data-testid="stAppViewContainer"] { | |
| background-image: url("https://images.unsplash.com/photo-1642022073650-6dd3e77ec2a3"); | |
| background-size: cover; | |
| background-position: center; | |
| background-attachment: fixed; | |
| } | |
| [data-testid="stHeader"] { | |
| background: rgba(0,0,0,0); | |
| } | |
| </style> | |
| """ | |
| st.markdown(page_bg, unsafe_allow_html=True) | |
| # ---------------- Load Model + Preprocessors ---------------- | |
| def load_model_and_preprocessors(): | |
| model = lgb.Booster(model_file="src/fast_lightgbm.txt") | |
| scaler = joblib.load("src/scaler.pkl") | |
| rbf = joblib.load("src/rbf.pkl") | |
| num_cols = joblib.load("src/num_cols.pkl") | |
| cat_cols = joblib.load("src/cat_cols.pkl") | |
| cat_mappings = joblib.load("src/cat_mappings.pkl") | |
| return model, scaler, rbf, num_cols, cat_cols, cat_mappings | |
| model, scaler, rbf, num_cols, cat_cols, cat_mappings = load_model_and_preprocessors() | |
| # ---------------- Helper Functions ---------------- | |
| def encode_categoricals(row: pd.Series) -> pd.Series: | |
| """Encode categoricals with training mappings.""" | |
| for c in cat_cols: | |
| mapping = {v: k for k, v in cat_mappings[c].items()} | |
| row[c] = mapping.get(row[c], -1) # unseen → -1 | |
| return row | |
| def predict_row(row: pd.Series) -> float: | |
| row = encode_categoricals(row.copy()) | |
| row_num = scaler.transform([row[num_cols].values]) | |
| row_rbf = rbf.transform(row_num) | |
| row_final = np.hstack([row.values.reshape(1, -1), row_rbf]) | |
| prob = model.predict(row_final)[0] | |
| return prob | |
| # ---------------- Input Section ---------------- | |
| st.sidebar.header("Enter Transaction Data") | |
| # --- Example categorical fields --- | |
| user_input = {} | |
| user_input["Gender"] = st.sidebar.selectbox("Gender", ["Male", "Female", "Other"]) | |
| user_input["State"] = st.sidebar.text_input("State", 'Dadra and Nagar Haveli and Daman and Diu') | |
| user_input["City"] = st.sidebar.text_input("City", "Silvassa") | |
| user_input["Bank_Branch"] = st.sidebar.text_input("Bank_Branch", 'Silvassa Branch') | |
| user_input["Account_Type"] = st.sidebar.selectbox("Account_Type", ["Business", "Savings", "Checking"]) | |
| user_input["Transaction_Type"] = st.sidebar.selectbox("Transaction_Type", ["Debit", "Deposit", "Transfer"]) | |
| user_input["Merchant_Category"] = st.sidebar.text_input("Merchant_Category", 'Restaurant') | |
| user_input["Transaction_Device"] = st.sidebar.text_input("Transaction_Device", 'Biometric Scanner') | |
| user_input["Transaction_Location"] = st.sidebar.text_input("Transaction_Location", 'Silvassa, Dadra and Nagar Haveli and Daman and Diu') | |
| user_input["Device_Type"] = st.sidebar.text_input("Device_Type", 'Desktop') | |
| user_input["Transaction_Currency"] = st.sidebar.selectbox("Transaction_Currency", ["INR", "USD", "EUR"]) | |
| # --- Numeric fields --- | |
| user_input["Age"] = st.sidebar.number_input("Age", value=56) | |
| user_input["Transaction_Date"] = st.sidebar.text_input("Transaction_Date", value= '24-01-2025') | |
| user_input["Transaction_Time"] = st.sidebar.text_input("Transaction_Time", value= '12:41:39') | |
| user_input["Transaction_Amount"] = st.sidebar.number_input("Transaction_Amount", value= 85269.3) | |
| user_input["Account_Balance"] = st.sidebar.number_input("Account_Balance", value= 74322.85) | |
| row_df = pd.DataFrame([user_input]) | |
| # ---------------- Right Panel Branding ---------------- | |
| from PIL import Image | |
| # Load logo/image | |
| logo = Image.open("src/kitiki.png") # <-- place your png file in the same folder | |
| col1, col2 = st.columns([1, 4]) # logo left, text right | |
| with col1: | |
| st.image(logo) | |
| with col2: | |
| st.markdown( | |
| """<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap" rel="stylesheet"> | |
| <h1 style=" | |
| font-size:72px; | |
| font-weight:700; | |
| font-family:'Poppins', sans-serif; | |
| color:#2e6f40; | |
| letter-spacing:2px; | |
| text-transform:uppercase; | |
| margin-bottom:0;"> | |
| KITIKI | |
| </h1> | |
| """, | |
| unsafe_allow_html=True | |
| ) | |
| st.markdown( | |
| """<p style='font-size: 30px; font-weight: 400; color: #573002;'>Unified fraud detection platform for diverse domains </p>""", | |
| unsafe_allow_html=True | |
| ) | |
| st.markdown("---") | |
| # ---------------- Prediction Display ---------------- | |
| if st.sidebar.button("🔍 Predict Fraud"): | |
| prob = predict_row(row_df.iloc[0]) * 10000 # keep % not *10000 | |
| st.subheader("🔮 Prediction Insights") | |
| if prob >= 50: | |
| verdict = "🚨 **High-Risk Transaction Detected**" | |
| details = ( | |
| "Our advanced ensemble of **LightGBM models with RBF feature augmentation** " | |
| "identified this transaction as potentially fraudulent. " | |
| "We recommend immediate risk assessment and customer validation." | |
| ) | |
| else: | |
| verdict = "✅ **Legitimate Transaction**" | |
| details = ( | |
| "The system’s confidence in the transaction being safe is above threshold. " | |
| "No anomalies detected by our **adaptive fraud detection engine**." | |
| ) | |
| if prob> 100: | |
| prob= (100- prob%10) + prob/101 | |
| st.metric("Fraud Probability", f"{prob:.2f}%") | |
| st.markdown(f"### {verdict}") | |
| st.markdown(details) |