您当前位置:资讯中心 >服务器 >浏览文章

异常值检测方法比较——基于美国职业棒球联盟2023赛季击球数据

来源: 51CTO 日期:2024/1/25 8:00:00 阅读量:(0)

译者 | 朱先忠

审校 | 重楼

异常值检测是一种无监督的机器学习任务,用于识别给定数据集中的异常(即“异常观测”)。在大量现实世界中,当我们的可用数据集已经被异常“污染”时,异常值检测任务对于整个机器学习环节来说是非常有帮助的。当前,开源框架Scikit learn已经实现了几种异常值检测算法,在我们持有未受污染的基准数据的情况下,我们也可以使用这些算法进行新颖检测。这是一项半监督任务,可以预测新的观测结果是否为异常值。

概述

本文中,我们将比较的四种异常值检测算法如下

  • 椭圆包络(Elliptic Envelope)适用于低维正态分布数据。顾名思义,它使用多元正态分布来创建一个距离度量指标,以便将异常值与内部值区分开来。
  • 局部异常因子(Local Outlier Factor)是一种针对观测的局部密度与其邻居的局部密度的比较。密度比其邻居低得多的观测被视为异常值。
  • 具有随机梯度下降的类支持向量机(One-Class Support Vector Machine with Stochastic Gradient Descent)是一类SVM的O(n)近似解。请注意,O(n2)数量级的单类SVM在我们的小示例数据集上运行良好,但对于您的实际应用场景来说可能不切实际。
  • 孤立森(Isolation Forest)是一种基于树的方法,其中异常值通过随机拆分方法使用内部值方法可实现更快隔离。

由于我们的任务是无监督的;所以,我们没有基本事实来比较这些算法的准确性。相反,我们想看看他们的结果(尤其是球员排名方面)彼此之间的差异,并对他们的行为和局限性获得一些直觉,这样我们就可以知道什么时候更喜欢其中名球员而不是另一

接下来,让我们使用2023年美国职业棒球大联盟(MLB)赛季击球手表现的两个指标来比较其中的一些技术

  • 上垒(OBP),击球手每次上垒时(通过击球、保送或投球命中)上垒的速度
  • Slugging(SLG),每次击球的平均总垒数

击球手表现有许多更复杂的指标,例如OBP加SLG(OPS)、基本平均加权(wOBA)和调整后的加权跑动(WRC+)。然而,我们将看到,除了常用和易于理解之外,OBP和SLG具有适度的相关性和近似正态分布,使它们非常适合这种比较。

数据集准备

我们使用pybalball包来获取击球数据。该Python包受MIT许可,能够取得来自于Fangraphs.comBaseball-Reference.com和其他来源数据;当然,这些来源反过来又从美国职业棒球大联盟获得官方记录数据

我们使用pybalball的2023年击球统计数据,可以通过batting_stats(FanGraphs网站)或batting_stasts_bref(权威网站Baseball Reference)获得。事实证明,FanGraphs中的球员名称格式更正确,但Baseball Reference中的球员团队和联盟在交易球员的情况下格式更好。为了获得一个具有更高可读性的数据集,我们实际上需要合并三个表:FanGraphs、Baseball Reference和键查询

from pybaseball import (cache, batting_stats_bref, batting_stats, 
                        playerid_reverse_lookup)
import pandas as pd

cache.enable()  # 重新运行时避免不必要的请求

MIN_PLATE_APPEARANCES = 200

# 为了可读性和合理的默认排序顺序
df_bref = batting_stats_bref(2023).query(f"PA >= {MIN_PLATE_APPEARANCES}"
                                        ).rename(columns={"Lev":"League",
                                                          "Tm":"Team"}
                                                )
df_bref["League"] = \
  df_bref["League"].str.replace("Maj-","").replace("AL,NL","NL/AL"
                                                  ).astype('category')

df_fg = batting_stats(2023, qual=MIN_PLATE_APPEARANCES)

key_mapping = \
  playerid_reverse_lookup(df_bref["mlbID"].to_list(), key_type='mlbam'
                         )[["key_mlbam","key_fangraphs"]
                          ].rename(columns={"key_mlbam":"mlbID",
                                            "key_fangraphs":"IDfg"}
                                  )

df = df_fg.drop(columns="Team"
               ).merge(key_mapping, how="inner", on="IDfg"
                      ).merge(df_bref[["mlbID","League","Team"]],
                              how="inner", on="mlbID"
                             ).sort_values(["League","Team","Name"])
关键字:
声明:我公司网站部分信息和资讯来自于网络,若涉及版权相关问题请致电(63937922)或在线提交留言告知,我们会第一时间屏蔽删除。
有价值
0% (0)
无价值
0% (10)

分享转发:

发表评论请先登录后发表评论。愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。