File size: 3,260 Bytes
3bd6c88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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

import gradio as gr
import joblib
import numpy as np

# 模型載入(需確認這些檔案存在於 Hugging Face Space 中)
clf_result = joblib.load("clf_result.pkl")
clf_cov = joblib.load("clf_cov.pkl")
clf_ou = joblib.load("clf_ou.pkl")
clf_score = joblib.load("clf_score.pkl")
score_classes = joblib.load("score_classes.pkl")

def parse_ah(value):
    try:
        if '/' in value:
            parts = value.replace('+', '').split('/')
            return round((float(parts[0]) + float(parts[1])) / 2, 2)
        else:
            return float(value.replace('+', ''))
    except:
        raise ValueError("❌ 讓球盤格式錯誤,請輸入 0.5 或 +0.5/+1")

def predict_all(B365H, B365D, B365A, Over25, Under25, AHCh, AHH, AHA):
    try:
        prob_h = 1 / float(B365H)
        prob_d = 1 / float(B365D)
        prob_a = 1 / float(B365A)
        sum_prob = prob_h + prob_d + prob_a
        imp_prob_h = prob_h / sum_prob
        imp_prob_d = prob_d / sum_prob
        imp_prob_a = prob_a / sum_prob

        over_prob = 1 / float(Over25)
        under_prob = 1 / float(Under25)
        over_diff = over_prob - under_prob
        ah_diff = float(AHH) - float(AHA)
        ah_value = parse_ah(AHCh)

        features = [[imp_prob_h, imp_prob_d, imp_prob_a, over_diff, ah_diff, ah_value]]

        prob_res = clf_result.predict_proba(features)[0]
        pred_res = clf_result.classes_[prob_res.argmax()]
        prob_cov = clf_cov.predict_proba(features)[0]
        pred_cov = "Covered" if prob_cov[1] >= 0.5 else "Not Covered"
        prob_ou = clf_ou.predict_proba(features)[0]
        pred_ou = "Over" if prob_ou[1] >= 0.5 else "Under"

        prob_score = clf_score.predict_proba(features)[0]
        top3_idx = prob_score.argsort()[::-1][:3]
        top3_scores = [(score_classes[i], prob_score[i]) for i in top3_idx]
        score_text = "\n".join([f"🥇🥈🥉"[i] + f" {s}{p*100:.1f}%)" for i, (s, p) in enumerate(top3_scores)])

        conf = max(prob_res.max(), prob_cov[1], prob_ou[1])
        if conf >= 0.7:
            confidence = "High"
        elif conf >= 0.5:
            confidence = "Medium"
        else:
            confidence = "Low"

        return {
            "result": pred_res,
            "result_prob": round(prob_res.max(), 4),
            "handicap": pred_cov,
            "handicap_prob": round(max(prob_cov), 4),
            "ou": pred_ou,
            "ou_prob": round(max(prob_ou), 4),
            "confidence": confidence,
            "score_top3": top3_scores
        }
    except Exception as e:
        return {"error": str(e)}

demo = gr.Interface(
    fn=predict_all,
    inputs=[
        gr.Textbox(label="主勝賠率 B365H"),
        gr.Textbox(label="和局賠率 B365D"),
        gr.Textbox(label="客勝賠率 B365A"),
        gr.Textbox(label="Over 2.5 賠率"),
        gr.Textbox(label="Under 2.5 賠率"),
        gr.Textbox(label="讓球盤口(如 +0.5/+1)"),
        gr.Textbox(label="主隊讓球賠率 AHH"),
        gr.Textbox(label="客隊受讓賠率 AHA"),
    ],
    outputs="json",
    title="⚽ 比賽預測 API + UI",
    description="輸入盤口與賠率,預測勝負、過盤、大小、正確比分、信心等級",
    allow_flagging="never"
)

demo.launch()