|
|
| import gradio as gr |
| import joblib |
| import numpy as np |
|
|
| |
| 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() |
|
|