决策树学习之概念理解和代码实现

前言:
在学习《python数据挖掘入门与实践》的决策树球队预测后,为了更好的了解决策树学习,我又阅读了李航老师的《统计学习方法》决策树章节内容。这本书被许多大神极力推荐,我在阅读后也发现确实不负盛名。我将在这做个小结,希望能够起到引导作用。

什么是决策树?
决策树是一种基本的分类和回归方法,这里主要讨论分类决策树。举个例子,你和一个女生能不能在一起是个分类问题,它包括能在一起与不能在一起。这里有两个特征,你喜欢她,她喜欢你。这两个特征都有两个值喜欢与不喜欢。
它的本质是从训练数据集中归纳出一组分类规则。他不断地选择最优特征,并根据该特征对数据集进行分割,使得数据集在原有基础上有一个最好的分类。
这里写图片描述

决策树学习分为几个步骤?
决策树学习分为特征选择,决策树的生成和决策树的剪枝三个步骤。算法实现主要有ID3、C4.5和CART。

一组数据集有多少决策树?
从另一个角度看,决策树学习是由训练数据集估计条件概率模型,基于特征空间划分的类的条件概率模型有无数个。我们选择的标准是:该决策树对训练数据集有很好的拟合,而且它要对未知数据有很好的预测。

怎么选择特征?
特征选择的准则通常是考虑信息增益或信息增益比,例如上面例子,你喜欢她,她喜欢你两个特征哪个特征更能决定在不在一起。信息增益或者信息增益比就是决定的度量。公式将在副文实现。

怎么生成决策树?
决策树的生成算法有ID3,C4.5和CART。ID3的核心是在各个结点应用信息增益选择特征,递归的构建决策树。而C4.5是ID3的改进,它应用信息增益比。CART算法生成决策树就是递归的构建二叉决策树的过程。

为什么要进行剪枝?
决策树生成算法依赖于训练数据集,对于训练数据集会有很好的分类,但是对于未知的测试数据却不尽人意,这是过拟合现象。简而言之就是你构建的决策树太复杂啦,细分的过分。

怎么进行决策树剪枝?
在决策树学习中将已生成的树进行简化的过程就叫剪枝。决策树的剪枝往往通过极小化决策树整体的损失函数来实现。剪枝算法不尽相同,同样我会在副文实现一部分。

代码:
在学完《统计学习方法》决策树部分后,我实现了书上的一些公式。当然,我希望你在实现这些代码前要先看书了解内容。

'''
本文件用来算法实现,传入参数即可计算
'''

#1.决策树特征选择准则之经验熵
from collections import defaultdict
def get_entropy(dataset):
'''
dataset是dataframe数据集
'''

lable_count = defaultdict(int)#储存某个离散随机变量X(类别)的频数
num_lables = 0
for index,row in dataset.iterrows():
current_lable = row[df.columns[-1]]#取最后一列的
lable_count[current_lable] += 1
num_lables += 1
#返回熵只依赖于X的分布,熵越大,随机变量的不确定性越大
base_entropy = sum([-lable_count[key]/num_lables*log(lable_count[key]/num_lables,2) for key in lable_count])
return base_entropy
#2.决策树特征选择准则之经验条件熵
def get_conditional_entropy(dataset,feature,feat_value_list):
'''
feature是所选特征
feat_value_list是该特征的数值列表
'''

#按所取特征的值将数据集分开,分为各个dataset
condition_ent = 0.0
for value in feat_value_list:
copy_dataset = dataset.copy()#复制一个dataset
#下面返回feature列中其值为value的所有行
current_dataset = copy_dataset[copy_dataset[feature].isin(value)]
prob = len(current_dataset) / float(len(dataset))#极大似然估计概率
condition_ent += prob * get_entropy(current_dataset)#条件熵计算
return condition_ent
#3.决策树特征选择准则之计算信息增益
def get_information_gain(dataset,feature):
base_entropy = get_entropy(dataset)
feat_value_list = [row[feature] for row in dataset]
unique_values = set(feat_value_list)#转换成集合消除同值
condition_entropy = get_conditional_entropy(dataset,feature,unique_values)
information_gain = base_entropy - condition_entropy
return information_gain
#4.决策树特征选择准则之计算信息增益比
def get_inforgain_ratio(dataset,feature):
information_gain_radio = get_information_gain(dataset,feature) / get_entropy(dataset)
return information_gain_radio

最后:
如果你要学习怎么用决策树,可以阅读《python数据挖掘入门与实践》决策树部分。数据集在上篇博客以下是示例代码:

import pandas as pd
import numpy as np
import os
filename = 'D:\\Python\\PythonProject\\nba_decisiontree_test\\matches.csv'
dataset = pd.read_csv(filename)
#数据清洗
del dataset['Unnamed: 0']
del dataset['1']
del dataset['8']
dataset.columns = ['Visitor Team','VisitorPts','Home Team','HomePts','Ccore Type','OT?','Notes']
#构造新特征
dataset['HomeWin'] = dataset['VisitorPts'] < dataset['HomePts']
y_true = dataset['HomeWin'].values#y_true列表存储赛况结果(输赢类别)
from collections import defaultdict
won_last = defaultdict(int)#创建默认字典,默认值为0,即失败
#dataframe增加新列
dataset['HomeLastWin'] = ''
dataset['VisitorLastWin'] = ''
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]#先储存为0
dataset.ix[index] = row#立马更新进dataframe
won_last[home_team] = row['HomeWin']#在字典内存储这一次循环到的赛况,下一次循环再更新
won_last[visitor_team] = not row['HomeWin']
#使用决策树
from sklearn.tree import DecisionTreeClassifier
from sklearn.cross_validation import cross_val_score
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))
#创建不同的特征
data_folder = 'D:\\Python\\PythonProject\\nba_decisiontree_test'
standing_filename = os.path.join(data_folder,'standing.csv')
standings = pd.read_csv(standing_filename)
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']
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'
#standings[standings['Team'] == home_team]返回home_team在standings的行
home_rank = standings[standings['Team'] == home_team]['Rk'].values
visitor_rank = standings[standings['Team'] == visitor_team]['Rk'].values
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('Accuracy:{0:.1f}%'.format(np.mean(scores)*100))
#再次增加新特征(上一场对战胜负)
last_match_winner = defaultdict(int)
dataset['HomeTeamWinLast'] = 0
for index,row in dataset.iterrows():
home_team = row['Home Team']
visitor_team = row['Visitor Team']
teams = tuple(sorted([home_team,visitor_team]))#排序,确保两支球队无论主客场作战,都使用相同的键
row['HomeTeamWinLast'] = 1 if last_match_winner[teams] == row['Home Team'] else 0
dataset.ix[index] = row
winner = row['Home Team'] if row['HomeWin'] else row['Visitor Team']
last_match_winner[teams] = winner
X_lastwinner = dataset[['HomeTeamRanksHigher','HomeTeamWinLast']].values
clf = DecisionTreeClassifier(random_state=14)
scores = cross_val_score(clf,X_lastwinner,y_true,scoring='accuracy')
print('Accuracy:{0:.1f}%'.format(np.mean(scores)*100))

———关注我的公众号,一起学数据挖掘————
这里写图片描述

扫描二维码关注公众号,回复: 1534930 查看本文章

猜你喜欢

转载自blog.csdn.net/crozonkdd/article/details/79452113