本文目录导读:

我来分享一个预测点球大战胜负的Python案例,包含数据模拟和机器学习两种方法:
蒙特卡洛模拟法
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 设置随机种子
np.random.seed(42)
class PenaltyShootoutSimulator:
"""点球大战模拟器"""
def __init__(self, team1_strength, team2_strength):
"""
team1_strength: 队伍1门将扑救能力(0-1)
team2_strength: 队伍2门将扑救能力(0-1)
"""
self.team1_save_prob = team1_strength # 队伍1门将扑救概率
self.team2_save_prob = team2_strength # 队伍2门将扑救概率
# 球员射门成功率(基于历史数据)
self.average_shot_accuracy = 0.75 # 平均射门成功率
self.team1_shot_accuracy = 0.78 # 队伍1射门成功率
self.team2_shot_accuracy = 0.72 # 队伍2射门成功率
def simulate_penalty(self, shooter_accuracy, goalkeeper_save_prob):
"""
模拟单个点球
返回: 1=进球, 0=未进
"""
# 考虑门将和射手能力
success_prob = shooter_accuracy * (1 - goalkeeper_save_prob)
return 1 if np.random.random() < success_prob else 0
def simulate_shootout(self):
"""
模拟整场点球大战
标准规则: 前5轮,如果平局则进入突然死亡
"""
# 前5轮
team1_goals = 0
team2_goals = 0
max_rounds = 5
for round_num in range(max_rounds):
# 队伍1射门
team1_score = self.simulate_penalty(
self.team1_shot_accuracy,
self.team2_save_prob
)
# 队伍2射门
team2_score = self.simulate_penalty(
self.team2_shot_accuracy,
self.team1_save_prob
)
team1_goals += team1_score
team2_goals += team2_score
# 提前结束判断
remaining = max_rounds - (round_num + 1)
if team1_goals > team2_goals + remaining:
return 'Team1', team1_goals, team2_goals
elif team2_goals > team1_goals + remaining:
return 'Team2', team1_goals, team2_goals
# 平局进入突然死亡
round_num = 5
while True:
# 队伍1射门
team1_score = self.simulate_penalty(
self.team1_shot_accuracy,
self.team2_save_prob
)
# 队伍2射门
team2_score = self.simulate_penalty(
self.team2_shot_accuracy,
self.team1_save_prob
)
team1_goals += team1_score
team2_goals += team2_score
round_num += 1
# 突然死亡判断
if round_num > 5 and team1_goals != team2_goals:
break
# 防止死循环
if round_num > 20:
# 极小概率下的保护措施
return 'Draw', team1_goals, team2_goals
winner = 'Team1' if team1_goals > team2_goals else 'Team2'
return winner, team1_goals, team2_goals
def run_simulation(self, n_simulations=10000):
"""
运行多次模拟
"""
results = []
for _ in range(n_simulations):
result = self.simulate_shootout()
results.append(result)
return pd.DataFrame(results, columns=['winner', 'team1_goals', 'team2_goals'])
# 使用示例
simulator = PenaltyShootoutSimulator(
team1_strength=0.3, # 队伍1门将扑救率30%
team2_strength=0.2 # 队伍2门将扑救率20%
)
# 运行10000次模拟
simulation_results = simulator.run_simulation(10000)
# 统计结果
print("=== 点球大战模拟结果 ===")
print(f"队伍1胜率: {simulation_results['winner'].value_counts().get('Team1', 0) / len(simulation_results) * 100:.1f}%")
print(f"队伍2胜率: {simulation_results['winner'].value_counts().get('Team2', 0) / len(simulation_results) * 100:.1f}%")
# 进球数分布
print("\n=== 进球数分布 ===")
print(f"队伍1平均进球: {simulation_results['team1_goals'].mean():.2f}")
print(f"队伍2平均进球: {simulation_results['team2_goals'].mean():.2f}")
# 可视化
plt.figure(figsize=(12, 5))
# 胜率饼图
plt.subplot(1, 2, 1)
winner_counts = simulation_results['winner'].value_counts()
plt.pie(winner_counts.values, labels=winner_counts.index, autopct='%1.1f%%')'点球大战胜率分布')
# 进球数分布
plt.subplot(1, 2, 2)
plt.hist(simulation_results['team1_goals'], alpha=0.7, label='Team 1', bins=10)
plt.hist(simulation_results['team2_goals'], alpha=0.7, label='Team 2', bins=10)
plt.xlabel('进球数')
plt.ylabel('频率')'进球数分布')
plt.legend()
plt.tight_layout()
plt.show()
机器学习预测法
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
class PenaltyMLPredictor:
"""基于机器学习的点球预测"""
def __init__(self):
self.model = RandomForestClassifier(n_estimators=100, random_state=42)
def prepare_training_data(self, n_samples=10000):
"""
生成训练数据
"""
data = []
for _ in range(n_samples):
# 特征向量
features = {
'team1_strength': np.random.uniform(0.5, 0.9), # 队伍1攻击力
'team2_strength': np.random.uniform(0.5, 0.9), # 队伍2攻击力
'team1_defense': np.random.uniform(0.1, 0.5), # 队伍1门将能力
'team2_defense': np.random.uniform(0.1, 0.5), # 队伍2门将能力
'form': np.random.uniform(0, 1), # 状态因素
'pressure': np.random.uniform(0, 1), # 压力因素
'fatigue': np.random.uniform(0, 1), # 疲劳因素
'historical_ratio': np.random.uniform(0, 1) # 历史胜率
}
# 计算胜率(简化的逻辑模型)
win_probability = (
0.3 * features['team1_strength'] -
0.2 * features['team2_defense'] +
0.2 * features['form'] +
0.1 * features['historical_ratio'] +
0.1 * (1 - features['pressure']) +
0.1 * (1 - features['fatigue'])
)
# 转换为胜或负
winner = 1 if win_probability > 0.5 else 0
data.append((list(features.values()), winner))
# 转换为DataFrame
X = pd.DataFrame([d[0] for d in data],
columns=['team1_strength', 'team2_strength',
'team1_defense', 'team2_defense',
'form', 'pressure', 'fatigue',
'historical_ratio'])
y = [d[1] for d in data]
return X, y
def train_model(self, X_train, y_train):
"""训练模型"""
self.model.fit(X_train, y_train)
return self
def predict_match(self, match_features):
"""
预测单个比赛
match_features: 字典包含所有特征
"""
feature_names = ['team1_strength', 'team2_strength',
'team1_defense', 'team2_defense',
'form', 'pressure', 'fatigue', 'historical_ratio']
# 确保特征顺序正确
X_pred = pd.DataFrame([match_features], columns=feature_names)
# 预测概率
win_probability = self.model.predict_proba(X_pred)[0][1]
# 预测结果
prediction = self.model.predict(X_pred)[0]
return {
'win_probability': win_probability,
'winner': 'Team1' if prediction == 1 else 'Team2',
'confidence': max(win_probability, 1 - win_probability)
}
# 查看解释代码
import textwrap
print("="*50)
print("点球预测模型Python实现")
print("="*50)
实战预测示例
# 创建简单预测函数
def simple_penalty_prediction(team1_stats, team2_stats):
"""
简化的点球预测
team1_stats: (攻击力, 门将能力)
team2_stats: (攻击力, 门将能力)
"""
atk1, gk1 = team1_stats
atk2, gk2 = team2_stats
# 综合分析
team1_advantage = (atk1 * 0.5 - gk2 * 0.3) * 0.6
team2_advantage = (atk2 * 0.5 - gk1 * 0.3) * 0.6
# 胜率计算
total_advantage = 0.5 + (team1_advantage - team2_advantage)
total_advantage = max(0, min(1, total_advantage)) # 限制在0-1之间
print(f"队伍1胜率预测: {total_advantage*100:.1f}%")
print(f"队伍2胜率预测: {(1-total_advantage)*100:.1f}%")
if total_advantage > 0.6:
return "Team1 较有优势"
elif total_advantage < 0.4:
return "Team2 较有优势"
else:
return "双方势均力敌"
# 实战示例
print("示例:巴西(攻击力0.85, 门将能力0.35) vs 德国(攻击力0.82, 门将能力0.40)")
result = simple_penalty_prediction((0.85, 0.35), (0.82, 0.40))
print(f"预测结果: {result}")
高级特征工程版
import numpy as np
def advanced_penalty_predictor(data_dict):
"""
使用更多特征的高级预测器
data_dict包含:
- home_advantage: 主场优势 (0~1)
- experience: 大赛经验 (0~1)
- tiredness: 疲劳程度 (0~1)
- match_importance: 比赛重要性 (0~1)
"""
# 基础胜率
base_rate = 0.5
# 权重调整
adjustments = {
'home_advantage': 0.1, # 主场优势
'experience': 0.15, # 经验
'tiredness': -0.1, # 疲劳
'match_importance': 0.05 # 重要性
}
# 调整胜率
adjusted_rate = base_rate
for key, weight in adjustments.items():
if key in data_dict:
value = data_dict[key] * weight
# 根据队伍1还是队伍2调整
if key in ['home_advantage', 'experience']:
adjusted_rate += value
else:
adjusted_rate -= value
# 限制在0.05-0.95之间
adjusted_rate = max(0.05, min(0.95, adjusted_rate))
return {
'team1_win_prob': adjusted_rate,
'team2_win_prob': 1 - adjusted_rate,
'prediction': 'Team1' if adjusted_rate > 0.5 else 'Team2',
'confidence': abs(adjusted_rate - 0.5) * 2
}
# 使用示例
match_data = {
'home_advantage': 0.7, # 主队有优势
'experience': 0.8, # 主队经验丰富
'tiredness': 0.3, # 客队更疲劳
'match_importance': 0.9 # 重要比赛
}
result = advanced_penalty_predictor(match_data)
print(f"预测结果: {result}")
关键发现和建议
-
核心因素:
- 门将扑救率
- 球员射门成功率
- 心理状态和压力管理
- 身体疲劳度
-
统计分析:
- 点球进球的平均成功率约75-78%
- 前5轮进球数通常在2-4个
- 第五轮是情绪压力最大的
-
实战建议:
- 利用历史数据进行贝叶斯更新
- 考虑实时数据(球员最近状态)
- 融合多家博彩公司的赔率数据
这个案例展示了从基础模拟到机器学习的完整预测链条,你可以根据实际需求调整参数和使用不同的方法。