File size: 3,712 Bytes
cf86c3a dd8c606 4881b97 dd8c606 4881b97 dd8c606 4881b97 cf86c3a 4881b97 235d85c 4881b97 235d85c 4881b97 c41e114 4881b97 235d85c 4881b97 8b0c3b4 4881b97 c6d403e 4881b97 5d337dd 4881b97 5d337dd 4881b97 8bab071 4881b97 5d337dd 4881b97 dd8c606 4881b97 |
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 |
import gradio as gr
import pandas as pd
import joblib
import matplotlib.pyplot as plt
import seaborn as sns
import io
# Load trained model
model = joblib.load("anomaly_detector_rf_model.pkl")
# Features used during training
feature_cols = [
"amount", "hour", "day_of_week", "is_weekend", "merchant_avg_amount",
"amount_zscore", "log_amount", "type_atm_withdrawal", "type_credit",
"type_debit", "merchant_encoded"
]
# Function to detect anomalies
def detect_anomalies(df):
original_df = df.copy()
for col in ["transaction_id", "merchant", "location", "amount"]:
if col not in original_df.columns:
original_df[col] = "N/A" if col != "amount" else 0.0
model_input = df.reindex(columns=feature_cols, fill_value=0)
preds = model.predict(model_input)
original_df["is_anomalous"] = preds
anomalies = original_df[original_df["is_anomalous"] == 1]
return original_df, anomalies[["transaction_id", "merchant", "location", "amount", "is_anomalous"]]
# Function to plot charts
def plot_charts(df):
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
if "amount" in df.columns:
sns.histplot(df["amount"], bins=30, kde=True, ax=axes[0, 0])
axes[0, 0].set_title("Amount Distribution")
sns.boxplot(x=df["amount"], ax=axes[0, 1])
axes[0, 1].set_title("Amount Box Plot")
else:
axes[0, 0].text(0.5, 0.5, "No 'amount' column", ha='center')
axes[0, 1].text(0.5, 0.5, "No 'amount' column", ha='center')
if "day_of_week" in df.columns:
sns.countplot(x=df["day_of_week"], ax=axes[1, 0])
axes[1, 0].set_title("Transactions by Day of Week")
else:
axes[1, 0].text(0.5, 0.5, "No 'day_of_week' column", ha='center')
if "merchant" in df.columns:
top_merchants = df.groupby("merchant")["amount"].sum().nlargest(5).reset_index()
sns.barplot(data=top_merchants, x="merchant", y="amount", ax=axes[1, 1])
axes[1, 1].set_title("Top 5 Merchants by Amount")
else:
axes[1, 1].text(0.5, 0.5, "No 'merchant' column", ha='center')
plt.tight_layout()
return fig
# Function to generate summary + charts + file
def app_interface(csv_file):
df = pd.read_csv(csv_file)
full_df, anomalies = detect_anomalies(df)
total = len(full_df)
anom_count = len(anomalies)
percent = (anom_count / total) * 100 if total > 0 else 0
summary = (
f"π’ **Total Transactions**: {total}\n"
f"β οΈ **Anomalies Detected**: {anom_count}\n"
f"π **Anomaly Percentage**: {percent:.2f}%"
)
# Convert anomalies to CSV bytes for download
csv_bytes = anomalies.to_csv(index=False).encode()
download = io.BytesIO(csv_bytes)
fig = plot_charts(full_df)
return summary, anomalies, fig, download
# Gradio App with UI
with gr.Blocks(theme=gr.themes.Soft()) as interface:
gr.Markdown("# π‘οΈ Financial Abuse & Anomaly Detection App")
gr.Markdown("Upload your **transaction CSV** to detect anomalies and view insights.")
with gr.Row():
file_input = gr.File(label="π Upload CSV File", file_types=[".csv"])
detect_button = gr.Button("π¨ Run Detection", variant="primary")
with gr.Row():
summary_box = gr.Markdown("")
with gr.Tab("π Anomalies Detected"):
result_table = gr.Dataframe(label="π΄ Anomalies")
download_btn = gr.File(label="β¬οΈ Download Detected Anomalies")
with gr.Tab("π Transaction Charts"):
chart_output = gr.Plot()
detect_button.click(fn=app_interface, inputs=file_input,
outputs=[summary_box, result_table, chart_output, download_btn])
interface.launch(share=True)
|