本文目录导读:

我来给你一个完整的点球大战胜负预测的Python案例,包含数据模拟、机器学习模型和可视化分析。
完整实现代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class PointShootoutPredictor:
"""点球大战预测系统"""
def __init__(self):
self.model = None
self.scaler = StandardScaler()
self.historical_data = None
def generate_training_data(self, n_samples=1000):
"""生成模拟训练数据"""
np.random.seed(42)
data = []
for _ in range(n_samples):
# 球队实力相关特征
team_a_rating = np.random.uniform(70, 95)
team_b_rating = np.random.uniform(70, 95)
# 门将能力
goalkeeper_a = np.random.uniform(60, 90)
goalkeeper_b = np.random.uniform(60, 90)
# 球员压力水平(0-1,越高压力越大)
pressure_a = np.random.uniform(0.2, 0.9)
pressure_b = np.random.uniform(0.2, 0.9)
# 历史点球命中率
historical_accuracy_a = np.random.uniform(0.65, 0.9)
historical_accuracy_b = np.random.uniform(0.65, 0.9)
# 球队状态(近期战绩)
recent_form_a = np.random.uniform(0.3, 0.9)
recent_form_b = np.random.uniform(0.3, 0.9)
# 比赛重要程度(1-10)
importance = np.random.uniform(5, 10)
# 计算真实胜率(模拟逻辑)
score_a = (team_a_rating * 0.3 + historical_accuracy_a * 40 +
goalkeeper_b * 0.3 + recent_form_a * 20)
score_b = (team_b_rating * 0.3 + historical_accuracy_b * 40 +
goalkeeper_a * 0.3 + recent_form_b * 20)
# 加入随机因素
score_a += np.random.normal(0, 5)
score_b += np.random.normal(0, 5)
# 胜负判定
winner = 1 if score_a > score_b else 0
data.append([
team_a_rating, team_b_rating, goalkeeper_a, goalkeeper_b,
pressure_a, pressure_b, historical_accuracy_a, historical_accuracy_b,
recent_form_a, recent_form_b, importance, winner
])
columns = ['team_a_rating', 'team_b_rating', 'goalkeeper_a', 'goalkeeper_b',
'pressure_a', 'pressure_b', 'historical_accuracy_a', 'historical_accuracy_b',
'recent_form_a', 'recent_form_b', 'importance', 'winner']
self.historical_data = pd.DataFrame(data, columns=columns)
return self.historical_data
def train_model(self):
"""训练预测模型"""
if self.historical_data is None:
self.generate_training_data()
# 准备特征和目标
X = self.historical_data.drop('winner', axis=1)
y = self.historical_data['winner']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 特征标准化
X_train_scaled = self.scaler.fit_transform(X_train)
X_test_scaled = self.scaler.transform(X_test)
# 训练随机森林模型
self.model = RandomForestClassifier(
n_estimators=100,
max_depth=10,
random_state=42
)
self.model.fit(X_train_scaled, y_train)
# 评估模型
y_pred = self.model.predict(X_test_scaled)
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy:.3f}")
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=['B队胜', 'A队胜']))
# 返回特征重要性
return pd.DataFrame({
'feature': X.columns,
'importance': self.model.feature_importances_
}).sort_values('importance', ascending=False)
def simulate_shootout(self, team_a_strength=0.8, team_b_strength=0.7, n_simulations=10000):
"""蒙特卡洛模拟点球大战"""
def simulate_single_shootout(team_a_prob, team_b_prob):
"""模拟单次点球大战"""
shots_a, shots_b = 0, 0 # 已射门次数
score_a, score_b = 0, 0 # 得分
# 前5轮常规射门
for round_num in range(5):
# A队射门
if np.random.random() < team_a_prob:
score_a += 1
shots_a += 1
# B队射门
if np.random.random() < team_b_prob:
score_b += 1
shots_b += 1
# 提前结束判断
if round_num == 4:
if score_a > score_b + (5 - shots_b):
return 1
elif score_b > score_a + (5 - shots_a):
return 0
# 如果5轮后平局,进入突然死亡
while score_a == score_b:
# A队射门
if np.random.random() < team_a_prob:
score_a += 1
shots_a += 1
# B队射门
if np.random.random() < team_b_prob:
score_b += 1
shots_b += 1
# 判断是否分出胜负
if score_a != score_b:
break
return 1 if score_a > score_b else 0
# 执行多次模拟
results = []
scores_history = []
for _ in range(n_simulations):
result = simulate_single_shootout(team_a_strength, team_b_strength)
results.append(result)
# 模拟可能的总比分
total_score_a = int(team_a_strength * 5 + np.random.randint(0, 3))
total_score_b = int(team_b_strength * 5 + np.random.randint(0, 3))
scores_history.append((total_score_a, total_score_b))
win_rate_a = np.mean(results)
return {
'win_rate_a': win_rate_a,
'win_rate_b': 1 - win_rate_a,
'avg_score_a': np.mean([s[0] for s in scores_history]),
'avg_score_b': np.mean([s[1] for s in scores_history]),
'total_simulations': n_simulations
}
def predict_match(self, team_a_params, team_b_params):
"""使用训练好的模型进行预测"""
if self.model is None:
self.train_model()
# 构建特征向量
features = np.array([
team_a_params['rating'], team_b_params['rating'],
team_a_params['goalkeeper'], team_b_params['goalkeeper'],
team_a_params['pressure'], team_b_params['pressure'],
team_a_params['accuracy'], team_b_params['accuracy'],
team_a_params['form'], team_b_params['form'],
team_a_params['importance']
]).reshape(1, -1)
# 标准化特征
features_scaled = self.scaler.transform(features)
# 预测
prediction = self.model.predict(features_scaled)[0]
probabilities = self.model.predict_proba(features_scaled)[0]
return {
'winner': 'A队' if prediction == 1 else 'B队',
'probability_a': probabilities[1],
'probability_b': probabilities[0]
}
def visualize_probabilities(self, results):
"""可视化预测结果"""
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 胜率饼图
labels = ['A队胜', 'B队胜']
sizes = [results['win_rate_a'] * 100, results['win_rate_b'] * 100]
colors = ['#ff9999', '#66b3ff']
explode = (0.1, 0) # 突出显示A队
axes[0].pie(sizes, explode=explode, labels=labels, colors=colors,
autopct='%1.1f%%', shadow=True, startangle=90)
axes[0].set_title('点球大战胜率预测')
# 比分分布图(模拟)
scores = []
for _ in range(1000):
score_a = int(results['avg_score_a'] + np.random.normal(0, 1))
score_b = int(results['avg_score_b'] + np.random.normal(0, 1))
scores.append((max(0, score_a), max(0, score_b)))
score_df = pd.DataFrame(scores, columns=['A队得分', 'B队得分'])
axes[1].hist(score_df['A队得分'], alpha=0.5, label='A队', bins=10, color='red')
axes[1].hist(score_df['B队得分'], alpha=0.5, label='B队', bins=10, color='blue')
axes[1].set_xlabel('得分')
axes[1].set_ylabel('频次')
axes[1].set_title('模拟比分分布')
axes[1].legend()
plt.tight_layout()
plt.show()
def analyze_scenarios(self):
"""分析不同场景下的胜率变化"""
scenarios = []
# 不同实力差距场景
strength_diffs = [-0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3]
for diff in strength_diffs:
basic_strength = 0.7
team_a = basic_strength + diff
team_b = basic_strength
result = self.simulate_shootout(team_a, team_b, n_simulations=5000)
scenarios.append({
'实力差': f'{diff:+.1f}',
'A队胜率': result['win_rate_a'],
'B队胜率': result['win_rate_b']
})
scenario_df = pd.DataFrame(scenarios)
# 可视化
plt.figure(figsize=(10, 6))
plt.plot(scenario_df['实力差'], scenario_df['A队胜率'], 'ro-', label='A队胜率')
plt.plot(scenario_df['实力差'], scenario_df['B队胜率'], 'bo-', label='B队胜率')
plt.axhline(y=0.5, color='gray', linestyle='--', label='50%线')
plt.xlabel('实力差')
plt.ylabel('胜率')
plt.title('实力差距对胜率的影响')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
return scenario_df
# 使用示例
if __name__ == "__main__":
# 创建预测器实例
predictor = PointShootoutPredictor()
# 1. 生成训练数据并训练模型
print("=== 训练预测模型 ===")
data = predictor.generate_training_data(1500)
feature_importance = predictor.train_model()
print("\n特征重要性排名:")
print(feature_importance.head(5))
# 2. 蒙特卡洛模拟
print("\n=== 蒙特卡洛模拟点球大战 ===")
simulation_result = predictor.simulate_shootout(
team_a_strength=0.75, # A队点球命中率75%
team_b_strength=0.68, # B队点球命中率68%
n_simulations=10000
)
print(f"模拟次数: {simulation_result['total_simulations']}")
print(f"A队胜率: {simulation_result['win_rate_a']*100:.2f}%")
print(f"B队胜率: {simulation_result['win_rate_b']*100:.2f}%")
print(f"A队平均得分: {simulation_result['avg_score_a']:.2f}")
print(f"B队平均得分: {simulation_result['avg_score_b']:.2f}")
# 3. 可视化胜率预测
predictor.visualize_probabilities(simulation_result)
# 4. 使用ML模型预测具体比赛
print("\n=== 模型预测具体比赛 ===")
team_a_parameters = {
'rating': 88, # 球队实力评级
'goalkeeper': 82, # 门将能力
'pressure': 0.6, # 压力水平
'accuracy': 0.85, # 点球命中率
'form': 0.7, # 近期状态
'importance': 8 # 比赛重要程度
}
team_b_parameters = {
'rating': 85,
'goalkeeper': 78,
'pressure': 0.7,
'accuracy': 0.78,
'form': 0.6,
'importance': 8
}
prediction = predictor.predict_match(team_a_parameters, team_b_parameters)
print(f"预测获胜球队: {prediction['winner']}")
print(f"A队胜率: {prediction['probability_a']*100:.2f}%")
print(f"B队胜率: {prediction['probability_b']*100:.2f}%")
# 5. 场景分析
print("\n=== 场景分析 ===")
scenario_df = predictor.analyze_scenarios()
print(scenario_df)
# 6. 实时监控功能(模拟)
print("\n=== 实时动态预测 ===")
print("假设比赛进行到第3轮,比分2:1,A队领先")
# 更新概率(留出余量给剩下2轮及可能的突然死亡)
remaining_score_a = np.random.binomial(2, 0.75) # 剩余2轮A队可能得分
remaining_score_b = np.random.binomial(2, 0.68) # 剩余2轮B队可能得分
print(f"A队剩余轮次预计得分: {remaining_score_a}")
print(f"B队剩余轮次预计得分: {remaining_score_b}")
# 计算最终预计比分
final_score_a = 2 + remaining_score_a
final_score_b = 1 + remaining_score_b
print(f"预测最终比分: {final_score_a} : {final_score_b}")
print(f"A队获胜概率: {max(0.5, 1 - final_score_b/max(final_score_a, 0.01)):.2f}")
关键功能说明
特征工程
- 球队实力评级
- 门将扑救能力
- 球员压力水平
- 历史点球命中率
- 近期状态
- 比赛重要程度
模型算法
- 随机森林: 用于预测胜负
- 蒙特卡洛模拟: 10,000次模拟出胜率
- 梯度提升: 可扩展选项
可视化功能
- 胜率饼图
- 比分分布直方图
- 实力差距影响曲线
预测输出
- 双方胜率百分比
- 预计比分
- 特征重要性排名
- 实时动态更新
使用方法
# 快速开始
predictor = PointShootoutPredictor()
result = predictor.simulate_shootout(0.75, 0.68)
print(f"A队胜率: {result['win_rate_a']*100:.1f}%")
这个案例提供了完整的预测流程,从数据生成、模型训练到实际预测和可视化,你可以根据实际数据替换模拟数据使用。