波士顿房价预测python决策树_机器学习·波士顿房价预测模型

模型评估与验证

当我们的机器学习模型建立好之后,如何训练数据以获得最优的模型参数,又用什么指标来评价模型的优劣呢?本文以波士顿房价为例,说明如何训练数据以及对模型做评估,辨别模型的优劣。

第一步:导入数据

将数据的Features和Values分开,以便后续步骤可以分开使用(训练时只使用Features,验证时二者都要使用)。数据集来自[UCI机器学习知识库]。

import pandas as pd

import numpy as np

import visuals as vs

data = pd.read_csv('housing.csv')

features = data.drop('MEDV',axis=1)

prices = data['MEDV']

print data.head()

下面是运行结果

RM LSTAT PTRATIO MEDV

0 6.575 4.98 15.3 504000.0

1 6.421 9.14 17.8 453600.0

2 7.185 4.03 17.8 728700.0

3 6.998 2.94 18.7 701400.0

4 7.147 5.33 18.7 760200.0

数据解释如下:

RM表示该地区中每个房屋的平均房间数量;

LTSAT表示有多少百分比的业主属于低收入阶层;

PARATIO表示该地区的中学和小学里,学生和老师的数目比(学生/老师);

MEDV表示当地的房价。

其中RM,LTSAT,PARATIO三个是Features,MEDV是我们需要预测的Values。

第二步:分析数据

特征观察,观察数据,分析每个变量与预测值之间的关系(正相关,负相关);

将数据分割为训练集(train set)和验证集(validation set),使用以下方法:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(features, prices, test_size=0.2,random_state=1)

print X_train.head()

下面是运行结果

RM LSTAT PTRATIO

307 6.382 10.36 18.4

58 6.145 6.86 19.7

424 6.406 19.52 20.2

78 6.232 12.34 18.7

439 5.976 19.01 20.2

下面来解释train_test_split()中的用到的参数:

features 表示数据中的‘特征’,在第一步中已经划分为单独的变量

prices 表示数据的‘值’,在第一步中已经划分为单独的变量

test_size 是0~1之间的数字,表示使用多少数据进行验证,如test_size=0.2表示使用20%的数据进行验证,使用80%的数据进行训练

random_state 表示是否随机划分训练集与测试集,若ransom_state=0,则会随机划分测试集与训练集。随机划分的结果就是会使每次训练的分数不同,程序每运行一次,训练分数就会变化。若使random_state =1(或其他非零数),则无论程序运行多少次,分数都是相同的。

训练集会把特征和结果同时给到模型,让模型找到一个可以比较好的拟合参数,训练集的目的就是就是使模型的Features和Values尽可能的拟合。

验证集只会把特征给到模型,模型会产生预测值,再将预测值与实际值相比较,通过得分(第三步会涉及到)判定模型对于验证集的拟合情况,来看模型的好坏。

模型对于数据的拟合情况不好,可以分为两类:过拟合与欠拟合,这两种情况在后文中会涉及。

第三步:模型衡量标准

本例中的房价预测属于回归问题,要判断模型预测值与实际值的拟合程度,可以使用**R2**分数进行评价。R2是决定系数(coefficient of determination),在统计学中,它表征回归方程多大程度上解释了因变量的变化,可用来表示表示对模型拟合程度的好坏,其取值范围是0~1,R2等于1表示模型可以100%解释目标值变化,R2等于0表示模型完全不能解释目标值的变化,下面是R2分数的推导过程:

1.Sum of square due to error(残差平方和):

对于第i个观察点,真实数据

与估算出的

之间的差称为第i个残差(residual),SSE就是所有点的残差的和。

2.Total sum of squares(总平方和):

SST的值与数据的方差(variance)成比例。

3.Sum of squares due to regression(回归平方和):

从公示可以看出他们的关系:

R2决定系数是判断回归方程的拟合程度,假设R2 = 0.6,表示房价60%的变化是模型可以解释的,其余40%模型无法解释,

用代码计算R2分数:

from sklearn.metrics import r2_score

def performance_metric(y_true,y_predict):

'''计算实际值与预测值的R2分数'''

score = r2_score(y_true,y_predict)

return score

第四步 分析模型表现

使用决策树回归算法,控制算法的max_depth参数,得到不同的学习曲线。

vs.ModelLearning(X_train,y_train)

当max_depth=1时,训练集和验证集的分数都比较低,此时模型欠拟合;

当max_depth=3时,随着训练样本数的增加,Training Score与Validation Score不断接近,R2分数稳定在0.8左右,说明模型拟合情况较好;

当max_depth=10时,Training Score接近1.0,而Validation Score只有0.7左右,此时模型过拟合。

欠拟合

欠拟合表示模型对训练集和验证集的拟合程度都比较低,本例中表现为其R2分数都比较低。

欠拟合表示模型虽然有充足的数据,但因不够复杂而无法捕捉到基本关系,模型会一直错误地表示数据,解决欠拟合的方法有:

– 使用更多特征训练数据

– 更改模型

过拟合

过拟合表示数据过于追求队训练集每一个点方差最小,而泛化能力不强,在验证集上表现较差。其表现就是训练集的R2分数较高,而验证集的R2分数较低。过拟合的可以理解为模型对数据过于关心,会推断出一些在数据实际中并不存在的关系,通常因为模型过于复杂或没有足够的数据训练,解决过拟合的方法有:

– 使用更多的数据进行训练

– 限制模型的复杂度

复杂度曲线

vs.ModelComplexity(X_train,y_train)

从上图的复杂度曲线可以看出,max_depth = 5时,Validation Score最高。当最大深度为1时训练模型,Training Score和Validation Score都较低,出现了欠拟合的情况,模型出现了比较大的偏差(bias);以最大深度为10训练模型,Tarining Score较高而Validation Score较低,模型出现过拟合的情况,有比较大的方差(variance)。

训练误差与测试误差相差较远时(训练集R2分数较高,而验证集R2分数较低),模型有方差(variance),方差较大表示模型过拟合。

训练误差与测试误差相差都比较大时(训练集与验证集R2分数都较低),模型有偏差(bias),偏差较大表示模型欠拟合。

为了权衡模型的偏差(bias)与方差(variance),观察图中Tarin Score与Validation Score,我们认为Max_depth=5时模型拟合度最好。

第五步 选择最优参数

在上一步中,我们从复杂度曲线可以看出,max_depth=5时拟合程度最好仅是我们观察得出的猜测,如何计算出模型的最优参数(max_depth=5)呢?计算得出的结论是否与我们的猜测一致呢?

网格搜索(Grid Search)

本例我们使用网格搜索来寻找最优参数。网格搜索类似于穷举法,会将全部参数计算一遍,并根据评分方法(R2分数)计算得分,最后找出最优的参数。本例的参数是max_depth。

交叉验证

本例使用k折交叉验证(k-fold cross-validation)。k折交叉验证法是将数据集分为k个相等的部分,k-1份作为训练集,1份作为验证集,这个过程会进行k次,然后会计算每个参数(max_depth=1~10)的R2分数,并对k次结果取平均数,然后找出R2分数最高的一个参数。

GridSearchCV的cv_result属性可以看到,k折交叉验证中每个split在不同max_depth下Training Score和test Score。下面的代码是使用决策树算法训练模型,使用10折交叉验证,使用网格搜索法,以找到最佳的max_depth。

from sklearn.model_selection import GridSearchCV

from sklearn.model_selection import KFold

from sklearn.tree import DecisionTreeRegressor

from sklearn.metrics import make_scorer

def fit_model(X,y):

cross_validator = KFold(n_splits=10,shuffle=False) #使用10折交叉验证

regressor = DecisionTreeRegressor()

params = {'max_depth':[1,2,3,4,5,6,7,8,9,10]}

scoring_fnc = make_scorer(score_func = performance_metric)

grid = GridSearchCV(estimator = regressor,

param_grid = params,

scoring = scoring_fnc,

cv = cross_validator)

grid = grid.fit(X,y) #基于数据X,y进行网格搜索

return grid.best_estimator_ #返回网格搜索后的最优模型

optimal_reg = fit_model(X_train,y_train) #使用数据对模型进行训练,找出最优参数

print 'The best parameter is max_depth={}'.format(optimal_reg.get_params()['max_depth'])

代码输出:

The best parameter is max_depth=4

GridSearchCV参数

cross_validator参数表示使用的交叉验证方法,本例中定义为10折交叉验证,默认为3折交叉验证;

regressor参数表示使用的回归函数,本例使用决策树回归;

params参数表示要使用交叉验证的参数,本例中的参数为决策树的最大深度(max_depth)使用字典表示;

scoring_fnc表示评分函数,本例使用R2分数

从结果来看,使用网格搜索所得出的最优参数是max_depth=4。

第六步 做出预测

我们已经训练好一个模型,现在我们想知道模型的预测能力怎样,使用在第二步分割好的X_test与y_test对模型的预测能力评分。

predicted_test = optimal_reg.predict(X_test) #将X_test放入模型进行预测,并将预测结果放在变量predicted_test中

test_set_scoring = performance_metric(predicted_test,y_test) #将预测值predicted_test与实际值y_test计算R2分数

print 'The test set score is {}'.format(test_set_scoring)

代码输出:

The test set score is 0.740662174161

最终测试集R2分数为0.74。这个分数表示,房价74%的价格模型可以解释,还有26%的房价模型无法解释。

总结

本文以波士顿房价数据为例,先将数据集分割,分割为训练集与验证集,同时将Features与Values分开,再进一步确定要使用的模型评分标准,本例中使用R2分数,然后使用了决策树回归算法(当然这个算法不是重点啦),以决策树的最大深度max_depth作为参数,得出在参数取不同值时的模型表现,接着使用训练集训练数据,并做交叉验证,找出了R2分数最高的参数,这个参数就是我们想要的结果。

你可能感兴趣的:(波士顿房价预测python决策树_机器学习·波士顿房价预测模型)