人们对数据科学、机器学习和人工智能等术语存在诸多混淆。这些术语常常交替使用,但从更高角度讲:
机器学习的一个常常被忽略的部分是 80/20 规则,约 80% 的时间用来获取和处理数据,20% 的时间用于执行重要任务,比如分析数据、建模数据和执行预测。
点击查看大图
一个不太显眼的数据处理问题是,首先获取数据。使用公开数据集执行试验是一回事;抓取互联网数据、调用 API 并获取实用格式的数据完全是另一回事。除此之外,一个更具挑战性的问题是将数据应用于生产中。
点击查看大图
理所当然地,人们非常重视机器学习和建模所需的技能:应用数学、专业领域技能和工具知识。而部署一个用于生产的机器学习系统完全是另一回事。本教程系列仅作大致介绍,希望能激励您创建机器学习模型并将它们部署到生产中。
这里将对机器学习进行分层介绍,暂时先不作进一步描述。位于最高层的是监督学习和无监督学习。监督学习技术分为两种类型:分类问题和回归问题,它们都有一个包含带标签的数据的训练集。
机器学习监督回归问题的一个示例是,根据历史销售数据来预测未来的住房价格。监督分类问题的一个示例是,使用图像的历史存储库对图像中的物体进行分类:汽车、住房、形状等。
无监督学习涉及建模,其中的数据没有标签。正确的答案可能是未知的,需要去发现。一个常见示例是聚类。聚类的一个示例是查找具有某些共性的 NBA 球员群体,并手动为这些聚类添加标签 —例如最佳射手、篮板王等。
掌握了基础知识后,是时候开始深入钻研了:
要回答这些及其他问题,必须检索多种类别的数据:
点击查看大图
收集此数据是一个重要的软件工程问题。收集所有数据的第一步都是确定从何处开始。对于本教程,一个不错的起点是收集 NBA 2016-17 赛季中所有球员的数据。
这引出了一个对如何收集数据很有帮助的观点:如果手动收集数据比较容易(例如,从网站下载和在 Excel 中手动清理数据),那么这是一种开始解决数据科学问题的合理方式。如果收集数据源并手动清理数据要花好几个小时,那么最好能够通过编写代码来解决问题。
幸运的是,收集第一个数据源和从 Basketball Reference 下载一个 CSV 文件同样简单。现在已拥有第一个数据集合,是时候使用 pandas 和 Jupyter Notebook 来快速的探索它了。在运行代码之前,您需要:
因为包的安装和更新的模式很常见,所以我通常将它放在一个
Makefile中,如下所示:
setup: mkdir -p ~/.socialpowernba && python3 -m venv ~/.socialpowernba install: pip install -r requirements.txt
要开始在一个项目上工作,请运行
make setup && make install。
另一个诀窍是创建一个别名,以便在您想要在某个特定项目上工作时,能够在通过
cd命令进入项目时自动获取
virtualenv。包含此别名的 .zshrc 文件的内容类似于:
alias nbatop = "cd ~/src/socialpowernba && source ~/.socialpowernba/bin/activate"
要启动该虚拟环境,请键入
nbatop。通过
cd命令进入 checkout 目录并启动您的 virtualenv。
要检查您从 GitHub 存储库下载或使用的数据集:
启动 Jupyter Notebook:
Jupyter notebook。运行此命令会启动一个 web 浏览器,您可以在其中浏览现有 notebook 或创建新的 notebook。
如果您正在使用 GitHub 存储库中的文件,请查找 basketball_reference.ipynb,这是一个可以查看内部数据的简单 notebook。
可以使用 Web 浏览器上的菜单创建您的 notebook,或者加载名为 basketball_reference 的 GitHub 存储库中的 notebook。要执行初始验证和探索,请将一个 CSV 文件加载到 pandas 数据帧中。将一个 CSV 文件加载到 pandas 中很容易,但需要注意两点:
清单 2 展示了如何将该文件加载到 pandas 中。
import pandas as pd nba = pd.read_csv("../data/nba_2017_br.csv") nba.describe()
下图显示了数据加载结果。pandas 数据帧上的
describe函数提供了描述性统计数据,包括列数。在您的数据中,如下图所示,列数为 27,还显示了每列的中值(也就是 50% 处的行)。此刻,使用您创建的 Jupyter Notebook 并查看可以观察到哪些洞察可能是个好主意。要进一步了解 pandas 的功能,请参阅官方的
pandas 教程页面
。点击查看大图
此数据集缺少使用一个统计指标对球员的攻防表现进行排名的明确方式。仅使用一个统计指标对 NBA 中的球员进行排名的方法有许多。网站 FiveThirtyEight 中有一个 CARMELO 排名系统。ESPN 拥有真实贡献值,其中非常方便地列出了每个球员的获胜数据。NBA 的单数字统计指标名为 PIE (Player Impact Estimate)。
同时从 ESPN 和 NBA 网站获取数据时,难度稍有增加。一种解决方法是使用诸如 Scrapy 之类的工具从该网站抓取数据。不过,本教程中使用的方法稍微简单一点。在本例中,我们将数据从该网站剪切并粘贴到 Excel 中,手动清理数据,然后将数据保存为 CSV,这比编写代码来完成此任务要快得多。以后,如果该项目变成了更大的项目,此方法也可能不太适用。但对于本教程,这是一个不错的解决方案。处理复杂数据科学问题的一个关键结论是,持续快速地取得进展,而无需深究。
"您可能花了大量时间来完善获取数据源并执行清理的方式,却发现数据对您要创建的模型没有多大帮助。"
下图显示了 NBA PIE 数据集。该数据也有 486 个或 486 行。从 ESPN 获取数据的过程与上述过程类似。要考虑的其他数据源包括薪资和代言。ESPN 拥有薪资信息,Forbes 拥有少量的代言数据。这两个数据源都包含在 GitHub 项目中。
点击查看大图
在表 1 中,有一个数据源的名称和位置清单。很快,我们拥有了来自许多不同数据源的许多内容。
数据源 | 文件名 | 行数 | 摘要 |
---|---|---|---|
Basketball-Reference | nba_2017_attendance.csv | 30 | 体育馆出场率 |
Forbes | nba_2017_endorsements.csv | 8 | 最佳球员 |
Forbes | nba_2017_team_valuations.csv | 30 | 所有球队 |
ESPN | nba_2017_salary.csv | 450 | 大部分球员 |
NBA | nba_2017_pie.csv | 468 | 所有球员 |
ESPN | nba_2017_real_plus_minus.csv | 468 | 所有球员 |
Basketball-Reference | nba_2017_br.csv | 468 | 所有球员 |
FiveThirtyEight | nba_2017_elo.csv | 30 | 球队排名 |
要下载所有这些数据并将它们转换为统一的数据集,仍有许多工作要做。更糟的是,目前为止,收集数据都很容易。但前面仍有很长的路要走。查看此数据的形式就可以发现,一个不错的起点是获取排名前 8 的球员的代言数据,查看是否可以梳理出一种模式。但是,在这样做之前,需要了解 NBA 球队的估值。从这里,您可以确定某个球员对 NBA 职业球队整体价值的影响。
第一个任务是创建一个新的 Jupyter Notebook。对您而言幸运的是,已经创建好了 Jupyter Notebook。可以在 GitHub 存储库 exploring_team_valuation_nba 中找到它。
接下来,导入一组常用库,这些库通常用来探索 Jupyter Notebook 中的数据。
import pandas as pd import statsmodels.api as sm import statsmodels.formula.api as smf import matplotlib.pyplot as plt import seaborn as sns color = sns.color_palette() %matplotlib inline
现在您需要为每个来源都创建一个 pandas 数据。
attendance_df = pd.read_csv("../data/nba_2017_attendance.csv") endorsement_df = pd.read_csv("../data/nba_2017_endorsements.csv") valuations_df = pd.read_csv("../data/nba_2017_team_valuations.csv") salary_df = pd.read_csv("../data/nba_2017_salary.csv") pie_df = pd.read_csv("../data/nba_2017_pie.csv") plus_minus_df = pd.read_csv("../data/nba_2017_real_plus_minus.csv") br_stats_df = pd.read_csv("../data/nba_2017_br.csv") elo_df = pd.read_csv("../data/nba_2017_elo.csv")
处理大量数据源时,一个巧妙的方法是显示每个数据帧的前几行。可以在以下图片中看到这些内容。
点击查看大图
点击查看大图
现在,将球队估值数据与出场率数据合并,并创建一个图表。清单 5 提供了合并 pandas 数据帧的代码。
attendance_valuation_df = attendance_df.merge(valuations_df, how="inner", on="TEAM") attendance_valuation_df.head()
下图显示了合并的输出。
点击查看大图
为了更好地理解刚合并的数据,可执行一些快速可视化。第一步是告诉该 notebook 显示更宽的图表,然后执行一次 Seaborne pairplot,如下所示。
from IPython.core.display import display, html display(HTML("")) sns.pairplot(attendance_valuation_df, hue="TEAM")
查看这些图表,注意平均出场率与球员估值之间的关系。两个特征之间存在一种强线性关系,这一点从各个点形成的接近直线的线就可以看出。
点击查看大图
分析此数据的另一种方法是创建关联图。要创建关联图,请执行下面提供的代码,下图显示了输出。
corr = attendance_valuation_df.corr() sns.heatmap(corr, xticklabels=corr.columns.values, yticklabels=corr.columns.values)
点击查看大图
该关联图表明了(NBA 球队的)价值(以百万美元为单位)、体育馆的平均上座率 (PCT) 和平均出场率之间的关系。通过热图显示 NBA 中每个球队的平均出勤次数与估值之间的关系,这有助于深入分析此数据。要在 Seaborn 中生成热图,必须将数据重塑为数据透视表(非常类似于 Excel 中的功能)。数据透视表允许 Seaborn 图表对 3 个值进行透视分析,并显示 3 列中的每一列与其他两列的关系。下面的代码展示了如何将数据重塑为数据透视表。
valuations = attendance_valuation_df.pivot("TEAM", "AVG", "VALUE_MILLIONS") plt.subplots(figsize=(20,15)) ax = plt.axes() ax.set_title("NBA Team AVG Attendance vs Valuation in Millions: 2016-2017 Season") sns.heatmap(valuations,linewidths=.5, annot=True, fmt='g')
图 11 显示了一些有趣的异常值,例如,布鲁克林篮网队的估值为 18 亿美元,而他们在 NBA 中的平均出场率最低。这种情况值得分析一下。
点击查看大图
一种深入调查方法是使用 Statsmodels 包执行一次线性回归。依据 Statsmodels.org,Statsmodels 包 " 是一个 Python 模块,它提供类和函数来对许多不同的统计模型进行估算,并执行统计测试和统计数据探索。每个估算工具都有一个庞大的结果统计数据列表。"
您可使用
pip install Statsmodel命令安装 Statsmodels 包。以下是运行回归所需的 3 行代码。
results = smf.ols('VALUE_MILLIONS ~AVG', data=attendance_valuation_df).fit() print(results.summary())
下图显示了该回归的输出。决定系数表明,约 28% 的估值可通过出场率来解释,P 值 0.044 在具有统计意义的范围内。 该数据的一个潜在问题是,残值图表看起来不是完全随机的。这是尝试开发一个模型来解释 NBA 职业球队的估值组成部分的良好开端。
点击查看大图
潜在地向该模型添加更多数据的一种方法是,添加每个球队的 ELO 数量。依据 Wikipedia,"ELO 评分系统是一种计算比赛者在竞技比赛(比如象棋)中的相对技能水平的方法 。"ELO 评分系统也用在体育项目中。
ELO 数量包含的信息比胜 / 负记录更多,因为它们依据比赛对手的实力进行排名。调查某个球队对估值的影响程度似乎是个不错的主意。
为此,可将 ELO 数据合并到此数据中,如下所示。
attendance_valuation_elo_df = attendance_df.merge(elo_df, how="inner", on="TEAM") attendance_valuation_elo_df.head() attendance_valuation_elo_df.to_csv("../data/nba_2017_att_val_elo.csv") corr_elo = attendance_valuation_elo_df.corr() plt.subplots(figsize=(20,15)) ax = plt.axes() ax.set_title("NBA Team Correlation Heatmap: 2016-2017 Season (ELO, AVG Attendance, VALUATION IN MILLIONS)") sns.heatmap(corr_elo, xticklabels=corr_elo.columns.values, yticklabels=corr_elo.columns.values) corr_elo ax = sns.lmplot(x="ELO", y="AVG", data=attendance_valuation_elo_df, hue="CONF", size=12) ax.set(xlabel='ELO Score', ylabel='Average Attendance Per Game', title="NBA Team AVG Attendance vs ELO Ranking: 2016-2017 Season") attendance_valuation_elo_df.groupby("CONF")["ELO"].median() attendance_valuation_elo_df.groupby("CONF")["AVG"].median()
合并后,需要创建两个图表。第一个图表是一个新的关联度热图,如图 13 所示。一些正相关关系需要更详细地解释一下。具体来讲,出场率与 ELO 之间的关系似乎值得画出来。在下面的热图中,颜色越浅,两列就越相关。如果矩阵显示同一个值与自己作比较,则关联度为 1,该正方形显示为米黄色。对于 TOTAL 和 ELO,关联度似乎为 0.5。
点击查看大图
图 14 描绘了 ELO 与出场率之间的关系球队的表现 (ELO RANK) 与出场率之间似乎存在一种弱线性关系。下图用不同颜色分别绘制了东散点图和西散点图,并提供了一个置信区间。弱线性关系由穿过 X,Y 空间中的点的直线表示。
点击查看大图
线性回归有助于进一步检查图表中的关系。
results = smf.ols('AVG ~ELO', data=attendance_valuation_elo_df).fit() print(results.summary())
回归的输出(参见图 15)显示决定系数为 8%,P 值为 0.027,所以也存在一个有统计意义的信号,但该信号非常弱。
点击查看大图
要处理的最后一项是,使用 k-means 聚类基于 AVG、ELO 和 VALUE_MILLIONS 创建 3 个聚类。
from sklearn.cluster import KMeans from sklearn.preprocessing import MinMaxScaler #Only cluster on these values numerical_df = val_housing_win_df.loc[:,["TOTAL_ATTENDANCE_MILLIONS", "ELO", "VALUE_MILLIONS", "MEDIAN_HOME_PRICE_COUNTY_MILLONS"]] #Scale to between 0 and 1 from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() print(scaler.fit(numerical_df)) print(scaler.transform(numerical_df)) #Add back to DataFrame from sklearn.cluster import KMeans k_means = KMeans(n_clusters=3) kmeans = k_means.fit(scaler.transform(numerical_df)) val_housing_win_df['cluster'] = kmeans.labels_ val_housing_win_df.head()
通过下面的图表可以看到,有 3 个不同的分组,而且聚类的中心表示不同的标签。需要注意的是,这里使用了 sklearn MinMaxScaler 将所有列缩放至 0 与 1 之间的某个值,以便标准化各个尺度之间的差异。
点击查看大图
下图显示了聚类 1 的成员。从这个聚类得出的主要结论是,它们既是 NBA 中的最佳球队,也是拥有最高平均出场率的球队。产生分歧的地方在总估值上。例如,依据 ELO,犹他爵士队是一支非常优秀的球队,而且拥有非常高的出场率,但他们的估值没有聚类中其他成员那么高。这可能意味着犹他爵士队有机会通过细微调整来显著提高球队估值。
点击查看大图
本系列包含两个部分,在第 1 部分中,您学习了数据科学和机器学习的基本知识,并开始探索估值、出场率与获胜 NBA 球队的关系。教程的代码保存在一个可在这里引用的 Jupyter Notebook 中。 第 2 部分将抛开球队,探索 NBA 中的每个球员。这部分将探索代言数据、真实场上表现,以及 Twitter 和 Wikipedia 的社会力量。
目前为止,我们从数据探索中学到的经验包括:
来源: http://www.ibm.com/developerworks/cn/opensource/ba-offloading-informix-data-spark-2/index.html