基于队伍实力,使用Scipy计算赛事获胜概率
基于Scipy估算比赛获胜概率的实现方案
核心思路
由于无法实现《Learning to Rank the Bayesian Way》中的贝叶斯推断方法,我们可以利用**逻辑斯蒂函数(S型曲线)**映射实力差与获胜概率的关系——这是体育竞技胜率估算的常用方法,符合"实力差越大,胜率越趋近于0或1"的规律。
Scipy提供两类工具实现需求:
- 无胜负标签时:用
scipy.stats.logistic的累积分布函数(CDF)直接转换实力差; - 有胜负标签时:用
scipy.optimize.curve_fit拟合逻辑斯蒂函数参数,得到更贴合实际的结果。
数据预处理
首先修正实力差字段(原数据为绝对值,无法判断强弱):
import pandas as pd import scipy.stats as stats import scipy.optimize as opt import numpy as np # 加载你的数据 data = { 'strength_team': [30.000000, 78.332709, 59.179468, 38.104159, 59.314350, 42.622705, 37.261146, 90.000000, 70.981641, 67.744474, 83.795429, 54.289996, 37.800674, 43.634320, 74.825777, 85.818659, 32.708880, 30.000000, 53.941551, 78.332709], 'strength_opponent': [34.945673, 66.968902, 53.941551, 32.708880, 49.704009, 51.558636, 52.570251, 47.107531, 72.263020, 47.512177, 30.449607, 52.334208, 53.076058, 51.693518, 58.336456, 58.032971, 66.968902, 59.179468, 34.945673, 38.104159], 'strength_diff': [4.945673, 11.363807, 5.237917, 5.395279, 9.610341, 8.935931, 15.309105, 42.892469, 1.281379, 20.232297, 53.345822, 1.955789, 15.275384, 8.059198, 16.489322, 27.785688, 34.260022, 29.179468, 18.995879, 40.833455] } df = pd.DataFrame(data) # 计算真实实力差:己方实力 - 对手实力(正表示己方更强,负表示对手更强) df['true_diff'] = df['strength_team'] - df['strength_opponent']
方案1:无胜负标签时的快速估算
利用逻辑斯蒂分布的CDF,将真实实力差映射为0-1的概率,再转换为百分比:
# 用真实实力差的标准差作为缩放参数(控制曲线陡峭程度) scale = df['true_diff'].std() # 计算获胜概率(逻辑斯蒂CDF) df['win_prob'] = stats.logistic.cdf(df['true_diff'], loc=0, scale=scale) # 转换为百分比并保留两位小数 df['win_prob_pct'] = (df['win_prob'] * 100).round(2)
示例结果(前5行):
| strength_team | strength_opponent | true_diff | win_prob_pct |
|---|---|---|---|
| 30.00 | 34.95 | -4.95 | 41.02% |
| 78.33 | 66.97 | 11.36 | 69.01% |
| 59.18 | 53.94 | 5.24 | 59.38% |
| 38.10 | 32.71 | 5.40 | 59.77% |
| 59.31 | 49.70 | 9.61 | 65.82% |
方案2:有胜负标签时的精准拟合
如果有比赛胜负数据(假设df['win']列,1=己方胜,0=己方负),用curve_fit拟合逻辑斯蒂函数的参数:
# 定义逻辑斯蒂函数 def logistic_func(x, a, b): return 1 / (1 + np.exp(-(a + b * x))) # 模拟胜负数据(实际中替换为真实数据) df['win'] = (df['true_diff'] > 0).astype(int) # 拟合参数 x = df['true_diff'].values y = df['win'].values popt, _ = opt.curve_fit(logistic_func, x, y, p0=[0, 0.1]) # p0为初始参数猜测 # 计算获胜概率 df['win_prob'] = logistic_func(df['true_diff'], *popt) df['win_prob_pct'] = (df['win_prob'] * 100).round(2)
关键Scipy工具说明
scipy.stats.logistic:提供逻辑斯蒂分布的CDF,无需训练即可快速转换实力差为概率,适合无标签场景;scipy.optimize.curve_fit:通过最小二乘法拟合自定义函数参数,能结合胜负数据得到更精准的胜率模型。
内容的提问来源于stack exchange,提问作者8-Bit Borges
相关产品推荐
相关产品推荐

