Yatheshr's picture
Update app.py
9b063ce verified
import gradio as gr
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
# --- Sample Morningstar-style data ---
data = {
"5Y_Return": [14.0, 7.5, 13.2, 6.0, 15.0, 8.0, 12.0, 6.5, 10.5, 7.2],
"Volatility": [8.0, 6.5, 7.8, 9.0, 7.0, 6.2, 7.1, 8.5, 6.8, 7.9],
"Risk_Score": [2, 3, 2, 4, 1, 3, 2, 4, 2, 3],
"Rating": ["Good", "Bad", "Good", "Bad", "Good", "Bad", "Good", "Bad", "Good", "Bad"]
}
df = pd.DataFrame(data)
df["Label"] = df["Rating"].map({"Good": 1, "Bad": 0})
# --- Train full SVM model for prediction ---
X = df[["5Y_Return", "Volatility", "Risk_Score"]]
y = df["Label"]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
model = SVC(kernel="linear", probability=True)
model.fit(X_scaled, y)
# --- Function to classify and plot 2D SVM boundary ---
def classify_and_plot(return_5y, volatility, risk_score):
# Predict
input_data = [[return_5y, volatility, risk_score]]
input_scaled = scaler.transform(input_data)
prediction = model.predict(input_scaled)[0]
confidence = model.predict_proba(input_scaled)[0][prediction]
result = "Good Investment" if prediction == 1 else "Bad Investment"
# For plotting, use only 2D
X_2d = df[["5Y_Return", "Volatility"]].values
y_2d = df["Label"].values
scaler_2d = StandardScaler()
X_2d_scaled = scaler_2d.fit_transform(X_2d)
model_2d = SVC(kernel="linear")
model_2d.fit(X_2d_scaled, y_2d)
# Plot decision boundary
fig, ax = plt.subplots(figsize=(6, 5))
ax.scatter(X_2d_scaled[:, 0], X_2d_scaled[:, 1], c=y_2d, cmap="bwr", edgecolors="k", s=60)
# Support vectors
ax.scatter(model_2d.support_vectors_[:, 0], model_2d.support_vectors_[:, 1],
s=150, facecolors='none', edgecolors='k', linewidths=1.5, label="Support Vectors")
# Decision boundary
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = model_2d.decision_function(xy).reshape(XX.shape)
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1],
alpha=0.7, linestyles=['--', '-', '--'])
# Annotations
ax.set_title("SVM Decision Boundary (2 Features)")
ax.set_xlabel("5Y Return (scaled)")
ax.set_ylabel("Volatility (scaled)")
ax.legend()
ax.grid(True)
# Save and return image
plot_path = "/tmp/svm_plot.png"
fig.savefig(plot_path)
plt.close(fig)
return f"{result} (Confidence: {confidence:.2f})", plot_path
# --- Gradio UI ---
with gr.Blocks() as demo:
gr.Markdown("## 🧠 SVM Classifier: Mutual Fund Recommendation")
with gr.Row():
return_input = gr.Number(label="5-Year Return (%)", value=10.0)
vol_input = gr.Number(label="Volatility (%)", value=7.0)
risk_input = gr.Number(label="Risk Score (1=Low, 5=High)", value=3)
classify_btn = gr.Button("Classify and Show Decision Boundary")
output_label = gr.Textbox(label="Prediction")
gr.Markdown("""### πŸ“Š Benchmark Guide
**πŸ”΄ Blue Dots = Good Investments**
**πŸ”΄ Red Dots = Bad Investments**
**⚫ Solid Black Line = Decision Boundary**
**⚫ Dashed Lines = Margins (distance to support vectors)**
**β­• Large Hollow Dots = Support Vectors (key data points)**
""")
output_plot = gr.Image(label="SVM Decision Boundary")
classify_btn.click(
fn=classify_and_plot,
inputs=[return_input, vol_input, risk_input],
outputs=[output_label, output_plot]
)
if __name__ == "__main__":
demo.launch()