使用sklearn进行数据挖掘-房价预测(5)—训练模型

使用sklearn进行数据挖掘系列文章:

在前几节,我们先对数据进行了解,然后又详细介绍了数据集划分的方法,为了帮助我们更好的了解数据,又绘制了数据的分布图,之后对数据进行了预处理(数值类型和标签类型特征的处理)。上面这些步骤都是一些基础工作,本节将介绍选择和构建机器学习模型。

在测试集上面训练模型###

经验告诉我们,在使用机器学习算法的时候,一开始先选用简单的模型,撸一个baseline是一个很好的习惯。所以我们先尝试使用线性回归模型,先使用几个样本尝试以下该分类器:

from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(housing_prepared,housing_labels)
some_data = housing.iloc[:5]
some_labels = housing_labels.iloc[:5]
some_data_preared = full_pipeline.transform(some_data)
print 'prediction:',lin_reg.predict(some_data_preared)
print 'labels:',some_labels.values
>>
prediction: [ 210644.60459286  317768.80697211  210956.43331178   59218.9888684  189747.55849879]
labels: [ 286600.  340600.  196900.   46300.  254500.]

不错,看来我们之前的一些预处理工作和分类器都能正常运行。那么我们该如何衡量我们的算法的好坏呢?
,sklearn提供了root mean squared error,RMSE作为评价指标:

from sklearn.metrics import mean_squared_error #

housing_predictions = lin_reg.predict(housing_prepared)
lin_mse = mean_squared_error(housing_labels,housing_predictions)
lin_rmse = np.sqrt(lin_mse) #平方根
print lin_rmse
>>
68628.1981985

从第一节housing.describe()中我们知道median_housing_values的范围为14W-50W ,着也意味着分类器欠拟合训练数据,我们需要做的是找一个能力更加强大的分类器或者减少对模型的约束。尝试以下非线性回归模型DecisionTreeRegressor,回归决策树能够找出复杂的非线性关系,下面是代码

from sklearn.tree import DecisionTreeRegressor 
tree_reg = DecisionTreeRegressor()
tree_reg.fit(housing_prepared,housing_labels)

housing_predictions = tree_reg.predict(housing_prepared)
tree_mse = mean_squared_error(housing_labels,housing_predictions)
tree_rmse = np.sqrt(tree_mse)
>>print tree_rmse
0.0

误差竟然为0,实际上可能发生了严重的过拟合。那么问题来了,我们该如何分析结果到底是欠拟合还是过拟合呢?下面就引入了交叉验证

交叉验证###

由于目前我们的测试集是不能动的,因为还没到确定最终的模型。我们可以把训练集再划分为训练集和测试集两部分。我们可以使用前面提到的train_test_split方法,不过强大的sklearn还提供了K-fold交叉验证方法:

from sklearn.model_selection import cross_val_score
scores = cross_val_score(tree_reg,housing_prepared,
        housing_labels,scoring='neg_mean_squared_error',cv=10)
rmse_scores = np.sqrt(-scores)

上面这段代码将训练集随机的分为10份,在9份上面训练,在剩下的一份上面测试。

>>rmse_scores 
array([ 69080.4167045 ,  67652.35297369,  70592.30099278,  67905.0445584 ,
        71256.61551091,  74264.47020443,  70141.37468916,  71525.02444872,
        76283.57397045,  69691.77150094])
>>rmse_scores.mean()
70839.294555398083
>>rmse_scores.std()
2564.0079357717691

note:sklearn提供的交叉验证方法希望得到一个较大的值(越大越好),这个和损失函数正好相反(越小越好),所以使用的是-score
看到了上面的结果,发现决策是的效果其实很一般,甚至还没有线性回归的结果好(增加了3K)。
现在看以下线性回归的交叉验证值

lin_scores = cross_val_score(lin_reg,housing_prepared,
            housing_labels,scoring='neg_mean_squared_error',cv=10)
lin_rmse_scores = np.sqrt(-lin_scores)
>>lin_rmse_scores 
array([ 66782.73843989,  66960.118071  ,  70347.95244419,  74739.57052552,
        68031.13388938,  71193.84183426,  64969.63056405,  68281.61137997,
        71552.91566558,  67665.10082067])
>>lin_rmse_scores.mean()
69052.461363450828
>>lin_rmse_scores.std()
2731.6740017983493

使用随机森林(RandomForestRegression)

from sklearn.ensemble import RandomForestRegressor
forest_reg = RandomForestRegressor()
forest_reg.fit(housing_prepared, housing_labels)
housing_predictions = forest_reg.predict(housing_prepared)
forest_mse = mean_squared_error(housing_labels, housing_predictions)
forest_rmse = np.sqrt(forest_mse)
print forest_rmse #22180.0543101
forest_scores = cross_val_score(forest_reg, housing_prepared, housing_labels,
                                scoring="neg_mean_squared_error", cv=10)
forest_rmse_scores = np.sqrt(-forest_scores)
>>forest_rmse_scores 
array([ 52036.18016789,  51138.17643755,  54179.12437821,  53870.89837397,
        52413.73419948,  55299.52908533,  51322.32440328,  50743.46362248,
        55491.68139413,  52746.07818231])
>>forest_rmse_scores.mean() #结果大于22180。说明训练集存在过拟合
52924.119024463616
>>forest_rmse_scores.std()
1621.653495429834

上面列举了使用线性回归、决策树回归和随机森林回归的方法。可以看的出随机森林的效果最好,如果你想还可以继续尝试其他的算法比如SVR、神经网络等,找出效果较好的模型。