前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于《Python数据挖掘入门与实战》读书笔记五(决策树和随机森林)

关于《Python数据挖掘入门与实战》读书笔记五(决策树和随机森林)

作者头像
python与大数据分析
发布2022-03-11 13:18:04
3280
发布2022-03-11 13:18:04
举报
文章被收录于专栏:python与大数据分析

本笔记介绍两种分类算法——决策树和随机森林决策树,用它预测NBA篮球赛的获胜球队。比起其他算法,决策树有很多优点,其中最主要的一个优点是决策过程是机器和人都能看懂的,我们使用机器学习到的模型就能完成预测任务。

通过决策树预测NBA获胜球队,主要包括以下几个知识点:

1、数据预处理,主要是队名的转换,消除歧义

2、寻找新特征辅助预测,比如增加主客队胜负关系,上一场获胜情况,其实可以追加很多指标,比如主客场胜率,比如交叉战绩情况,比如连续获胜场次等等

3、爬取辅助数据,NBA2013年最终成绩,主要原因是NBA2013年的数据已无法获取,拷贝到excel中面临格式调整。

代码示例

代码语言:javascript
复制
import pandas as pd
import numpy as np
import re
from sklearn.tree import DecisionTreeClassifier
from sklearn.cross_validation import cross_val_score
from urllib.request import urlopen
from bs4 import BeautifulSoup
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import GridSearchCV
def get_nba_2013data():
    # 1、获取html内容,2、BeautifulSoup进行转换,3、缩小范围再次进行匹配,
    # 4、正则表达式匹配,5、再次进行BeautifulSoup进行转换转换,6、遍历tr,7遍历td
    # 8、将list转换为DataFrame,将DataFrame存为csv格式
    #正则表达式匹配tbody之间的任意字符
    pattern = re.compile('<tbody>[\s\S]*?</tbody>')#模仿html注释的正则
    #获取2013年NBA比赛结果URL,并转换为BeautifulSoup格式
    url = 'https://www.basketball-reference.com/leagues/NBA_2013_standings.html'
    html = urlopen(url).read()
    bSoup = BeautifulSoup(html,'lxml')
    #找到ID=all_expanded_standings之间的内容并格式化
    content = bSoup.find(id='all_expanded_standings').prettify()
    match = re.search(pattern,content)
    str_tbody = match.group()
    # 将str字符串传入获得html对象
    html_tbody = BeautifulSoup(str_tbody,'lxml')
    list = []
    for tr in html_tbody.find_all('tr'):
        rows = [td.text for td in tr.find_all('td')]
        list.append(rows)
    print(list)
    #转成csv格式
    file = 'NBAstanding.csv'
    df_data = pd.DataFrame(data=list)
    df_data.to_csv(file)

#---------------------------数据集加载--------------------------------
data_filename='leagues_NBA_2014_games_games.csv'
dataset=pd.read_csv(data_filename, parse_dates= ['Date'])
#---------------------------数据集清洗--------------------------------
#重命名表头
dataset.columns = ['Date','Score Type', 'Visitor Team', 'VisitorPts', 'Home Team', 'HomePts', 'OT?', 'Notes']
#读取前5项数据集,数据集合形状,数据表头
#print(dataset.head())
print(dataset[:5])
#print(dataset.shape)   # (1319, 8)
print(dataset.columns)
#---------------------------提取新特征--------------------------------
dataset["HomeWin"] = dataset["VisitorPts"] < dataset["HomePts"]
y_true = dataset["HomeWin"].values
from collections import defaultdict
#创建(默认)字典,存储球队上次比赛的结果
won_last = defaultdict(int)
#在原有数据集中增加两列,上次主队是否获胜上次客队是否获胜
dataset['HomeLastWin'] = None
dataset['VisitorLastWin'] = None
for index, row in dataset.iterrows():
    #获取本次主客队名称
    home_team = row['Home Team']
    visitor_team = row['Visitor Team']
    #根据名称获取上次主客队胜负情况
    row['HomeLastWin'] = won_last[home_team]
    row['VisitorLastWin'] = won_last[visitor_team]
    #更新数据集当前行
    dataset.ix[index] = row
    #用当前比赛的结果更新两支球队上场比赛的获胜情况, 以便下次再遍历到这两支球队时使用
    won_last[home_team] = row['HomeWin']    #判断上一场是否获胜
    won_last[visitor_team] =not row['HomeWin']
print(dataset[:5])
#-----------------------------决策树----------------------------------
#决策树是一种有监督的机器学习算法,它看起来就像是由一系列节点组成的流程图
#  首先是训练阶段,用训练数据构造一棵树。
#  其次是预测阶段,用训练好的决策树预测新数据的类别。
#scikit-learn库实现的决策树算法给出了退出方法,使用下面这两个选项就可以达到目的。
# 剪枝:先创建一棵完整的树,再对其进行修剪,去掉对整个过程没有提供太多信息的节点。
# 退出:是决策树的一个重要特性。构建决策树时,后几步决策仅依赖于少数个体,随意性大。
# 使用特定节点作出推测容易导致过拟合训练数据,而使用退出准则可以防止决策精度过高。
#  min_samples_split:指定创建一个新节点至少需要的个体数量。
#  min_samples_leaf:指定为了保留节点,每个节点至少应该包含的个体数量
# 第一个参数控制着决策节点的创建,第二个参数决定着决策节点能否被保留
# 决策树的另一个参数是创建决策的标准,常用的有以下两个。
#  基尼不纯度(Gini impurity):用于衡量决策节点错误预测新个体类别的比例。
#  信息增益(Information gain):用信息论中的熵来表示决策节点提供多少新信息。
clf = DecisionTreeClassifier(random_state=14)
X_previouswins = dataset[["HomeLastWin", "VisitorLastWin"]].values
scores = cross_val_score(clf, X_previouswins, y_true, scoring='accuracy')
print("决策树 Accuracy: {0:.1f}%".format(np.mean(scores) * 100))
#------------------------------版本2----------------------------------
#-----------------使用 2013赛季的战绩作为特征取值来源-----------------
#获取2013年NBA排名成绩
#get_nba_2013data()
#创建一个新特征,创建过程与上个特征类似。
# 遍历每一行,查找主场队和客场队两NBA比赛结果预测支球队的战绩。
standings = pd.read_csv('NBAstanding.csv',header=None)
#创建一个新特征,创建过程与上个特征类似。
# 遍历每一行,查找主场队和客场队两NBA比赛结果预测支球队的战绩。
standings.columns = ['Rk','Team','Overall','Home','Road','E','W','A','C','SE','NW','P','SW','Pre','Post','≤3','≥10','Oct','Nov','Dec','Jan','Feb','Mar','Apr']
#print(standings .head())
dataset['HomeTeamRanksHigher'] = 0
for index,row in dataset.iterrows():
    #获取主客队名称
    home_team = row['Home Team']
    visitor_team = row['Visitor Team']
    #数据清洗,修改队名,两边数据保持一致
    if home_team == 'New Orleans Pelicans':
        home_team = 'New Orleans Hornets'
    if visitor_team == 'New Orleans Pelicans':
        visitor_team = 'New Orleans Hornets'
    #获取主客队成绩,另增加一列进行成绩对比
    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.ix[index] = row
#用新结果集进行决策树预测
X_homehigher = dataset[['HomeLastWin','VisitorLastWin','HomeTeamRanksHigher']].values
clf = DecisionTreeClassifier(random_state=14)
scores = cross_val_score(clf,X_homehigher,y_true,scoring='accuracy')
print('决策树(参考2013年战绩)Accuracy:{0:.1f}%'.format(np.mean(scores)*100))
#------------------------------版本3----------------------------------
#-----用LabelEncoder转换器就能把字符串类型的球队名转化为整型。--------
encoding = LabelEncoder()
#将主场球队名称转化为整型:
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
onehot = OneHotEncoder()
#在相同的数据集上进行预处理和训练操作,将结果保存起来备用。
X_teams_expanded = onehot.fit_transform(X_teams).todense()
#接着,像之前那样在新数据集上调用决策树分类器。
clf = DecisionTreeClassifier(random_state=14)
scores = cross_val_score(clf, X_teams_expanded, y_true,   scoring='accuracy')
print("决策树(队名转化) Accuracy: {0:.1f}%".format(np.mean(scores) * 100))

# 一棵决策树可以学到很复杂的规则。然而,很可能会导致过拟合问题——学到的规则只适用 于训练集。
# 解决方法之一就是调整决策树算法,限制它所学到的规则的数量
# 使用这种折中方案得到的决策树泛化 能力强,但整体表现稍弱
# 随机森林的工作原理:创建多棵决策树,用它们分别进行预测,再根据少数服 从多数的原则从多个预测结果中选择终预测结果。
# 装袋(bagging):每次随机从数据集中选取一部分数据用作训练集。
# 随机选取部分特征作为决策依据。
#------------------------版本4 随机森林-------------------------------
#的随机森林算法使用估计器接口,用交叉检验方法调用它即可
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(random_state=14)
scores = cross_val_score(clf, X_teams, y_true, scoring='accuracy')
print("随机森林 Accuracy: {0:.1f}%".format(np.mean(scores) * 100))
#随机森林使用不同的特征子集进行学习,应该比普通的决策树更为高效。
X_all = np.hstack([X_homehigher, X_teams])
clf = RandomForestClassifier(random_state=14)
scores = cross_val_score(clf, X_all, y_true, scoring='accuracy')
print("随机森林(采用不同特征) Accuracy: {0:.1f}%".format(np.mean(scores) * 100))
#可以使用GridSearchCV类搜索佳参数
#能够在指定的范围内自动搜索具有不同超参数的不同模型组合
parameter_space = {    'max_features': ['auto', 'sqrt', 'log2'],
                       "n_estimators": [100,],
                       "criterion": ["gini", "entropy"],
                       "min_samples_leaf": [2, 4, 6], }
clf = RandomForestClassifier(random_state=14)
grid = GridSearchCV(clf, parameter_space)
grid.fit(X_all, y_true)
print("随机森林(参数组合) Accuracy: {0:.1f}%".format(grid.best_score_ * 100))
#输出用网格搜索找到的佳模型,查看都使用了哪些参数。
print(grid.best_estimator_)
#输出正确率高的模型所用到的参数
'''
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='entropy',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=4, min_samples_split=2,
            min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=1,
            oob_score=False, random_state=14, verbose=0, warm_start=False)
'''
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python与大数据分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档