python案例如何识别球队的战术风格类型?

wen python案例 5

本文目录导读:

python案例如何识别球队的战术风格类型?

  1. 第一步:准备数据(特征定义)
  2. 第二步:数据标准化(特征缩放)
  3. 第三步:降维(PCA)与可视化(可选)
  4. 第四步:聚类建模(识别风格)
  5. 第五步:风格标签解释(核心!)
  6. 第六步:验证与调优(真实项目必备)
  7. 完整代码整合(可直接运行)
  8. 进阶优化建议

识别球队战术风格类型是一个经典的机器学习/数据挖掘问题,核心在于特征工程,你需要把比赛中的“跑位”和“传球”转化为可量化的数据,然后通过聚类(无监督)或分类(有监督)来划分风格。

以下是一个完整的Python实战案例,从数据模拟(或说明数据格式)到模型训练,最终输出球队风格标签。


第一步:准备数据(特征定义)

战术风格通常体现为以下几个维度的统计特征:

  1. 控球率:控球时间占比。
  2. 传球数/传球成功率:短传多还是长传多。
  3. 进攻方向:向前传球比例、横传比例、回传比例。
  4. 压迫强度:前场30米区域抢断次数、高位防线(防守线高度)。
  5. 反击倾向:由守转攻时的平均传球速度(每秒推进距离)或直接长传比例。
  6. 射门区域:禁区内射门占比、远射占比。

模拟数据(假设你有历史比赛数据,以下生成示意数据):

import pandas as pd
import numpy as np
# 模拟10支球队的比赛统计数据(每行代表一支球队的一个赛季平均)
data = {
    'Team': ['曼城', '利物浦', '曼联', '马竞', '国米', '多特', '莱斯特', '布莱顿', '伯恩利', '水晶宫'],
    'Possession': [68, 55, 52, 48, 55, 60, 50, 62, 40, 44],
    'PassesPerMatch': [700, 550, 520, 380, 580, 620, 450, 650, 300, 420],
    'LongBallsRate': [0.08, 0.12, 0.15, 0.22, 0.13, 0.10, 0.18, 0.07, 0.30, 0.20],
    'HighPress': [80, 95, 70, 65, 75, 85, 60, 78, 40, 55],
    'CounterAttackGoals': [5, 10, 8, 12, 6, 7, 9, 4, 3, 6],
    'BuildUpSpeed': [8.5, 9.8, 7.0, 5.8, 6.5, 8.2, 6.1, 9.0, 4.5, 5.0],
}
df = pd.DataFrame(data)
print(df)

第二步:数据标准化(特征缩放)

不同指标量纲不同(控球率0-100,传球数300-700),必须标准化。

from sklearn.preprocessing import StandardScaler
features = df.drop('Team', axis=1)
scaler = StandardScaler()
scaled_features = scaler.fit_transform(features)
# 构建带索引的DataFrame用于后续分析
scaled_df = pd.DataFrame(scaled_features, columns=features.columns, index=df['Team'])

第三步:降维(PCA)与可视化(可选)

维度较多时进行降维,方便观察聚类结构。

from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
pca = PCA(n_components=2)
pca_result = pca.fit_transform(scaled_features)
# 可视化,颜色代表后续聚类标签(先不画)
plt.figure(figsize=(8,6))
plt.scatter(pca_result[:,0], pca_result[:,1], c='lightblue', edgecolor='black')
for i, team in enumerate(df['Team']):
    plt.annotate(team, (pca_result[i,0], pca_result[i,1]))'球队战术空间(PCA降维)')
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.grid(True)
plt.show()

第四步:聚类建模(识别风格)

使用 K-Means 聚类,把球队划分到 (k) 个风格簇中。(k) 的选择可以通过“肘部法则”确定。

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 肘部法则找k
inertia = []
for k in range(1, 7):
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    kmeans.fit(scaled_features)
    inertia.append(kmeans.inertia_)
plt.plot(range(1,7), inertia, 'o-')
plt.xlabel('K')
plt.ylabel('Inertia')'肘部法则确定K值')
plt.show()

假设你观察到拐点在 (k=3) 或 (k=4),我们选择 k=3(常见分为:控球渗透型、防反直接型、压迫冲击型)。

kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
labels = kmeans.fit_predict(scaled_features)
df['Style_Cluster'] = labels
print(df[['Team', 'Style_Cluster']])

第五步:风格标签解释(核心!)

聚类后,你需要根据簇的中心特征给每个簇起名字(如“控球型”、“反击型”、“直接型”)。

# 查看每个簇的特征均值(原始值)
cluster_means = df.groupby('Style_Cluster')[features.columns].mean()
print("各簇的平均特征值:\n", cluster_means)
# 简单规则化命名
def label_style(row):
    if row['Possession'] > 60:
        return '控球渗透型'
    elif row['HighPress'] > 75 and row['CounterAttackGoals'] > 8:
        return '高位压迫冲击型'
    else:
        return '防守反击型'
df['Style_Name'] = df.apply(lambda r: 
    '控球控制型' if r['Possession']>60 else 
    ('高位压迫型' if r['HighPress']>75 else '防守反击型'), axis=1)
print(df[['Team', 'Style_Name']])

第六步:验证与调优(真实项目必备)

  • 轮廓系数(Silhouette Score)检查聚类质量:

    from sklearn.metrics import silhouette_score
    score = silhouette_score(scaled_features, labels)
    print(f"轮廓系数: {score:.3f}(大于0.5说明聚类有效)")
  • 调参:尝试不同的聚类算法(如DBSCAN、层次聚类),或者调整特征权重(比如强调“传球推进速度”来区分“渗透”和“控球倒脚”)。


完整代码整合(可直接运行)

import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# --- 模拟数据 ---
data = {
    'Team': ['曼城','利物浦','曼联','马竞','国米','多特','莱斯特','布莱顿','伯恩利','水晶宫'],
    'Possession': [68,55,52,48,55,60,50,62,40,44],
    'PassesPerMatch': [700,550,520,380,580,620,450,650,300,420],
    'LongBallsRate': [0.08,0.12,0.15,0.22,0.13,0.10,0.18,0.07,0.30,0.20],
    'HighPress': [80,95,70,65,75,85,60,78,40,55],
    'CounterAttackGoals': [5,10,8,12,6,7,9,4,3,6],
    'BuildUpSpeed': [8.5,9.8,7.0,5.8,6.5,8.2,6.1,9.0,4.5,5.0],
}
df = pd.DataFrame(data)
# --- 标准化 ---
features = df.drop('Team', axis=1)
scaler = StandardScaler()
scaled = scaler.fit_transform(features)
# --- 聚类 ---
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
labels = kmeans.fit_predict(scaled)
df['Cluster'] = labels
# --- 风格命名(基于业务规则) ---
df['Style'] = df.apply(lambda r: 
    '控球控制型' if r['Possession']>60 else 
    ('高位压迫型' if r['HighPress']>75 else '防守反击型'), axis=1)
# --- 输出结果 ---
result = df[['Team','Style']].sort_values('Style')
print(result)
# --- 可视化(可选) ---
pca = PCA(n_components=2)
pca_result = pca.fit_transform(scaled)
plt.figure(figsize=(8,6))
scatter = plt.scatter(pca_result[:,0], pca_result[:,1], c=df['Cluster'], cmap='viridis', edgecolor='black')
for i, team in enumerate(df['Team']):
    plt.annotate(team, (pca_result[i,0], pca_result[i,1]))'球队战术风格聚类')
plt.colorbar(scatter)
plt.show()

进阶优化建议

  1. 真实数据源:使用StatsBomb、Wyscout或Kaggle上的比赛事件数据(如传球、抢断坐标),提取传球网络指标(如传球次数、传球熵)会更精准。
  2. 时序分析:如果是动态分析(一个赛季的演变),可以用滑动窗口做聚类。
  3. 深度学习:用LSTM处理球员跑位轨迹序列,输出风格向量——但需要大量标注数据,通常中小球队用统计特征就够了。

这个案例的关键在于你怎么定义“风格”——统计特征选得准,规则定得好,这个模型就能很好地帮你给球队自动打上标签。

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