亚马逊AWS官方博客

谁才是一级方程式赛车中的最强车手?

Original Link: https://aws.amazon.com/cn/blogs/machine-learning/the-fastest-driver-in-formula-1/

本篇博文为合著文章,联合作者包括一级方程式赛车数据系统总监Rob Smedley

一级方程式(简称F1)赛车无疑是世界上最为复杂精妙的运动。人与机器的完美融合,成为在赛道上夺取优胜的关键。正是这种人机交互,使得F1赛车、特别是F1驾驶员们的天赋与才华往往很难被普通观众所理解。如果没有贝纳通以及后来的法拉利车队背后才华横溢的集体技术储备所推动,迈克尔·舒马赫还能拿下这么多比赛、夺得那么多冠军吗?如果刘易斯·汉密尔顿的职业生涯有所变化,只能驾驶处于中下游水准的赛车,他还能赢得六届世界冠军吗?也许这些例子不够恰当,但二位确实是有史以来最出色的两位F1车手。与此同时,也有不少同样拥有超一流才华的车手因为种种原因而未能被大家所熟知。他们也许只是没能“在正确的时间出现在正确的地点”,因此永远无法站上F1的最高领奖台。

由AWS支持的最新F1 Insight,专门用于构建数学模型与算法,旨在帮助我们回答一个长久以来难以破解的谜团:谁才是有史以来最强车手?F1与AWS科学家们投入近一年时间构建模型和算法,希望为这个难题找到深刻且清晰的答案。模型给出的答案,只关注众多F1驾驶员身上的一项素质,即周六下午排位赛中的最快圈速。换言之,模型并不关注赛车本身,也不关注谁能在赛道上开出每小时200英里的最高极速、同时游刃有余地应对赛道上的突发情况(迈克尔·舒马赫与费尔南多·阿隆索等车手都在这方面展示出强大的实力)。而这种仅看排位赛圈速的判断思路,已经足以让舒马赫与汉密尔顿在一众对手中脱颖而出。虽然我曾有幸在维修区观看过这些选手的比赛,但必须承认,我没有能力判断每一种具体驾驶技巧的重要性。或者说,正是这些技能的总和,决定了优秀车手与伟大车手间的差距。因此,模型并没有迷失在这些技能当中,而单纯只强调圈速、以及车手极限压榨赛车性能的能力。

最终得出的有史以来最快车手名单(基于1983年至今整个F1历史数据库提供的信息)也确实让人眼前一亮,其中一部分车手牢牢把持着领先排名。包括艾尔顿·塞纳,迈克尔·舒马赫以及刘易斯·汉密尔顿,他们始终位列榜单前五名。但也有些名字实在有些陌生,大家甚至很难相信这是F1历史上能够杀进前二十的顶尖车手,例如海基·科瓦莱宁。有些朋友可能会问,是那位在科特勒姆大奖赛的赛道后结束自己职业生涯的那位科瓦莱宁吗?没错,就是他。只有一直关注F1赛事的朋友们,才清楚他在单圈速度方面绝对有实力拿到这么高的排名。事实上,他曾在迈凯轮车队与刘易斯·汉密尔顿有过一段激烈燃烧的对决时光。在当时的排位赛中,二人的单圈成绩只相差0.1秒。如果问科瓦莱宁本他,他会告诉你他在正式比赛中的表现在很多方面都不及汉密尔顿。但单从排位赛的角度出发,他的统计数据强得可怕——而如此优秀的成绩,源自他在整个职业生涯中保持着高度统一的排位赛表现。我个人很高兴看到科瓦莱宁在数据分析中得到的认可,他在排位赛中表现出的才华绝对配得上这样出色的排名。希望您所热爱的车手也出现在这份名单当中,希望您曾在过去十年、二十年甚至四十年中为其加油鼓劲的车手,可以凭借个人数据在榜单上占得一席之地。无论他们是否名满天下,这一次,我们只用数据说话。

— Rob Smedley

Fastest Driver

作为F1赛事成立七十周年庆典的重要一环,也为了帮助车迷们更好地了解谁才是这项运动在发展过程中的最强车手,F1与Amazon机器学习实验室合作开发出Fastest Driver——由AWS服务支持的最新F1 Insight项目。

Fastest Driver使用AWS机器学习(ML)技术,通过F1历史数据库中自1983年以来的排位赛圈速记录对车手进行排名。在本文中,我们将演示如何使用全托管Amazon SageMaker服务实现机器学习模型的构建、训练与部署。在模型部署完成之后,Fastest Driver洞见即可客观确定F1赛事历史上最强最快的车手。

使用认证数据量化车手表现

我们将速度定义为排位赛中各位车手的单圈用时。车手们的赛场表现受到诸多因素的影响,包括天气条件、汽车配置(例如所用轮胎)以及赛道环境等。F1排位赛共分为三节:第一节淘汰掉单圈用时位列第16位或更低的车手,第二节淘汰第11至第15位,第三位则确定正式比赛中从第1位至第10位车手的发车顺序。我们使用由F1官方提供的认证数据分析各位车手的实际水平。

通过将排位赛中的单圈用时进行归一化,我们得以消除不同赛道之间的差异,跨越多场比赛对单圈时间进行全面汇总。这种标准化过程得以均衡不同车手之间的用时差异,更准确地比较不同赛道上各位车手的实际表现,同时也消除了针对特定赛道构建模型以解决完赛时长的客观区别。除此之外,我们还引入另一项重要技术,即比较同一车队(例如阿斯顿·马丁红牛车队)内部的车手在排位赛中的数据,观察各位队友在至少五轮排位赛中的竞争结果。以车队为基础,我们得以在相同的比赛条件下直接进行车手能力比较,同时将赛车本身造成的影响控制在最低水平。

当然,比赛条件(例如湿滑路况)以及规则变更都有可能给车手的成绩造成重大影响。为此,我们将同一车队各位队员之间的中位单圈用时偏差(阈值设定为2秒)以识别并消除异常单圈时间离群值。例如,我们可以比较丹尼尔·里卡多与塞巴斯蒂安·维特尔在2014年参加红牛F1挑战赛时的表现。在该赛季内,里卡多单圈平均比维物尔快0.2秒。但如果排除到2014年美国大奖赛期间的成绩,则里卡多与维特尔的平均单圈用时差距将缩小至0.1秒。为什么会这样?因为在该分站赛中,维特尔因107%规则处罚而被迫从维修区开始比赛,导致里卡尔的单圈用时比维特尔领先超过2秒。

构建Fastest Driver模型

要构建良好的机器学习模型,首先需要准备高质量数据。通过对车手们的认证数据进行汇总,我们构建起一套跨越多年赛程的队友比较网络,旨在比较各支车队、各个赛季以及各场分站赛中的车手成绩。例如,塞巴斯蒂安·维特尔与马克斯·维斯塔彭从未效力于同一车队,因此我们将二者与红牛车队的丹尼尔·里卡多进行比较,借此区分他们的驾驶水平。在2016至2018赛季,里卡多在红牛车队的平均圈速比维斯塔彭慢 0.18秒。在删除了2018年巴林分站赛(这场比赛中,里卡多的圈速远好于维斯塔彭,但这是因为维斯塔彭发生撞车而未能正确完赛)等离群成绩值后,我们假设每场排位赛的权重值相等,那么在只考虑里卡多、维特尔以及维斯塔彭的情况下,维斯塔彭将当选为最强车手:维斯塔鼓比里卡多单圈快0.18秒,里卡多又比维特尔快0.1秒。

使用全车手网络之后,我们可以开始比较所有F1车手的赛事成绩,真正踏上最强车手的探索之旅。回到海基·科瓦莱宁,我们看看他在迈凯轮车队时与刘易斯·汉密尔顿在比赛中的表现。按排位赛中的单速成绩中位数来比较,二者的差距仅为0.1秒。虽然科瓦莱宁在世界锦标赛上的成绩无法与汉密尔顿相比肩,但其排位统计数据已经很能说明问题。凭借着整个职业生涯中稳定扎实的排位赛表现,他在模型的统计结果中高居榜首。

Insight背后的核心模型之一,使用的正是Massey方法(一种线性回归形式的方法)。使用Massey方法,Fastest Driver通过求解一组线性方程式对各位车手进行排名,其中每位车手的得分根据他们与队友间的平均圈速差计算得出。另外,在比较队友间的得分时,我们的模型还使用车手日程安排强度等特征,希望尽可能实现车手赛场表现的标准化。总体而言,这套模型认为在对阵同队车手或者高水平对手时拥有良好排位赛圈速的车手,其技术实力更强。

我们的目标是为每位车手划定一项数字得分,借此推断该车手相对于其他F1车手的比较优势。当然,前提是在任何一场比赛中,单圈用时差的预期裕度与车手的真实固有得分差值成正比。可能有些读者朋友对数学比较感兴趣,那这里再多解释几句:方程式中的xi代表所有车手,r代表真实固有车手得分。在每场比赛当中,我们可以预测两位车手之间的任意单圈时间优势或劣势(yi)的裕度为:

在此等式中,xi将为胜者+1,为负者-1;而ei则为由无法解释的变化而引起的误差项。对于给定的m场比赛观察值与n位车手,我们可以整理出如下(m * n)线性议程:

车手得分(r)则为通过线性回归对这一正态方程的解:

以下为Massey方法的示例代码,其使用Amazon SageMaker进行车手排名计算并演示出完整的训练过程:

  1. 1.	import numpy as np
    2.	import pandas as pd
    3.	import statsmodels.api as sm
    4.	from scipy.stats import norm 
    5.	
    6.	#example data comparing five drivers
    7.	data = pd.DataFrame([[1, 0, 88, 90], 
    8.	                     [2, 1, 87, 88],
    9.	                     [2, 0, 87, 90],
    10.	                     [3, 4, 88, 92],
    11.	                     [3, 1, 88, 90],
    12.	                     [1, 4, 90, 92]], columns=['Driver1', 'Driver2', 'Driver1_laptime', 'Driver2_laptime'])
    13.	
    14.	def init_linear_regressor_matrix(data, num_of_drivers, col_to_rank):
    15.	    """initialize linear system matrix for regression"""
    16.	    wins = np.zeros((data.shape[0], num_of_drivers))
    17.	    score_diff = np.zeros(data.shape[0])
    18.	
    19.	    for index, row in data.iterrows():
    20.	        idx1 = row["Driver1"]
    21.	        idx2 = row["Driver2"]
    22.	        if row['Driver1_laptime'] - row['Driver2_laptime'] > 0:
    23.	            wins[(index)][(idx1)] = -1
    24.	            wins[(index)][(idx2)] = 1
    25.	            score_diff[(index)] = row['Driver1_laptime'] - row['Driver2_laptime']
    26.	        else:
    27.	            wins[(index)][(idx1)] = 1
    28.	            wins[(index)][(idx2)] = -1
    29.	            score_diff[(index)] = row['Driver2_laptime'] - row['Driver1_laptime']
    30.	    wins_df = pd.DataFrame(wins)
    31.	    wins_df[col_to_rank] = score_diff
    32.	    return wins_df 	
    33.	
    34.	def massey(data, num_of_drivers, col_to_rank='delta'):
    35.	    """Compute for each driver, adjacency matrix and aggregated scores, as input to the Massey Model"""
    36.	
    37.	    wins_df = init_linear_regressor_matrix(data, num_of_drivers, col_to_rank)
    38.	    model = sm.OLS(
    39.	        wins_df[col_to_rank], wins_df.drop(columns=[col_to_rank])
    40.	    )
    41.	    results = model.fit(cov_type='HC1')
    42.	    rankings = pd.DataFrame(results.params)
    43.	    rankings['std'] = np.sqrt(np.diag(results.cov_params()))
    44.	    rankings['consistency'] = (norm.ppf(0.9)-norm.ppf(0.1))*rankings['std']
    45.	    rankings = (
    46.	        rankings
    47.	        .sort_values(by=0, ascending=False)
    48.	        .reset_index()
    49.	        .rename(columns={"index": "Driver", 0: "massey"})
    50.	    )
    51.	    rankings = rankings.sort_values(by=["massey"], ascending=False)
    52.	    rankings["massey_new"] = rankings["massey"].max() - rankings["massey"]
    53.	    return rankings[['Driver', 'massey_new']]
    54.	
    55.	rankings = massey(data, 5)
    56.	print(rankings)
    

赛道之王

著名车手艾尔顿·塞纳、迈克尔·舒马赫、刘易斯·汉密尔顿、马克斯·维斯塔彭以及费尔南多·阿隆索等车手在我们这份最强车手榜单中名列前茅。这一结果,来自Fastest Driver模型的洞见结论。结论来自由1983年至今所有车手的排位赛单圈用时生成的数据集排名,计算方法也非常简单,只考虑Driver, Rank (整数), Gap to Best(毫秒)几个变量。

需要强调的是,要量化车手的实际能力,我们需要将互动次数控制在最低水平。为此,我们只考虑五轮排位赛中同车队成员的对抗成绩。此外,我们还添加了大量参数与影响因素,努力消除各类实际条件给排名造成的影响——包括撞车、故障、年龄、职业暂歇或者排位赛期间的天气变化情况等。

此外,我们还注意到,如果某位车手在休息三年或者更长时间后重新回归F1赛场(例如2010年的迈克尔·舒马赫与佩德罗·德·拉·罗萨,2011年的卡菲基恩,2019年的罗伯特·库比卡等),则相对单圈成绩能够提高0.1秒。而当车手与同车队其他队员间的年龄差距较大时,例如2013年马克·韦伯对塞巴斯蒂安·维特尔,2017年费利佩·马萨对兰斯·斯特罗尔,以及2019年基米·莱科宁对安东尼奥·吉奥维纳齐,年轻一方也会表现出类似的优势。从1983年至2019年,我们通过观察发现与年龄较大的队员对抗时,年轻车手平均拥有0.06秒的单圈优势。

当然,这份榜单不能算是最终排名,每位车手的粉丝肯定也会有不同意见。我们鼓励大家健康的开展讨论!Fastest Driver只是提出了一种科学的车手排名方法,希望客观评估车手在不同赛车上表现出的操控水平。

使用Amazon SageMaker实现轻量化灵活部署

为了从Fastest Driver中获取洞见结论,我们在Python Web服务器上实施Massey方法。但一种复杂的情况在于,每轮比赛周末之后,模型需要使用新的认证数据进行圈速更新。为了及时完成模型更新,除了向Web服务器发送排名标准请求之外,我们还执行刷新请求,使服务器从(Amazon Simple Storage Service (Amazon S3)处下载新的认证数据。

我们将模型Web服务器部署在Amazon SageMaker模型端点之上。默认情况下,多实例Amazon SageMaker模型端点分布在多个可用区内,且内置有自动伸缩功能,能够保证我们的端点始终具备极高的可用性。除此之外,各端点还与其他Amazon SageMaker功能相集成,进一步提升系统的运行效能。例如Amazon SageMaker Model Monitor,能够自动监视端点中的模型漂移。作为一项全托管服务,Amazon SageMaker让我们的最终架构非常轻巧灵活。为了完成部署,我们还使用Amazon API Gateway 与 AWS Lambda在端点周边添加了API层。下图所示,为我们实际使用的基本架构。

这套架构包含以下操作步骤:

  1. 由用户向API Gateway发送一条请求。
  2. API Gateway将该请求发送至Lambda函数。
  3. 该Lambda函数向Amazon SageMaker模型端点生成一条请求。如果请求用于获取排名,则端点使用当前可用的认证数据计算UDC排名,并返回结果。如果请求用于执行刷新,则端点将从Amazon S3处下载新的认证数据。

总结

在本文中,我们讲解了F1与Amazon机器学习解决方案实验室的科学家们如何合作创建Fastest Driver——第一套以客观事实与数据资源驱动的分析模型,用于计算F1赛事历史上的最强车手。回顾F1赛事七十年的发展历程,F1与AWS之间的这项合作,为破解最强车手这个历史难题带来了独特的视角。跟随F1的机器学习探索脚步,您也可以将这项技术应用到其他领域的复杂问题当中,处理各种长久存在的争议。在本赛季的F1赛事中,车迷们将有机会看到“最强车手”们轮番登场,关注他们在最新一轮竞逐中的实际表现。

全世界的体育联盟都在运用AWS机器学习技术改善粉丝体验。健力士六国橄榄球锦标赛与德国德甲联赛已经在使用AWS服务帮助粉丝们更具体地观察赛场上的细节,获得更深刻的赛场动态见解。在美国,全国橄榄球联盟(NFL)使用AWS为球迷、球员及联盟各球队提供先进的统计数据,努力借助AI与机器学习之力改善球员们的健康与运动安全水平。

如果您希望加快在自有产品及流程中使用机器学习技术的进度,请与Amazon机器学习解决方案实验室联系。