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

wen python案例 5

本文目录导读:

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

  1. 基础概率模型
  2. 特征工程与机器学习模型
  3. 可视化分析
  4. 完整使用案例
  5. 进阶优化建议

我来提供一个预测点球大战胜负走向的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

这个预测系统涵盖了:

  1. 蒙特卡洛模拟:通过大量模拟预测胜负概率
  2. 机器学习模型:基于历史数据训练
  3. 可视化分析:直观展示预测结果
  4. 多因素考虑:包括球员、门将、心理、环境等多维因素

实际使用时,需要收集足够的历史数据和实时数据来训练模型,以获得更准确的预测结果。

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