机器学习案例之二 房价预测

房价预测案例

检视源数据集

import numpy as np
import pandas as pd
读入数据
  • 一般来说index那一栏没有什么用,我们用来作为我们pandas dataframe的index。这样以后要是检索起来也很方便
  • Kaggle上默认数据放在input文件夹下。
train_df=pa.read_csv('../input/train.csv',index_col=0)
test_df=pd.read_csv('../input/test.csv',index_col=0)
检视数据源
train_df.head()

pandas默认给出前五行
NAN不考虑
文本转化为数字

step 2 合并数据

将train集和test集合并起来,这么做主要是为了用DF进行数据预处理的时候回方便。等所有的需要的预处理进行完成后,我们再把他们分开
首先,SalePrice作为我们的训练目标,只会出现在训练集中,不会出现在测试集中。所以,我们先把SalePrice这一列拿出来。
我们先看一下SalePrice长什么样子

%matplotlib inline
prices=pd.DataFrame({"price":train_df['SalePrice'],"log(price+1)":np.loglp(train_df["SalePrice"]})
prices.hist()   

这里写图片描述
可见,我们的label本身并不平滑(分布为高斯分布)。为了我们分类器的学习更加准确,我们会把label给“平滑掉”(正态化)(回归问题需要平滑,分类问题不需要平滑)。
这一步大多数同学都会Miss掉,导致自己的结果总是达不到一定标准。
这里我们使用log1p,也就是log(X+1)(防止x为0),避免了复值的问题。
如果我们这里把数据都给平滑化了,那么最后算结果的时候,得把预测到的平滑数据变回去。
按照“怎么来的就怎么回去”原则,log1p()就需要expm1();同理,log()就需要exp()

y_train=np.log1p(train_df.pop["SalePrice"])    

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

all_df=np.contact((train_df,test_df),axis=0)
all_df.shape()  

y_train是“SalePrice”那一列

y_train.head()   
step3 变量转化

类似特征工程,就是把不方便处理或者不unify的数据给统一了。
正确化变量属性
首先,我们注意到,MSSubClass的值其实是一个category(无数值大小之分),
使用DF时,这类数字会被默认记成数字。
这种东西很有误导性,我们需要把它变回成string。

all_df["MSSubClass"].dtypes 
all_df["MSSubClass"]=all_df["MSSubClass"].astype("str")  

变成string之后,做个统计就很清楚了。

all_df["MSSubClass"].value_counts()

把category的变量转变成numerical表达形式
当我们用numerical来表达categorical的时候,要注意,数字本身有大小的含义,所以乱用数字后给模型学习带来麻烦。于是我们用one-hot的方法表达category。
pandas自带的get_dummies方法,可以帮你一键做到one-hot。

pd.get_dummies(all_df["MSSubClass"],prefix='MSSubClass').head()

此刻MSSubClass就被分成12个column,每一个代表一个category。是就是1,不是就是0。
同理,我们把所有的category数据,都给one-hot了。

all_dummy_df=pd.get_dummies(all_df)%自动选取category的拓展
all_dummy_df.head()

处理好numerical变量
就算是numerical变量,也是有一些小问题,
比如,有一些数据是缺失的

all_dummy_df.isnull().sum().sort_values(ascending=False).head()

处理这些缺失信息,得靠审题。一般来说,数据集的描述里会写的很清楚,这些缺失值都代表什么。当然,如果实在没有的话,也只能靠自己的“想当然”。
在这里,我们用平均值(0,中位数,最大值,最小值)来填满这些空缺。

mean_cols=all_dummy_df.mean()
mean_cols.head(10)
all_dummy_df=all_dummy_df.fillna(mean_cols)

看看是不是没空缺了。
NAN表示空缺

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

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

这里我们当然不需要吧One-Hot的那些0/1给标准化了。我们的目标是那些本来就是numerical的数据:
先来看看哪些本身是numerical的:

numeric_cols=all_df.columns[all_df.dtypes!='object']
numeric_cols

计算标准分布:(X-X‘)/s
让我们的数据点更加平滑,更便于计算。
注意:这里也可以使用log。

numeric_cols_means=all_dummy_df.loc[:,numeric_cols].mean()
numeric_cols_std=all_dummy_df.loc[:,numeric_cols].std()
all_dummy_df.loc[:,numeric_cols]=(all_dummy_df.loc[:,numeric_cols]-numeric_cols_means)/numeric_cols_std

step 4 建立模型
把数据分回训练/测试集

bummy_train_df=all_dummy_df.loc[train_df.index]
bummy_test_df=all_dummy_df.loc[test_df.index]
bummy_train_df.shape,dummy_test_df.shape

Ridge Reggression
用ridge reggression模型来跑一遍看看。(对于多因子的数据集,这种模型可以方便的把所有的var都无脑的放进去)

from sklearn.linear_model import Ridge
from sklearn.model_selection import cross_val_score

这一步不是很有必要,只要把DF转化成Numpy Array,这跟Sklearn更加匹配。

X_train=bummy_train_df.values
X_test=bummy_test_df.values

用sklearn自带的cross validation(可以减少数据中噪声的影响)方法来测试模型

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值,看那个更好(也就是调参数)

import matplotlib.pyplot as plt
plt.plot(alphas,test_scores)
plt.title("Alpha vs cv Error")

Random Forest

from sklearn.ensemble import RandomForestReggressor
max_featrues=[.1,.3,.5,.7,.9,.99]%每棵树看到的特征占总特征的比例
test_scores=[]
for max_feat in max_featrues:
    clf=RandomForestReggressor(n_estimator=200,max_features,max_feat)
    test_score=np.sqrt(-cross_val_score(clf,X_train,y_train,cv=5,score="neg_mean_squared_error"))
    test_scores.append(np.mean(test_score))
plt.plot(max_featrues,test_scores)
plt.title("Max Featrues vs cv Error")

step 5:Ensemble
这里我们用一个Stacking的思维来汲取两种或者多种模型的优点
首先,我们把最好的parameter拿出来,做成我们最终的model

ridge=Ridge(alpha=15)
rf=RandomForestReggressor(n_estimators=500,max_features=.3)
ridge.fix(X_train,y_train)
rf.fix(X_train,y_train)

上面提到了,因为最前面我们给label做了个log(1+x),于是我们要把predict的值给exp回去,并且减掉“1”
所以就是我们的expm1()函数

y_rigde=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(da={'Id':test_df.index,'SalePrice':y_final})

房价预测进阶版

前面的特征工程没有改动,重点在后面的模型Ensemble

高级的Ensemble
一般来说,单个分类器的效果真的是很有限的。我们会倾向于把N多的分类器和在一起,做一个“综合分类器”以达到最好的效果。
我们从刚刚的实验中得知,Ridge(alpha=15)给了我们最好的结果

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

Bagging
Bagging把很多的小分类器放在一起,每个train随机的一部分数据,然后把他们最终的结果综合起来(多数投票机制)。
Sklearn已经直接提供了这套架构,我们直接调用:

from sklearn.ensemble import BaggingRegrssor%分为BaggingRegrssor,%BaggingClassifier
from sklearn.model_selection import cross_val_score

在这里,我们用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
plt.plot(params,test_scores)
plt.title("n_estimators vs cv Error")

如果你并没有提亲测试过ridge模型,你也可以用Bagging自带的DecisionTree模型。
代码一样,就是把base_estimator删去。

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

from sklearn.ensemble import AdaBoostRegressor
test_scores=[]
params=[10,15,20,25,30,40]
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_estimators vs cv Error")    

这里写图片描述
不稳定,可以调更小的cv。希望为个V型
也可以使用AdaBoost自带的DecisionTree。

XGBoost

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))
plt.plot(params,test_scores)
plt.title("n_estimators vs cv Error")  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值