Python实战|用决策树实现NBA获胜球队预测

简介: Python实战|用决策树实现NBA获胜球队预测

NBA预测获胜球队

数据获取

因为疫情原因导致NBA2019-2020赛季没有进行完,所以我们使用NBA2018-2019赛季的数据进行预测,数据获取方式有下面两种:


通过网站获取

我们可以通过网站去获取任意一年的所有场次比赛数据,获取方式如下:


  1. 在浏览器中访问https://www.basketball-reference.com/leagues/NBA_2019_games.html
  2. 点击Share&more
  3. 点击Get table as CSV (for Excel)
  4. 复制连带表头的所有数据到Excel的文本文件中
  5. 依次选择每一个月份,复制不带表头的数据到上一个文件后


同时我们还需要获取上赛季积分榜的数据,获取方式如下:


  1. 在浏览器中访问https://www.basketball-reference.com/leagues/NBA_2018_standings.html
  2. 点击Expander Standings,可以看到整个赛季的战况信息
  3. 点击Export链接
  4. 复制数据并保存即可


通过GitHub获取

本文中的数据和代码已经上传到GitHub上,链接如下:https://github.com/bigdatavalley/NBA_predict


数据准备

在进行预测的算法设计之前,我们需要先进行数据的查看和整合,由于原有数据中很多的特征名称设定的不是很好,所以我们在加载数据的时候重新设定一下列名称,代码如下:

import pandas as pd
path = 'basketball.csv'
dataset = pd.read_csv(path, parse_dates=['Date'])
dataset.columns = [
    'Date', 'Start(ET)', 'Visitor Team', 'VisitorPts', 'Home Team', 'HomePts',
    'OT?', 'Score Type', 'Notes'
]
dataset.head()

运行结果如下:

25.png

我们在建立预测模型的时候通常会有一个标准,当我们的预测效果超过这个标准的时候我们就可以认为预测模型起到了作用,接下来我们来建立一个关于预测球队获胜的标准。


在NBA比赛中,通常分为主客场,当球队在主场比赛的时候往往会占据一定的优势,那么如果我们每次都预测主场球队获胜,应该也能得到不错的准确率,那么我们就可以用这个数值来当作我们的标准,代码如下:

# 提取新特征
# 统计客队得分小于主队的场次
dataset['HomeWin'] = dataset['VisitorPts'] < dataset['HomePts']
# 保留成label
y_true = dataset['HomeWin'].values
# y_true
dataset['HomeWin'].mean()

运行结果如下:

0.5907012195121951

现在我们就有了一个0.59作为标准,后面我们要保证建立的模型不低于这个准确率就可以了。


构建特征

构造特征一点一点进行,后面我们再陆续添加新的特征。


进行模型建立之前,还有一个重要的过程就是构建我们要使用的特征,第一个我们要思考的就是两只球队是否赢得了上一场的比赛,通常我们会认为赢得了上一场比赛的球队就是更厉害的。我们建立两个新的特征分别是主队/客队是否赢了上一场比赛。代码如下:

from collections import defaultdict
won_last = defaultdict(int)
dataset['HomeLastWin'] = 0
dataset['VisitorLastWin'] = 0
# 时间是无序的时候dataset.sort('Date').iterrows()
for index, row in dataset.iterrows():
    home_team = row['Home Team']
    visitor_team = row['Visitor Team']
    dataset.at[index, 'HomeLastWin'] = won_last[home_team]
    dataset.at[index, 'VisitorLastWin'] = won_last[visitor_team]
    won_last[home_team] = int(row['HomeWin'])
    won_last[visitor_team] = 1 - int(row['HomeWin'])
X_previouswins = dataset[['HomeLastWin', 'VisitorLastWin']].values
X_previouswins

运行结果如下:

array([[0, 0],
       [0, 0],
       [0, 0],
       ...,
       [0, 1],
       [1, 0],
       [1, 0]])

使用决策树

我们尝试使用简单的决策树算法进行简单的训练,并且通过交叉验证的方式获取评分。


决策树的原理:

决策树(上)

决策树(下)


代码如下:

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
import numpy as np
clf = DecisionTreeClassifier(random_state=42)
score = cross_val_score(clf, X_previouswins, y_true, scoring = 'accuracy')
print('score is:{0:.1f}%'.format(np.mean(score)*100))

运行结果如下:

score is:59.1%

根据结果可以发现,当前的特征下,并没有使得我们的预测效果提高,接下来我们继续对数据和模型进行改进。


增加特征

考虑到球队获胜可能和上个赛季的战绩也有一定的关系,我们尝试加入上个赛季的数据来进行预测。

# 加入上赛季数据
standings = pd.read_excel('standings.xls')
# 建立新的特征(排名情况)
dataset['HomeTeamRanksHigher'] = 0
for index, row in dataset.iterrows():
    home_team = row['Home Team']
    visitor_team = row['Visitor Team']
    home_rank = standings[standings['Team'] == home_team]['Rk'].values[0]
    visitor_rank = standings[standings['Team'] == visitor_team]['Rk'].values[0]
    row['HomeTeamRanksHigher'] = int(home_rank > visitor_rank)
    dataset.at[index, 'HomeTeamRanksHigher'] = int(home_rank < visitor_rank)
clf = DecisionTreeClassifier(random_state=42)
X_homehigher = dataset[[
    'HomeLastWin', 'VisitorLastWin', 'HomeTeamRanksHigher'
]].values
score = cross_val_score(clf, X_homehigher, y_true, scoring='accuracy')
print('score is:{0:.1f}%'.format(np.mean(score) * 100))

运行结果如下:

score is:62.2%

很明显,我们加入上个赛季的战绩的时候,预测的准确率提升了3个百分点。


接下来我们继续加入交手的两只球队中哪一个在上一次交手中胜出的数据,代码如下:

last_match_winner = defaultdict(int)
dataset['HomeTeamWonLast'] = 0
for index, row in dataset.iterrows():
    home_team = row['Home Team']
    visitor_team = row['Visitor Team']
    teams = tuple(sorted([home_team, visitor_team]))
    home_team_won_last = 1 if last_match_winner[teams] == row[
        'Home Team'] else 0
    dataset.at[index, 'HomeTeamWonLast'] = home_team_won_last
    winner = row['Home Team'] if row['HomeWin'] else row['Visitor Team']
    last_match_winner[teams] = winner
clf = DecisionTreeClassifier(random_state=42)
X_lastwinner = dataset[[
    'HomeLastWin', 'VisitorLastWin', 'HomeTeamRanksHigher', 'HomeTeamWonLast'
]].values
score = cross_val_score(clf, X_lastwinner, y_true, scoring='accuracy')
print('score is:{0:.1f}%'.format(np.mean(score) * 100))

运行结果如下:

score is:61.7%

结果和上面差异不大,没有关系,我们继续尝试使用其他的策略来进行改进。


加入队伍数据

我们之前做的工作都是根据一些比赛数据来进行的,下面我们尝试加入队伍数据来检验一下我们的运行成果,由于我们不能直接对字符数据进行计算,所以先把数据通过LabelEncoder转化为数值类型,但是一般数值类型又会有大小造成的影响,所以我们再进行一次OneHotEncoder的操作即可。代码如下:

from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
encoding = LabelEncoder()
onehot = OneHotEncoder()
encoding.fit(dataset['Home Team'].values)
home_teams = encoding.transform(dataset['Home Team'].values)
visitor_teams = encoding.transform(dataset['Visitor Team'].values)
X_teams = np.vstack([home_teams, visitor_teams]).T
X_teams = onehot.fit_transform(X_teams).todense()
X_all = np.hstack([X_lastwinner, X_teams])
clf = DecisionTreeClassifier(random_state=42)
score = cross_val_score(clf, X_all, y_true, scoring='accuracy')
print('score is:{0:.1f}%'.format(np.mean(score) * 100))

运行结果如下:

score is:60.7%

很显然虽然比我们直接预测主队获胜的效果要好,但是也没有高出很多。不要慌,我们继续使用更好的算法来尝试一下。


使用随机森林

随机森林是一种以决策树为基分类器的集成学习算法,理论上讲,我们所得到的效果要好于决策树。

代码如下:

clf = RandomForestClassifier(random_state=42)
score = cross_val_score(clf, X_all, y_true, scoring='accuracy')
print('score is:{0:.1f}%'.format(np.mean(score) * 100))

运行结果如下:

score is:63.6%

尝试使用网格搜索,代码如下:

from sklearn.model_selection import GridSearchCV
parameter_space = {
    'max_features': [2, 10, 'auto'],
    'n_estimators': [100, 200],
    'criterion': ['gini', 'entropy'],
    'min_samples_leaf': [2, 4, 6]
}
clf = RandomForestClassifier(random_state=42)
grid = GridSearchCV(clf, parameter_space)
grid.fit(X_all, y_true)
print('score is:{0:.1f}%'.format(np.mean(score) * 100))

运行结果如下:

score is:63.6%

可以看到根据目前我们所构造的几个简单的特征就已经可以得到显著的准确率提升了。同时收到球员转会、受伤等情况的影响,对于不同赛季的数据使用这些方法会得到不同的结果,有兴趣的读者可以自己获取其他赛季的数据来尝试一下。


进一步考虑

你可能对当前的结果还不是很满意,可以尝试进行下面几个方向的参考:


  • 上一次比赛距离本次比赛的时间
  • 最近半个月的比赛状态
  • 双方在最近几场比赛的战绩
  • 每个球队在客场和主场的表现情况
相关文章
|
2月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
30天前
|
测试技术 数据库 Python
Python装饰器实战:打造高效性能计时工具
在数据分析中,处理大规模数据时,分析代码性能至关重要。本文介绍如何使用Python装饰器实现性能计时工具,在不改变现有代码的基础上,方便快速地测试函数执行时间。该方法具有侵入性小、复用性强、灵活度高等优点,有助于快速发现性能瓶颈并优化代码。通过设置循环次数参数,可以更准确地评估函数的平均执行时间,提升开发效率。
103 61
Python装饰器实战:打造高效性能计时工具
|
2天前
|
存储 数据采集 数据库
Python爬虫实战:股票分时数据抓取与存储
Python爬虫实战:股票分时数据抓取与存储
|
26天前
|
运维 Shell 数据库
Python执行Shell命令并获取结果:深入解析与实战
通过以上内容,开发者可以在实际项目中灵活应用Python执行Shell命令,实现各种自动化任务,提高开发和运维效率。
54 20
|
2月前
|
小程序 开发者 Python
探索Python编程:从基础到实战
本文将引导你走进Python编程的世界,从基础语法开始,逐步深入到实战项目。我们将一起探讨如何在编程中发挥创意,解决问题,并分享一些实用的技巧和心得。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供有价值的参考。让我们一起开启Python编程的探索之旅吧!
64 10
|
2月前
|
数据采集 存储 XML
python实战——使用代理IP批量获取手机类电商数据
本文介绍了如何使用代理IP批量获取华为荣耀Magic7 Pro手机在电商网站的商品数据,包括名称、价格、销量和用户评价等。通过Python实现自动化采集,并存储到本地文件中。使用青果网络的代理IP服务,可以提高数据采集的安全性和效率,确保数据的多样性和准确性。文中详细描述了准备工作、API鉴权、代理授权及获取接口的过程,并提供了代码示例,帮助读者快速上手。手机数据来源为京东(item.jd.com),代理IP资源来自青果网络(qg.net)。
|
3月前
|
算法 Unix 数据库
Python编程入门:从基础到实战
本篇文章将带你进入Python编程的奇妙世界。我们将从最基础的概念开始,逐步深入,最后通过一个实际的项目案例,让你真正体验到Python编程的乐趣和实用性。无论你是编程新手,还是有一定基础的开发者,这篇文章都将为你提供有价值的信息和知识。让我们一起探索Python的世界吧!
|
2月前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!

热门文章

最新文章