kaggle(02)-房价预测案例(基础版)
房价预测案例
Step 1: 检视源数据集
import numpy as np
import pandas as pd
读入数据
一般来说源数据的index那一栏没什么用,我们可以用来作为我们pandas dataframe的index。这样之后要是检索起来也省事儿。
有人的地方就有鄙视链。跟知乎一样。Kaggle的也是个处处呵呵的危险地带。Kaggle上默认把数据放在input文件夹下。所以我们没事儿写个教程什么的,也可以依据这个convention来,显得自己很有逼格。。
train_df = pd.read_csv('train.csv', index_col=0)
test_df = pd.read_csv('test.csv', index_col=0)
检视源数据
train_df.head()
# print(train_df.info)
# print(train_df.shape)
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 0x7fbf9f8703c8>,<matplotlib.axes._subplots.AxesSubplot object at 0x7fbf97340400>]],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) #这个根据给出的数据集的描述可知,该属性应该是表示的为级别,但是PD在读取数据的时候会自动将其认为是数字,所以需要转换为字符串
变成str以后,做个统计,就很清楚了
all_df['MSSubClass'].value_counts()
20 1079
60 575
50 287
120 182
30 139
160 128
70 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) #打印出前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) #用每一列的平均值填充每一列中的NAN项
看看是不是没有空缺了?
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(['LotFrontage', 'LotArea', 'OverallQual', 'OverallCond', 'YearBuilt','YearRemodAdd', 'MasVnrArea', 'BsmtFinSF1', 'BsmtFinSF2', 'BsmtUnfSF','TotalBsmtSF', '1stFlrSF', '2ndFlrSF', 'LowQualFinSF', 'GrLivArea','BsmtFullBath', 'BsmtHalfBath', 'FullBath', 'HalfBath', 'BedroomAbvGr','KitchenAbvGr', 'TotRmsAbvGrd', 'Fireplaces', 'GarageYrBlt','GarageCars', 'GarageArea', 'WoodDeckSF', 'OpenPorchSF','EnclosedPorch', '3SsnPorch', 'ScreenPorch', 'PoolArea', 'MiscVal','MoSold', '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))
Ridge Regression
用Ridge Regression模型来跑一遍看看。(对于多因子的数据集,这种模型可以方便的把所有的var都无脑的放进去)
from sklearn.linear_model import Ridge
from sklearn.model_selection import cross_val_score
这一步不是很必要,只是把DF转化成Numpy Array,这跟Sklearn更加配
X_train = dummy_train_df.values
X_test = dummy_test_df.values
用Sklearn自带的cross validation方法来测试模型
alphas = np.logspace(-3, 2, 50)
test_scores = []
for alpha in alphas:clf = Ridge(alpha)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(alphas, test_scores)
plt.title("Alpha vs CV Error");
可见,大概alpha=10~20的时候,可以把score达到0.135左右。
Random Forest
from sklearn.ensemble import RandomForestRegressor
max_features = [.1, .3, .5, .7, .9, .99]
test_scores = []
for max_feat in max_features:clf = RandomForestRegressor(n_estimators=200, max_features=max_feat)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=5, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score))
plt.plot(max_features, test_scores)
plt.title("Max Features vs CV Error");
用RF的最优值达到了0.137
Step 5: Ensemble
这里我们用一个Stacking的思维来汲取两种或者多种模型的优点
首先,我们把最好的parameter拿出来,做成我们最终的model
ridge = Ridge(alpha=15)
rf = RandomForestRegressor(n_estimators=500, max_features=.3)
ridge.fit(X_train, y_train)
rf.fit(X_train, y_train)
RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,max_features=0.3, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, n_estimators=500, n_jobs=1,oob_score=False, random_state=None, verbose=0, warm_start=False)
上面提到了,因为最前面我们给label做了个log(1+x), 于是这里我们需要把predit的值给exp回去,并且减掉那个"1"
所以就是我们的expm1()函数。
y_ridge = np.expm1(ridge.predict(X_test))
y_rf = np.expm1(rf.predict(X_test))
一个正经的Ensemble是把这群model的预测结果作为新的input,再做一次预测。这里我们简单的方法,就是直接『平均化』。
y_final = (y_ridge + y_rf) / 2 #对模型进行融合
Step 6: 提交结果
submission_df = pd.DataFrame(data= {'Id' : test_df.index, 'SalePrice': y_final})
我们的submission大概长这样:
submission_df.head(10)
Id | SalePrice | |
---|---|---|
0 | 1461 | 120284.850938 |
1 | 1462 | 151366.179663 |
2 | 1463 | 174792.133120 |
3 | 1464 | 190099.605945 |
4 | 1465 | 195500.170436 |
5 | 1466 | 175876.563502 |
6 | 1467 | 177675.128914 |
7 | 1468 | 169318.651321 |
8 | 1469 | 184796.699921 |
9 | 1470 | 122328.836416 |
走你~
kaggle(02)-房价预测案例(基础版)相关推荐
- kaggle (02) - 房价预测案例(进阶版)
房价预测案例(进阶版) 这是进阶版的notebook.主要是为了比较几种模型框架.所以前面的特征工程部分内容,我也并没有做任何改动,重点都在后面的模型建造section Step 1: 检视源数据集 ...
- Kaggle实战之 房价预测案例
房价预测案例(进阶版) 这是进阶版的notebook.主要是为了比较几种模型框架.所以前面的特征工程部分内容,我也并没有做任何改动,重点都在后面的模型建造section Step 1: 检视源数据集 ...
- kaggle竞赛--房价预测详细解读
## Kaggle竞赛 -- 房价预测 (House Prices) #### 完整代码见[kaggle kernel](https://www.kaggle.com/massquantity/all ...
- 波士顿房价预测python代码_使用Python和Numpy构建神经网络模型——波士顿房价预测案例...
原标题:使用Python和Numpy构建神经网络模型--波士顿房价预测案例
- 二手房房价预测案例 -- 代码实现
本篇将继续上一篇二手房房价预测案例 -- 基本概念以及模型应用之后进行代码实现,这两部分构成了一个简单的数据分析流程.结合两篇文章通过数据分析和挖掘的方法实现二手房价格预测的预测后,分析报告请看这里. ...
- kaggle—HousePrice房价预测项目实战
房价预测是kaggle官网的一个竞赛项目,算是机器学习的一个入门项目.kaggle官网链接: link. 关于kaggle竞赛项目的操作流程可以参看这篇博客: link. 一.kaggle介绍 kag ...
- 波士顿房价预测(终版讲解)
代码段分四个部分:库的引入.加载数据(函数).配置网络结构(类).运行部分(获取数据,创建网络,启动训练,作图) 我的是基础版,库只用到了numpy和matplotlib的pyplto两个. 加载数据 ...
- 线性回归算法 从认知到实战内含波士顿房价预测案例
文章目录 2.1 线性回归简介 学习目标 1 线性回归应用场景 2 什么是线性回归 2.1 定义与公式 2.2 线性回归的特征与目标的关系分析 3 小结 2.2 线性回归api初步使用 学习目标 1 ...
- Kaggle入门——房价预测
Kaggle比赛 Kaggle是一个著名的供机器学习爱好者交流的平台.图3.7展示了Kaggle网站的首页.为了便于提交结果,需要注册Kaggle账号. 我们可以在房价预测比赛的网页上了解比赛信息和参 ...
最新文章
- CentOS 7 firewall防火墙命令
- vue图片懒加载实例
- 引用另一模板的宏_生信人值得拥有的编程模板Shell
- Linux sed命令实例详解
- 识别出脸部以及给脸部打马赛克
- html中body呈现属性,HTML body 标签
- webComponent初体验
- EXCEL表格超链接图片
- 【排障】为什么你发出去的邮件被退回
- 手机cpu天梯图2020
- win10 无法安全地连接到此页面 TLS安全设置未设置为默认 该怎么办? 无法访问此页面
- 跟领导关系再好,也别做3件小事,嘴欠手贱,煮熟鸭子会飞
- iOS app url scheme跳转到淘宝商品详情页 唤醒app
- 同花顺_代码解析_技术指标_S
- VS2012源代码管理没有AnkhSVN
- 解决更新页面数据回显时时间不匹配问题:The specified value “Fri Nov 05 08:00:00 CST 2021“ does not conform to the requir
- Windows7 GNS3 模拟路由器成功PING通网外
- M1 MacBook 苹果电脑安装brew
- 计算机辅助设计高级绘图员技能鉴定试题,计算机辅助设计高级绘图员技能鉴定试卷.doc...
- 同学,其实你可以不用周游世界……
热门文章
- half-sync/half-async 和 Leader/Followers 模式的主要区别
- 【转】Win10系统创建WiFi热点的两种方法
- !Spring Aop中四个重要概念,切点,切面,连接点,通知
- ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?
- php源码查找替换,php 替换模板中的 PHP源码标签字符方法
- idea中project sdk_一文秒懂IDEA中每天都在用的Project Structure知识
- 【JS 逆向百例】层层嵌套,某加速商城 RSA 加密
- Python 数据分析三剑客之 NumPy(二):数组索引 / 切片 / 广播 / 拼接 / 分割
- linux禁止u盘自动运行,求设置U盘自动运行和禁止运行的方法。
- 【NC51 合并k个已排序的链表】K路归并