File size: 3,697 Bytes
0dc9917 9b063ce 0dc9917 875906d 0dc9917 9b063ce 0dc9917 9b063ce 0dc9917 9b063ce 0dc9917 9b063ce 875906d 0dc9917 875906d 9b063ce 875906d 0dc9917 9b063ce 0dc9917 875906d 0dc9917 9b063ce 875906d 0dc9917 9b063ce 0dc9917 875906d 9b063ce 0dc9917 9b063ce 0dc9917 9b063ce 0dc9917 |
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 109 |
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()
|