本文目录导读:

我来提供一个预测点球大战胜负走向的Python案例,涵盖多个维度的分析:
基础概率模型
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
class PenaltyShootoutPredictor:
def __init__(self):
# 基础命中率(基于历史数据)
self.base_success_rate = {
'average': 0.75, # 平均命中率
'elite': 0.80, # 精英射手
'weak': 0.65 # 较弱射手
}
# 门将扑救率
self.goalkeeper_save_rate = {
'top': 0.25, # 顶级门将
'average': 0.15, # 平均门将
'weak': 0.10 # 较弱门将
}
def monte_carlo_simulation(self, team_a_probs, team_b_probs, n_simulations=10000):
"""
蒙特卡洛模拟点球大战
参数:
- team_a_probs: A队每个球员的进球概率列表
- team_b_probs: B队每个球员的进球概率列表
- n_simulations: 模拟次数
"""
results = []
for _ in range(n_simulations):
result = self._simulate_single_shootout(
team_a_probs.copy(),
team_b_probs.copy()
)
results.append(result)
# 统计分析
df_results = pd.DataFrame(results, columns=['winner', 'rounds', 'score_a', 'score_b'])
return {
'team_a_win_prob': (df_results['winner'] == 'A').mean() * 100,
'team_b_win_prob': (df_results['winner'] == 'B').mean() * 100,
'avg_rounds': df_results['rounds'].mean(),
'avg_score_a': df_results['score_a'].mean(),
'avg_score_b': df_results['score_b'].mean(),
'score_distribution': df_results.groupby(['score_a', 'score_b']).size().reset_index(name='counts')
}
def _simulate_single_shootout(self, team_a_probs, team_b_probs):
"""模拟单次点球大战"""
score_a = 0
score_b = 0
round_num = 0
# 前5轮
for i in range(5):
round_num += 1
# A队射门
if i < len(team_a_probs) and np.random.random() < team_a_probs[i]:
score_a += 1
# B队射门
if i < len(team_b_probs) and np.random.random() < team_b_probs[i]:
score_b += 1
# 提前结束判断
remaining = 5 - round_num
if score_a > score_b + remaining:
return ['A', round_num, score_a, score_b]
if score_b > score_a + remaining:
return ['B', round_num, score_a, score_b]
# 突然死亡阶段
i = 5
while i < 10:
round_num += 1
# A队射门
if i < len(team_a_probs) and np.random.random() < team_a_probs[i]:
score_a += 1
# B队射门
if i < len(team_b_probs) and np.random.random() < team_b_probs[i]:
score_b += 1
if score_a != score_b:
return ['A' if score_a > score_b else 'B', round_num, score_a, score_b]
i += 1
# 极限情况 - 平局
return ['Draw', round_num, score_a, score_b]
def player_probability_calculator(self, player_stats, goalkeeper_quality='average'):
"""
根据球员统计数据计算进球概率
参数:
- player_stats: 球员历史数据 DataFrame
- goalkeeper_quality: 门将质量
"""
base_prob = self.base_success_rate['average']
# 考虑门将因素
gk_effect = 1 - self.goalkeeper_save_rate[goalkeeper_quality]
prob = base_prob * gk_effect
# 调节prob基于球员历史数据
if 'success_rate' in player_stats.columns:
historical_rate = player_stats['success_rate'].mean()
prob = (prob + historical_rate) / 2
# 考虑压力因素(第5个罚球手)
if 'penalty_order' in player_stats.columns and player_stats['penalty_order'].iloc[0] == 5:
prob *= 0.95 # 第五个罚球手压力大
return np.clip(prob, 0.5, 0.95)
特征工程与机器学习模型
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import joblib
class AdvancedPredictor:
def __init__(self):
self.model = None
self.feature_importance = None
def extract_features(self, match_data, team_data):
"""
提取预测特征
特征包括:
- 球员历史命中率
- 比赛重要性(决赛/半决赛)
- 球队整体表现
- 时间(第几分钟)
- 球员疲劳程度
- 球队排名差异
"""
features = {
'team_rank_diff': team_data['team_a_rank'] - team_data['team_b_rank'],
'team_form': team_data['recent_form_a'] - team_data['recent_form_b'],
'goalkeeper_save_rate_a': team_data['gk_save_rate_a'],
'goalkeeper_save_rate_b': team_data['gk_save_rate_b'],
'player_success_rate_avg_a': team_data['avg_penalty_success_a'],
'player_success_rate_avg_b': team_data['avg_penalty_success_b'],
'match_importance': match_data['competition_importance'],
'team_fatigue': team_data['fatigue_index_a'] - team_data['fatigue_index_b'],
'head_to_head_wins': team_data['h2h_wins_a'] - team_data['h2h_wins_b'],
'extra_time_minutes': match_data['extra_time_played']
}
return pd.DataFrame([features])
def prepare_training_data(self, historical_matches):
"""
准备训练数据
"""
X = []
y = []
for match in historical_matches:
features = self.extract_features(match['match_data'], match['team_data'])
X.append(features)
y.append(match['outcome']) # 1表示A队赢,0表示B队赢
return pd.concat(X), np.array(y)
def train_model(self, X, y):
"""训练随机森林模型"""
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
self.model = RandomForestClassifier(
n_estimators=200,
max_depth=10,
random_state=42
)
self.model.fit(X_train, y_train)
# 评估
accuracy = self.model.score(X_test, y_test)
# 特征重要性
self.feature_importance = pd.DataFrame({
'feature': X.columns,
'importance': self.model.feature_importances_
}).sort_values('importance', ascending=False)
print(f"模型准确率: {accuracy:.2%}")
return self.model
def predict_match(self, match_data, team_data):
"""预测单场比赛"""
if self.model is None:
raise ValueError("请先训练模型")
features = self.extract_features(match_data, team_data)
# 预测概率
prob_a_win = self.model.predict_proba(features)[0][1]
prob_b_win = 1 - prob_a_win
return {
'team_a_win_probability': prob_a_win * 100,
'team_b_win_probability': prob_b_win * 100,
'features': features
}
可视化分析
class VisualizationTools:
@staticmethod
def plot_win_probability(matrix):
"""绘制胜负概率热力图"""
plt.figure(figsize=(10, 8))
sns.heatmap(matrix, annot=True, fmt='.2f', cmap='RdYlBu_r')
plt.title('点球大战胜负概率矩阵')
plt.xlabel('Team B')
plt.ylabel('Team A')
plt.show()
@staticmethod
def plot_monte_carlo_results(results):
"""绘制蒙特卡洛模拟结果"""
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 1. 胜率饼图
axes[0,0].pie(
[results['team_a_win_prob'], results['team_b_win_prob']],
labels=['Team A', 'Team B'],
autopct='%1.1f%%',
explode=[0.05, 0]
)
axes[0,0].set_title('胜负概率分布')
# 2. 轮次分布
rounds_dist = results['score_distribution']
axes[0,1].hist(rounds_dist['rounds'] if 'rounds' in rounds_dist else [5,6,7,8,9,10],
bins=range(5,11), alpha=0.7)
axes[0,1].set_title('比赛轮次分布')
axes[0,1].set_xlabel('轮次')
axes[0,1].set_ylabel('频率')
# 3. 得分分布
axes[1,0].scatter(results['score_distribution']['score_a'],
results['score_distribution']['score_b'])
axes[1,0].set_xlabel('A队得分')
axes[1,0].set_ylabel('B队得分')
axes[1,0].set_title('比分分布')
# 4. 概率累积图
axes[1,1].plot([0, 100], [0, 100], 'k--', alpha=0.5)
axes[1,1].scatter(results['team_a_win_prob'], 100 - results['team_b_win_prob'])
axes[1,1].fill_between([0, 100], 50, 100, alpha=0.1)
axes[1,1].set_xlabel('A队预测胜率 (%)')
axes[1,1].set_ylabel('实际胜率 (%)')
axes[1,1].set_title('预测vs实际')
plt.tight_layout()
plt.show()
完整使用案例
def full_prediction_example():
# 创建预测器
predictor = PenaltyShootoutPredictor()
# 示例数据:2022世界杯决赛阿根廷vs法国
team_a_probs = [0.85, 0.75, 0.80, 0.70, 0.90] # 阿根廷前5位罚球手
team_b_probs = [0.90, 0.70, 0.85, 0.75, 0.80] # 法国前5位罚球手
# 蒙特卡洛模拟
results = predictor.monte_carlo_simulation(
team_a_probs,
team_b_probs,
n_simulations=10000
)
print("=== 蒙特卡洛模拟结果 ===")
print(f"A队胜率: {results['team_a_win_prob']:.2f}%")
print(f"B队胜率: {results['team_b_win_prob']:.2f}%")
print(f"平均轮次: {results['avg_rounds']:.2f}")
# 可视化结果
viz = VisualizationTools()
viz.plot_monte_carlo_results(results)
# 高级机器学习模型
try:
# 假设有历史数据
historical_data = [] # 需要历史比赛数据
if len(historical_data) > 0:
advanced = AdvancedPredictor()
X, y = advanced.prepare_training_data(historical_data)
model = advanced.train_model(X, y)
# 预测新比赛
match_data = {
'competition_importance': 0.9, # 决赛
'extra_time_played': 30
}
team_data = {
'team_a_rank': 3,
'team_b_rank': 4,
'recent_form_a': 0.85,
'recent_form_b': 0.80,
'gk_save_rate_a': 0.20,
'gk_save_rate_b': 0.15,
'avg_penalty_success_a': 0.78,
'avg_penalty_success_b': 0.76,
'fatigue_index_a': 0.7,
'fatigue_index_b': 0.8,
'h2h_wins_a': 3,
'h2h_wins_b': 2
}
prediction = advanced.predict_match(match_data, team_data)
print(f"\n=== 机器学习预测 ===")
print(f"A队胜率: {prediction['team_a_win_probability']:.2f}%")
print(f"B队胜率: {prediction['team_b_win_probability']:.2f}%")
except Exception as e:
print(f"机器学习模型不可用: {e}")
# 球员个体分析
print("\n=== 球员命中率分析 ===")
for i, prob in enumerate(team_a_probs):
print(f"A队第{i+1}位罚球手命中率: {prob*100:.1f}%")
if __name__ == "__main__":
full_prediction_example()
进阶优化建议
class PredictorOptimization:
@staticmethod
def add_psychological_factors():
"""加入心理因素"""
factors = {
'pressure_index': 1.0, # 压力指数
'momentum_factor': 0.9, # 势头因素
'crowd_influence': 0.95, # 观众影响
'referee_effect': 1.0, # 裁判因素
'tactical_preparation': 1.05 # 战术准备程度
}
return factors
@staticmethod
def add_environmental_factors():
"""加入环境因素"""
environmental = {
'weather': 'clear', # 天气
'pitch_quality': 'excellent', # 场地质量
'altitude': 1500, # 海拔
'temperature': 22, # 温度
'wind_speed': 3 # 风速
}
return environmental
@staticmethod
def ensemble_predictions():
"""集成多种模型预测"""
predictions = []
# 分别用不同模型预测
# 1. 贝叶斯网络
# 2. 逻辑回归
# 3. 随机森林
# 4. 神经网络
# 加权平均
weights = [0.3, 0.2, 0.3, 0.2]
ensemble_pred = np.average(predictions, weights=weights)
return ensemble_pred
这个预测系统涵盖了:
- 蒙特卡洛模拟:通过大量模拟预测胜负概率
- 机器学习模型:基于历史数据训练
- 可视化分析:直观展示预测结果
- 多因素考虑:包括球员、门将、心理、环境等多维因素
实际使用时,需要收集足够的历史数据和实时数据来训练模型,以获得更准确的预测结果。