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()