python案例如何预测点球大战胜负走向?

wen python案例 5

本文目录导读:

python案例如何预测点球大战胜负走向?

  1. 完整实现代码
  2. 关键功能说明
  3. 使用方法

我来给你一个完整的点球大战胜负预测的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}%")

这个案例提供了完整的预测流程,从数据生成、模型训练到实际预测和可视化,你可以根据实际数据替换模拟数据使用。

抱歉,评论功能暂时关闭!