房价预测案例(进阶版)

这是进阶版的notebook。主要是为了比较几种模型框架。所以前面的特征工程部分内容,我也并没有做任何改动,重点都在后面的模型建造section

Step 1: 检视源数据集

import numpy as np
import pandas as pd

读入数据

  • 一般来说源数据的index那一栏没什么用,我们可以用来作为我们pandas dataframe的index。这样之后要是检索起来也省事儿。

  • 有人的地方就有鄙视链。跟知乎一样。Kaggle的也是个处处呵呵的危险地带。Kaggle上默认把数据放在input文件夹下。所以我们没事儿写个教程什么的,也可以依据这个convention来,显得自己很有逼格。。

train_df = pd.read_csv('../input/train.csv', index_col=0)
test_df = pd.read_csv('../input/test.csv', index_col=0)

检视源数据

train_df.head()
MSSubClass MSZoning LotFrontage LotArea Street Alley LotShape LandContour Utilities LotConfig ... PoolArea PoolQC Fence MiscFeature MiscVal MoSold YrSold SaleType SaleCondition SalePrice
Id
1 60 RL 65.0 8450 Pave NaN Reg Lvl AllPub Inside ... 0 NaN NaN NaN 0 2 2008 WD Normal 208500
2 20 RL 80.0 9600 Pave NaN Reg Lvl AllPub FR2 ... 0 NaN NaN NaN 0 5 2007 WD Normal 181500
3 60 RL 68.0 11250 Pave NaN IR1 Lvl AllPub Inside ... 0 NaN NaN NaN 0 9 2008 WD Normal 223500
4 70 RL 60.0 9550 Pave NaN IR1 Lvl AllPub Corner ... 0 NaN NaN NaN 0 2 2006 WD Abnorml 140000
5 60 RL 84.0 14260 Pave NaN IR1 Lvl AllPub FR2 ... 0 NaN NaN NaN 0 12 2008 WD Normal 250000

5 rows × 80 columns

这时候大概心里可以有数,哪些地方需要人为的处理一下,以做到源数据更加好被process。

Step 2: 合并数据

这么做主要是为了用DF进行数据预处理的时候更加方便。等所有的需要的预处理进行完之后,我们再把他们分隔开。

首先,SalePrice作为我们的训练目标,只会出现在训练集中,不会在测试集中(要不然你测试什么?)。所以,我们先把SalePrice这一列给拿出来,不让它碍事儿。

我们先看一下SalePrice长什么样纸:

%matplotlib inline
prices = pd.DataFrame({"price":train_df["SalePrice"], "log(price + 1)":np.log1p(train_df["SalePrice"])})
prices.hist()
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0000000009B8DE48>,<matplotlib.axes._subplots.AxesSubplot object at 0x0000000009BF4710>]],dtype=object)

可见,label本身并不平滑。为了我们分类器的学习更加准确,我们会首先把label给“平滑化”(正态化)

这一步大部分同学会miss掉,导致自己的结果总是达不到一定标准。

这里我们使用最有逼格的log1p, 也就是 log(x+1),避免了复值的问题。

记住哟,如果我们这里把数据都给平滑化了,那么最后算结果的时候,要记得把预测到的平滑数据给变回去。

按照“怎么来的怎么去”原则,log1p()就需要expm1(); 同理,log()就需要exp(), … etc.

y_train = np.log1p(train_df.pop('SalePrice'))

然后我们把剩下的部分合并起来

all_df = pd.concat((train_df, test_df), axis=0)

此刻,我们可以看到all_df就是我们合在一起的DF

all_df.shape
(2919, 79)

y_train则是SalePrice那一列

y_train.head()
Id
1    12.247699
2    12.109016
3    12.317171
4    11.849405
5    12.429220
Name: SalePrice, dtype: float64

Step 3: 变量转化

类似『特征工程』。就是把不方便处理或者不unify的数据给统一了。

正确化变量属性

首先,我们注意到,MSSubClass 的值其实应该是一个category,

但是Pandas是不会懂这些事儿的。使用DF的时候,这类数字符号会被默认记成数字。

这种东西就很有误导性,我们需要把它变回成string

all_df['MSSubClass'].dtypes
dtype('int64')
all_df['MSSubClass'] = all_df['MSSubClass'].astype(str)

变成str以后,做个统计,就很清楚了

all_df['MSSubClass'].value_counts()
20     1079
60      575
50      287
120     182
30      139
70      128
160     128
80      118
90      109
190      61
85       48
75       23
45       18
180      17
40        6
150       1
Name: MSSubClass, dtype: int64

把category的变量转变成numerical表达形式

当我们用numerical来表达categorical的时候,要注意,数字本身有大小的含义,所以乱用数字会给之后的模型学习带来麻烦。于是我们可以用One-Hot的方法来表达category。

pandas自带的get_dummies方法,可以帮你一键做到One-Hot。

pd.get_dummies(all_df['MSSubClass'], prefix='MSSubClass').head()
MSSubClass_120 MSSubClass_150 MSSubClass_160 MSSubClass_180 MSSubClass_190 MSSubClass_20 MSSubClass_30 MSSubClass_40 MSSubClass_45 MSSubClass_50 MSSubClass_60 MSSubClass_70 MSSubClass_75 MSSubClass_80 MSSubClass_85 MSSubClass_90
Id
1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
5 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0

此刻MSSubClass被我们分成了12个column,每一个代表一个category。是就是1,不是就是0。

同理,我们把所有的category数据,都给One-Hot了

all_dummy_df = pd.get_dummies(all_df)
all_dummy_df.head()
LotFrontage LotArea OverallQual OverallCond YearBuilt YearRemodAdd MasVnrArea BsmtFinSF1 BsmtFinSF2 BsmtUnfSF ... SaleType_ConLw SaleType_New SaleType_Oth SaleType_WD SaleCondition_Abnorml SaleCondition_AdjLand SaleCondition_Alloca SaleCondition_Family SaleCondition_Normal SaleCondition_Partial
Id
1 65.0 8450 7 5 2003 2003 196.0 706.0 0.0 150.0 ... 0 0 0 1 0 0 0 0 1 0
2 80.0 9600 6 8 1976 1976 0.0 978.0 0.0 284.0 ... 0 0 0 1 0 0 0 0 1 0
3 68.0 11250 7 5 2001 2002 162.0 486.0 0.0 434.0 ... 0 0 0 1 0 0 0 0 1 0
4 60.0 9550 7 5 1915 1970 0.0 216.0 0.0 540.0 ... 0 0 0 1 1 0 0 0 0 0
5 84.0 14260 8 5 2000 2000 350.0 655.0 0.0 490.0 ... 0 0 0 1 0 0 0 0 1 0

5 rows × 303 columns

处理好numerical变量

就算是numerical的变量,也还会有一些小问题。

比如,有一些数据是缺失的:

all_dummy_df.isnull().sum().sort_values(ascending=False).head(10)
LotFrontage     486
GarageYrBlt     159
MasVnrArea       23
BsmtHalfBath      2
BsmtFullBath      2
BsmtFinSF2        1
GarageCars        1
TotalBsmtSF       1
BsmtUnfSF         1
GarageArea        1
dtype: int64

可以看到,缺失最多的column是LotFrontage

处理这些缺失的信息,得靠好好审题。一般来说,数据集的描述里会写的很清楚,这些缺失都代表着什么。当然,如果实在没有的话,也只能靠自己的『想当然』。。

在这里,我们用平均值来填满这些空缺。

mean_cols = all_dummy_df.mean()
mean_cols.head(10)
LotFrontage        69.305795
LotArea         10168.114080
OverallQual         6.089072
OverallCond         5.564577
YearBuilt        1971.312778
YearRemodAdd     1984.264474
MasVnrArea        102.201312
BsmtFinSF1        441.423235
BsmtFinSF2         49.582248
BsmtUnfSF         560.772104
dtype: float64
all_dummy_df = all_dummy_df.fillna(mean_cols)

看看是不是没有空缺了?

all_dummy_df.isnull().sum().sum()
0

标准化numerical数据

这一步并不是必要,但是得看你想要用的分类器是什么。一般来说,regression的分类器都比较傲娇,最好是把源数据给放在一个标准分布内。不要让数据间的差距太大。

这里,我们当然不需要把One-Hot的那些0/1数据给标准化。我们的目标应该是那些本来就是numerical的数据:

先来看看 哪些是numerical的:

numeric_cols = all_df.columns[all_df.dtypes != 'object']
numeric_cols
Index([u'LotFrontage', u'LotArea', u'OverallQual', u'OverallCond',u'YearBuilt', u'YearRemodAdd', u'MasVnrArea', u'BsmtFinSF1',u'BsmtFinSF2', u'BsmtUnfSF', u'TotalBsmtSF', u'1stFlrSF', u'2ndFlrSF',u'LowQualFinSF', u'GrLivArea', u'BsmtFullBath', u'BsmtHalfBath',u'FullBath', u'HalfBath', u'BedroomAbvGr', u'KitchenAbvGr',u'TotRmsAbvGrd', u'Fireplaces', u'GarageYrBlt', u'GarageCars',u'GarageArea', u'WoodDeckSF', u'OpenPorchSF', u'EnclosedPorch',u'3SsnPorch', u'ScreenPorch', u'PoolArea', u'MiscVal', u'MoSold',u'YrSold'],dtype='object')

计算标准分布:(X-X’)/s

让我们的数据点更平滑,更便于计算。

注意:我们这里也是可以继续使用Log的,我只是给大家展示一下多种“使数据平滑”的办法。

numeric_col_means = all_dummy_df.loc[:, numeric_cols].mean()
numeric_col_std = all_dummy_df.loc[:, numeric_cols].std()
all_dummy_df.loc[:, numeric_cols] = (all_dummy_df.loc[:, numeric_cols] - numeric_col_means) / numeric_col_std

Step 4: 建立模型

把数据集分回 训练/测试集

dummy_train_df = all_dummy_df.loc[train_df.index]
dummy_test_df = all_dummy_df.loc[test_df.index]
dummy_train_df.shape, dummy_test_df.shape
((1460, 303), (1459, 303))
X_train = dummy_train_df.values
X_test = dummy_test_df.values

做一点高级的Ensemble

一般来说,单个分类器的效果真的是很有限。我们会倾向于把N多的分类器合在一起,做一个“综合分类器”以达到最好的效果。

我们从刚刚的试验中得知,Ridge(alpha=15)给了我们最好的结果

from sklearn.linear_model import Ridge
ridge = Ridge(15)

Bagging

Bagging把很多的小分类器放在一起,每个train随机的一部分数据,然后把它们的最终结果综合起来(多数投票制)。

Sklearn已经直接提供了这套构架,我们直接调用就行:

from sklearn.ensemble import BaggingRegressor
from sklearn.model_selection import cross_val_score
E:\Anaconda2\soft\lib\site-packages\sklearn\ensemble\weight_boosting.py:29: DeprecationWarning: numpy.core.umath_tests is an internal NumPy module and should not be imported. It will be removed in a future NumPy release.from numpy.core.umath_tests import inner1d

在这里,我们用CV结果来测试不同的分类器个数对最后结果的影响。

注意,我们在部署Bagging的时候,要把它的函数base_estimator里填上你的小分类器(ridge)

params = [1, 10, 15, 20, 25, 30, 40]
test_scores = []
for param in params:clf = BaggingRegressor(n_estimators=param, base_estimator=ridge)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=10, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score))
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(params, test_scores)
plt.title("n_estimator vs CV Error");

可见,前一个版本中,ridge最优结果也就是0.135;而这里,我们使用25个小ridge分类器的bagging,达到了低于0.132的结果。

当然了,你如果并没有提前测试过ridge模型,你也可以用Bagging自带的DecisionTree模型:

代码是一样的,把base_estimator给删去即可

params = [10, 15, 20, 25, 30, 40, 50, 60, 70, 100]
test_scores = []
for param in params:clf = BaggingRegressor(n_estimators=param)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=10, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score))
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(params, test_scores)
plt.title("n_estimator vs CV Error");

咦,看来单纯用DT不太灵光的。最好的结果也就0.140

Boosting

Boosting比Bagging理论上更高级点,它也是揽来一把的分类器。但是把他们线性排列。下一个分类器把上一个分类器分类得不好的地方加上更高的权重,这样下一个分类器就能在这个部分学得更加“深刻”。

from sklearn.ensemble import AdaBoostRegressor
params = [10, 15, 20, 25, 30, 35, 40, 45, 50]
test_scores = []
for param in params:clf = BaggingRegressor(n_estimators=param, base_estimator=ridge)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=10, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score))
plt.plot(params, test_scores)
plt.title("n_estimator vs CV Error");

Adaboost+Ridge在这里,25个小分类器的情况下,也是达到了接近0.132的效果。

同理,这里,你也可以不必输入Base_estimator,使用Adaboost自带的DT。

params = [10, 15, 20, 25, 30, 35, 40, 45, 50]
test_scores = []
for param in params:clf = BaggingRegressor(n_estimators=param)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=10, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score))
plt.plot(params, test_scores)
plt.title("n_estimator vs CV Error");

看来我们也许要先tune一下我们的DT模型,再做这个实验。。?

XGBoost

最后,我们来看看巨牛逼的XGBoost,外号:Kaggle神器

这依旧是一款Boosting框架的模型,但是却做了很多的改进。

from xgboost import XGBRegressor

用Sklearn自带的cross validation方法来测试模型

params = [1,2,3,4,5,6]
test_scores = []
for param in params:clf = XGBRegressor(max_depth=param)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=10, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score))

存下所有的CV值,看看哪个alpha值更好(也就是『调参数』)

import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(params, test_scores)
plt.title("max_depth vs CV Error");

惊了,深度为5的时候,错误率缩小到0.127

这就是为什么,浮躁的竞赛圈,人人都在用XGBoost ?


kaggle (02) - 房价预测案例(进阶版)相关推荐

  1. kaggle(02)-房价预测案例(基础版)

    房价预测案例 Step 1: 检视源数据集 import numpy as np import pandas as pd 读入数据 一般来说源数据的index那一栏没什么用,我们可以用来作为我们pan ...

  2. Kaggle实战之 房价预测案例

    房价预测案例(进阶版) 这是进阶版的notebook.主要是为了比较几种模型框架.所以前面的特征工程部分内容,我也并没有做任何改动,重点都在后面的模型建造section Step 1: 检视源数据集 ...

  3. kaggle竞赛--房价预测详细解读

    ## Kaggle竞赛 -- 房价预测 (House Prices) #### 完整代码见[kaggle kernel](https://www.kaggle.com/massquantity/all ...

  4. 波士顿房价预测python代码_使用Python和Numpy构建神经网络模型——波士顿房价预测案例...

    原标题:使用Python和Numpy构建神经网络模型--波士顿房价预测案例

  5. 二手房房价预测案例 -- 代码实现

    本篇将继续上一篇二手房房价预测案例 -- 基本概念以及模型应用之后进行代码实现,这两部分构成了一个简单的数据分析流程.结合两篇文章通过数据分析和挖掘的方法实现二手房价格预测的预测后,分析报告请看这里. ...

  6. Kaggle实战入门:泰坦尼克号生还预测(进阶版)

    Kaggle实战入门:泰坦尼克号生还预测 1. 加载数据 2. 特征工程 3. 模型训练 4. 模型部署 Kaggle实战入门:泰坦尼克号生还预测(基础版)对机器学习的全流程进行了总体介绍.本文继续以 ...

  7. kaggle—HousePrice房价预测项目实战

    房价预测是kaggle官网的一个竞赛项目,算是机器学习的一个入门项目.kaggle官网链接: link. 关于kaggle竞赛项目的操作流程可以参看这篇博客: link. 一.kaggle介绍 kag ...

  8. 线性回归算法 从认知到实战内含波士顿房价预测案例

    文章目录 2.1 线性回归简介 学习目标 1 线性回归应用场景 2 什么是线性回归 2.1 定义与公式 2.2 线性回归的特征与目标的关系分析 3 小结 2.2 线性回归api初步使用 学习目标 1 ...

  9. Kaggle入门——房价预测

    Kaggle比赛 Kaggle是一个著名的供机器学习爱好者交流的平台.图3.7展示了Kaggle网站的首页.为了便于提交结果,需要注册Kaggle账号. 我们可以在房价预测比赛的网页上了解比赛信息和参 ...

最新文章

  1. 【送书福利8本】YYDS《剑指Offer》,百万程序员人手一册
  2. IIS不能发布asp.net 应用程序
  3. MVC HtmlHelper扩展——实现分页功能
  4. 我有一个朋友毕业后一直在腾讯
  5. java并发线程池---了解ThreadPoolExecutor就够了
  6. 《剑指offer》面试题24——二叉搜索树的后序遍历序列(C++)
  7. 刚刚,Google 官方发布了 2 份编程指南,干货十足!
  8. YACC (Yet Another Compiler Compiler)
  9. wepy集成colorui 样式框架
  10. AD软件——设计总结(差分布线,蛇形布线)
  11. 逆水寒7.25服务器维护,逆水寒7月4日更新维护公告 角色交易功能上线
  12. 中南大学计算机博士就业,求救!中南大学博士毕业要求
  13. 网线哪几根是发送数据,哪几根是接收数据的?
  14. 2021年十佳优惠券返利APP排名榜 2021年用户喜欢的优惠券返利APP前10排行榜
  15. Use // eslint-disable-next-line to ignore the next line.Use /* eslint-disable */ to ignore all解决
  16. 服务器虚拟多个终端,虚拟化终端新主流 支持多操作系统
  17. PyTorch 入门:训练一个深度神经网络(DNN)
  18. 用GRUB2来实现——坎特伯雷项目 The Canterbury Project
  19. ICV报告:中国的数字经济与5G市场研究报告
  20. EOS版truffle测试框架js4eos上线了,合约一键自动化测试

热门文章

  1. Window CE 6.0流驱动开发动态加载实验
  2. 十六进制除法运算法则_苏教版数学七年级上册 微课视频 2.6 有理数的乘法与除法(1)...
  3. 练字格子纸模板pdf_高考英语作文模板(总结八种常考题型,配合例文,纯手打的)...
  4. 中职计算机属于专业课还是文化课,对中职计算机专业建设探讨.doc
  5. 智能机器人及其应用ppt课件_一文了解!伺服系统机理及其在工业机器人等领域的应用...
  6. 使用 Syslog 连接外部解决方案
  7. SharePoint 2013开发入门探索(二)- 列表操作
  8. C#中 ??、 ?、 ?: 、?.、?[ ]、:
  9. 浅谈Mysql 表设计规范
  10. Java 中创建对象方式