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

wen python案例 3

本文目录导读:

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

  1. 基础数据模拟预测法
  2. 基于历史数据的Poisson模型
  3. 机器学习预测模型
  4. 实时决策辅助系统
  5. 可视化结果
  6. 使用建议

我来提供一个完整的点球大战预测案例,包含数据模拟和统计模型:

基础数据模拟预测法

import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
class PenaltyShootoutPredictor:
    def __init__(self, team_A_strength=0.75, team_B_strength=0.70, n_shots=5):
        """
        初始化预测器
        team_A_strength: A队射门成功率 (0-1)
        team_B_strength: B队射门成功率 (0-1)
        n_shots: 常规点球轮数 (通常5轮)
        """
        self.team_A_strength = team_A_strength
        self.team_B_strength = team_B_strength
        self.n_shots = n_shots
    def simulate_single_shootout(self):
        """模拟一次点球大战"""
        # A队先罚
        score_A = 0
        score_B = 0
        # 常规5轮
        for i in range(self.n_shots):
            # A队罚球
            if random.random() < self.team_A_strength:
                score_A += 1
            # B队罚球
            if random.random() < self.team_B_strength:
                score_B += 1
            # 提前结束判断(当一方无法追平时)
            remaining = self.n_shots - (i + 1)
            if score_A > score_B + remaining:
                return 'A', score_A, score_B
            elif score_B > score_A + remaining:
                return 'B', score_B, score_A
        # 如果5轮后平局,进入突然死亡
        if score_A == score_B:
            return self.sudden_death(score_A, score_B)
        return ('A' if score_A > score_B else 'B', 
                max(score_A, score_B), min(score_A, score_B))
    def sudden_death(self, score_A, score_B):
        """突然死亡阶段"""
        while True:
            # 双方各罚一次
            if random.random() < self.team_A_strength:
                score_A += 1
            if random.random() < self.team_B_strength:
                score_B += 1
            # 判断是否分出胜负
            if score_A != score_B:
                winner = 'A' if score_A > score_B else 'B'
                return (winner, max(score_A, score_B), min(score_A, score_B))
    def monte_carlo_simulation(self, n_simulations=10000):
        """蒙特卡洛模拟"""
        results = {'A': 0, 'B': 0}
        score_distribution = {}
        for _ in range(n_simulations):
            winner, high_score, low_score = self.simulate_single_shootout()
            results[winner] += 1
            # 记录比分分布
            score_key = f"{high_score}-{low_score}"
            score_distribution[score_key] = score_distribution.get(score_key, 0) + 1
        # 计算概率
        prob_A = results['A'] / n_simulations
        prob_B = results['B'] / n_simulations
        # 转换分数分布为概率
        for key in score_distribution:
            score_distribution[key] /= n_simulations
        return {
            'win_prob_A': prob_A,
            'win_prob_B': prob_B,
            'score_distribution': score_distribution
        }
# 使用示例
predictor = PenaltyShootoutPredictor(0.78, 0.72)
results = predictor.monte_carlo_simulation(10000)
print(f"A队胜率: {results['win_prob_A']*100:.1f}%")
print(f"B队胜率: {results['win_prob_B']*100:.1f}%")
print("常见比分概率:")
for score, prob in sorted(results['score_distribution'].items(), 
                          key=lambda x: x[1], reverse=True)[:5]:
    print(f"  {score}: {prob*100:.2f}%")

基于历史数据的Poisson模型

from scipy import stats
import numpy as np
class PoissonPenaltyModel:
    def __init__(self, team_A_goals_per_game, team_B_goals_per_game):
        """
        基于赛季进球数据的Poisson回归模型
        """
        self.lambda_A = team_A_goals_per_game
        self.lambda_B = team_B_goals_per_game
    def predict_single_round(self):
        """预测单轮点球得分"""
        # 使用Poisson分布预测每轮进球数
        score_A = np.random.poisson(self.lambda_A)
        score_B = np.random.poisson(self.lambda_B)
        return score_A, score_B
    def simulate_match(self, n_simulations=10000):
        """模拟多场比赛"""
        results = []
        for _ in range(n_simulations):
            # 模拟5轮点球
            total_A_score = 0
            total_B_score = 0
            rounds = 5
            for round_num in range(rounds):
                score_A, score_B = self.predict_single_round()
                total_A_score += score_A
                total_B_score += score_B
                # 提前结束判断
                remaining = rounds - (round_num + 1)
                if total_A_score > total_B_score + remaining:
                    results.append(('A', total_A_score, total_B_score))
                    break
                elif total_B_score > total_A_score + remaining:
                    results.append(('B', total_B_score, total_A_score))
                    break
            else:
                # 5轮结束
                if total_A_score > total_B_score:
                    results.append(('A', total_A_score, total_B_score))
                elif total_B_score > total_A_score:
                    results.append(('B', total_B_score, total_A_score))
                else:
                    # 平局,进入突然死亡
                    winner = 'A' if random.random() < 0.5 else 'B'
                    results.append((winner, total_A_score, total_B_score))
        return results
    def calculate_probabilities(self, simulations=10000):
        """计算胜负概率"""
        results = self.simulate_match(simulations)
        A_wins = sum(1 for r in results if r[0] == 'A')
        B_wins = sum(1 for r in results if r[0] == 'B')
        return {
            'A_win_prob': A_wins / len(results),
            'B_win_prob': B_wins / len(results),
            'draw_prob': 1 - (A_wins + B_wins) / len(results)
        }
# 使用示例
poisson_model = PoissonPenaltyModel(1.5, 1.2)
probabilities = poisson_model.calculate_probabilities(10000)
print(f"A队胜率: {probabilities['A_win_prob']*100:.1f}%")
print(f"B队胜率: {probabilities['B_win_prob']*100:.1f}%")

机器学习预测模型

from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
import pandas as pd
class MLShootoutPredictor:
    def __init__(self):
        self.model = GradientBoostingClassifier()
        self.scaler = StandardScaler()
        self.encoder = LabelEncoder()
    def create_training_data(self, n_samples=1000):
        """生成训练数据"""
        data = []
        for _ in range(n_samples):
            # 生成特征
            team_A_attack_rating = np.random.randint(60, 90)
            team_A_defense_rating = np.random.randint(50, 85)
            team_B_attack_rating = np.random.randint(60, 90)
            team_B_defense_rating = np.random.randint(50, 85)
            # 历史点球成功率
            team_A_penalty_pct = np.random.uniform(0.6, 0.9)
            team_B_penalty_pct = np.random.uniform(0.6, 0.9)
            # 团队士气和压力因素
            team_A_pressure = np.random.uniform(0.5, 1.0)
            team_B_pressure = np.random.uniform(0.5, 1.0)
            # 门将扑救能力
            team_A_goalkeeper_rating = np.random.randint(60, 95)
            team_B_goalkeeper_rating = np.random.randint(60, 95)
            # 计算胜率(简化的公式)
            strength_diff = ((team_A_attack_rating - team_B_defense_rating) + 
                           (team_A_penalty_pct - team_B_penalty_pct) * 100)
            win_prob = 1 / (1 + np.exp(-strength_diff/50))
            winner = 1 if random.random() < win_prob else 0
            data.append([
                team_A_attack_rating, team_A_defense_rating,
                team_B_attack_rating, team_B_defense_rating,
                team_A_penalty_pct, team_B_penalty_pct,
                team_A_pressure, team_B_pressure,
                team_A_goalkeeper_rating, team_B_goalkeeper_rating,
                winner
            ])
        return pd.DataFrame(data, columns=[
            'team_A_attack', 'team_A_defense',
            'team_B_attack', 'team_B_defense',
            'team_A_penalty_pct', 'team_B_penalty_pct',
            'team_A_pressure', 'team_B_pressure',
            'team_A_gk_rating', 'team_B_gk_rating',
            'winner'
        ])
    def train(self, X, y):
        """训练模型"""
        # 标准化特征
        X_scaled = self.scaler.fit_transform(X)
        # 划分训练集和测试集
        X_train, X_test, y_train, y_test = train_test_split(
            X_scaled, y, test_size=0.2, random_state=42
        )
        # 训练模型
        self.model.fit(X_train, y_train)
        # 评估
        train_acc = self.model.score(X_train, y_train)
        test_acc = self.model.score(X_test, y_test)
        return train_acc, test_acc
    def predict_match(self, team_data):
        """预测单场比赛"""
        # 格式: [A_attack, A_defense, B_attack, B_defense, 
        #        A_penalty_pct, B_penalty_pct, A_pressure, B_pressure, 
        #        A_gk_rating, B_gk_rating]
        X = np.array(team_data).reshape(1, -1)
        X_scaled = self.scaler.transform(X)
        # 预测
        prediction = self.model.predict(X_scaled)
        probability = self.model.predict_proba(X_scaled)
        return {
            'predicted_winner': 'A' if prediction[0] == 1 else 'B',
            'prob_A_wins': probability[0][1],
            'prob_B_wins': probability[0][0]
        }
# 使用示例
ml_predictor = MLShootoutPredictor()
# 生成训练数据
df = ml_predictor.create_training_data(1000)
X = df.drop('winner', axis=1)
y = df['winner']
# 训练模型
train_acc, test_acc = ml_predictor.train(X, y)
print(f"训练准确率: {train_acc*100:.2f}%")
print(f"测试准确率: {test_acc*100:.2f}%")
# 预测一场模拟比赛
match_data = [78, 72, 75, 70, 0.75, 0.72, 0.8, 0.7, 85, 80]
prediction = ml_predictor.predict_match(match_data)
print(f"预测赢家: {prediction['predicted_winner']}队")
print(f"A队胜率: {prediction['prob_A_wins']*100:.1f}%")

实时决策辅助系统

class RealTimeDecisionSupport:
    def __init__(self):
        self.historical_data = []
        self.model = None
    def update_with_live_data(self, shot_data):
        """实时更新数据"""
        self.historical_data.append(shot_data)
    def analyze_shooter_tendency(self, shooter_stats):
        """分析射手习惯"""
        return {
            'favorite_side': 'left' if shooter_stats['left_goals'] > shooter_stats['right_goals'] 
                            else 'right',
            'weakness': 'high' if shooter_stats['high_fail'] > shooter_stats['low_fail'] 
                       else 'low',
            'pressure_performance': 0.9 if shooter_stats['pressure_scored'] >= 0.8 else 0.6
        }
    def suggest_goalkeeper_strategy(self, opponent_shooter_stats):
        """建议门将策略"""
        analysis = self.analyze_shooter_tendency(opponent_shooter_stats)
        strategies = []
        if analysis['favorite_side'] == 'left':
            strategies.append(f"对方倾向射左路,建议门将提前预判左侧")
        else:
            strategies.append(f"对方倾向射右路,建议门将提前预判右侧")
        if analysis['weakness'] == 'high':
            strategies.append("对方在高球方面表现不佳,可尝试诱导其踢高球")
        else:
            strategies.append("对方低球处理较好,建议加强低球防守")
        if analysis['pressure_performance'] < 0.7:
            strategies.append("对方在高压下表现不稳,可以适当拖延时间增加压力")
        return strategies
# 使用示例
decision_support = RealTimeDecisionSupport()
# 模拟对手数据
opponent_stats = {
    'left_goals': 8,
    'right_goals': 5,
    'high_fail': 3,
    'low_fail': 1,
    'pressure_scored': 0.65
}
strategies = decision_support.suggest_goalkeeper_strategy(opponent_stats)
for strategy in strategies:
    print(f"• {strategy}")

可视化结果

def visualize_predictions(results):
    """可视化预测结果"""
    fig, axes = plt.subplots(1, 2, figsize=(12, 5))
    # 饼图 - 胜负概率
    axes[0].pie([results['win_prob_A'], results['win_prob_B']], 
                labels=['A队', 'B队'], 
                autopct='%1.1f%%',
                colors=['#3498db', '#e74c3c'])
    axes[0].set_title('点球大战胜率分布')
    # 柱状图 - 比分分布
    scores = list(results['score_distribution'].keys())[:5]
    probs = [results['score_distribution'][s] * 100 for s in scores]
    axes[1].bar(scores, probs, color='green')
    axes[1].set_xlabel('比分 (A-B)')
    axes[1].set_ylabel('概率 (%)')
    axes[1].set_title('最可能比分')
    axes[1].tick_params(axis='x', rotation=45)
    plt.tight_layout()
    plt.show()
# 执行可视化
visualize_predictions(results)

使用建议

  1. 数据收集:尽量收集真实的点球数据(球员罚球习惯、门将扑救数据、比赛压力等)

  2. 模型选择

    • 简单预测:使用蒙特卡洛模拟
    • 数据分析:使用Poisson回归
    • 高级预测:使用机器学习模型
  3. 动态更新:根据实时比赛情况调整参数

  4. 风险评估:考虑球员疲劳、士气、战术安排等因素

这个案例系统涵盖了从简单到复杂的预测方法,你可以根据实际需求选择使用。

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