根据php项目,客队客场表现如何评估?

wen PHP项目 3

PHP项目中客队客场表现的评估方法

在PHP体育数据项目中评估客队客场表现,通常需要从数据采集、指标计算、权重建模三个层面入手,下面给出一个完整的实现思路和代码示例。

根据php项目,客队客场表现如何评估?


核心评估指标

维度 指标 说明
进攻 客场场均进球 客场比赛进球数 / 客场场次
进攻 客场射正率、控球率 反映进攻效率
防守 客场场均失球 客场比赛失球数 / 客场场次
防守 客场零封率 零封场次 / 客场场次
结果 客场胜率、平率、负率 直接反映拿分能力
稳定性 客场积分率 客场积分 / (3×客场场次)
对手强度 对手平均排名 需做加权修正
近期状态 近5个客场走势 时间衰减加权

数据库设计(MySQL)

-- 比赛表
CREATE TABLE matches (
    id INT PRIMARY KEY AUTO_INCREMENT,
    home_team_id INT NOT NULL,
    away_team_id INT NOT NULL,
    home_goals TINYINT,
    away_goals TINYINT,
    match_date DATE,
    league_id INT,
    status TINYINT DEFAULT 1  -- 1已结束
);
-- 球队表
CREATE TABLE teams (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    league_id INT
);

PHP 评估类实现

<?php
class AwayPerformanceEvaluator
{
    private PDO $pdo;
    // 指标权重(可按联赛调参)
    private array $weights = [
        'points_rate'   => 0.30,  // 客场积分率
        'goal_diff'     => 0.25,  // 场均净胜球
        'attack'        => 0.15,  // 场均进球
        'defense'       => 0.15,  // 场均失球(反向)
        'recent_form'   => 0.15,  // 近期状态
    ];
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
    /**
     * 评估某队客场表现
     * @param int $teamId 球队ID
     * @param int $limit  考察最近N场(0=全部)
     * @return array
     */
    public function evaluate(int $teamId, int $limit = 10): array
    {
        $sql = "SELECT m.*, 
                       ht.name AS home_name, 
                       at.name AS away_name
                FROM matches m
                JOIN teams ht ON ht.id = m.home_team_id
                JOIN teams at ON at.id = m.away_team_id
                WHERE m.away_team_id = :tid
                  AND m.status = 1
                ORDER BY m.match_date DESC";
        if ($limit > 0) {
            $sql .= " LIMIT " . (int)$limit;
        }
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':tid' => $teamId]);
        $matches = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (empty($matches)) {
            return ['error' => '无客场数据'];
        }
        $n = count($matches);
        $wins = $draws = $losses = 0;
        $goalsFor = $goalsAgainst = 0;
        $cleanSheets = 0;
        $weightedPoints = 0.0;
        $weightSum = 0.0;
        foreach ($matches as $i => $m) {
            $gf = (int)$m['away_goals'];
            $ga = (int)$m['home_goals'];
            $goalsFor     += $gf;
            $goalsAgainst += $ga;
            if ($ga === 0) $cleanSheets++;
            if ($gf > $ga)      { $wins++;   $pts = 3; }
            elseif ($gf === $ga){ $draws++;  $pts = 1; }
            else                { $losses++; $pts = 0; }
            // 时间衰减:越近权重越大(最新场权重=1)
            $decay = exp(-0.15 * $i);
            $weightedPoints += $pts * $decay;
            $weightSum      += $decay;
        }
        // 基础指标
        $pointsRate   = ($wins * 3 + $draws) / (3 * $n);       // 0~1
        $avgGF        = $goalsFor / $n;
        $avgGA        = $goalsAgainst / $n;
        $avgGD        = $avgGF - $avgGA;
        $cleanRate    = $cleanSheets / $n;
        $recentForm   = $weightSum > 0 ? ($weightedPoints / (3 * $weightSum)) : 0;
        // 归一化到 0~100
        $scoreAttack  = $this->normalize($avgGF, 0, 3);
        $scoreDefense = $this->normalize(3 - $avgGA, 0, 3);   // 失球越少分越高
        $scoreGD      = $this->normalize($avgGD + 3, 0, 6);   // 平移避免负值
        $scorePoints  = $pointsRate * 100;
        $scoreRecent  = $recentForm * 100;
        // 加权总分
        $total = $scorePoints   * $this->weights['points_rate']
               + $scoreGD       * $this->weights['goal_diff']
               + $scoreAttack   * $this->weights['attack']
               + $scoreDefense  * $this->weights['defense']
               + $scoreRecent   * $this->weights['recent_form'];
        return [
            'team_id'         => $teamId,
            'samples'         => $n,
            'record'          => ['w' => $wins, 'd' => $draws, 'l' => $losses],
            'avg_goals_for'   => round($avgGF, 2),
            'avg_goals_against'=> round($avgGA, 2),
            'avg_goal_diff'   => round($avgGD, 2),
            'clean_sheet_rate'=> round($cleanRate, 2),
            'points_rate'     => round($pointsRate, 2),
            'recent_form'     => round($recentForm, 2),
            'total_score'     => round($total, 2),   // 0~100,越高客场越强
            'level'           => $this->level($total),
        ];
    }
    private function normalize(float $v, float $min, float $max): float
    {
        if ($max <= $min) return 0;
        $v = max($min, min($max, $v));
        return ($v - $min) / ($max - $min) * 100;
    }
    private function level(float $score): string
    {
        return match(true) {
            $score >= 80 => '客场极强',
            $score >= 65 => '客场较强',
            $score >= 50 => '客场中庸',
            $score >= 35 => '客场偏弱',
            default      => '客场很弱',
        };
    }
}

使用示例

$pdo = new PDO('mysql:host=localhost;dbname=football;charset=utf8mb4', 'user', 'pass');
$evaluator = new AwayPerformanceEvaluator($pdo);
$result = $evaluator->evaluate(teamId: 12, limit: 10);
print_r($result);

输出示例:

Array (
    [samples] => 10
    [record] => [w=>3, d=>3, l=>4]
    [avg_goals_for] => 1.10
    [avg_goals_against] => 1.30
    [avg_goal_diff] => -0.20
    [clean_sheet_rate] => 0.20
    [points_rate] => 0.40
    [recent_form] => 0.45
    [total_score] => 47.6
    [level] => 客场中庸
)

进阶优化建议

  1. 对手强度修正(Elo/SPI):用对手平均 Elo 分修正进球、积分,避免虐菜刷分。
    $adjust = $opponentElo / 1500;  // 简单系数
  2. 主客场分离模型:Poisson 模型分别估计主队进球率 λ_home 和客队进球率 λ_away,比简单统计更精确。
  3. 时间衰减:本示例已用指数衰减 exp(-0.15*i),可调参数。
  4. 缺失值处理:客场样本少(<5 场)时,应用联赛平均值做贝叶斯平滑:
    $smoothedGF = ($goalsFor + 5 * $leagueAvgGF) / ($n + 5);
  5. 缓存:评估结果写 Redis,键为 away:eval:{teamId},TTL 1 小时。

评估结果应用场景

  • 赛前预测:作为 Poisson / 逻辑回归模型的输入特征
  • 盘口参考:与主队主场评分对比,估算让球盘
  • 数据看板:前端展示球队客场雷达图(进攻/防守/稳定性/对手强度)

需要我进一步给出 Poisson 模型预测比分 或 对手强度加权版本 的 PHP 代码吗?

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