高端织梦html5网站模板 dedecms网络公司模板,wordpress 改网址,wordpress7牛云插件,网站规划设计方案房价预测案例
Step 1: 检视源数据集
import numpy as np
import pandas as pd读入数据 一般来说源数据的index那一栏没什么用#xff0c;我们可以用来作为我们pandas dataframe的index。这样之后要是检索起来也省事儿。 有人的地方就有鄙视链。跟知乎一样。Kaggle的也是个处…房价预测案例
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_col0)
test_df pd.read_csv(test.csv, index_col0)检视源数据
train_df.head()
# print(train_df.info)
# print(train_df.shape)MSSubClassMSZoningLotFrontageLotAreaStreetAlleyLotShapeLandContourUtilitiesLotConfig...PoolAreaPoolQCFenceMiscFeatureMiscValMoSoldYrSoldSaleTypeSaleConditionSalePriceId160RL65.08450PaveNaNRegLvlAllPubInside...0NaNNaNNaN022008WDNormal208500220RL80.09600PaveNaNRegLvlAllPubFR2...0NaNNaNNaN052007WDNormal181500360RL68.011250PaveNaNIR1LvlAllPubInside...0NaNNaNNaN092008WDNormal223500470RL60.09550PaveNaNIR1LvlAllPubCorner...0NaNNaNNaN022006WDAbnorml140000560RL84.014260PaveNaNIR1LvlAllPubFR2...0NaNNaNNaN0122008WDNormal250000
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]],dtypeobject)可见label本身并不平滑。为了我们分类器的学习更加准确我们会首先把label给“平滑化”正态化
这一步大部分同学会miss掉导致自己的结果总是达不到一定标准。
这里我们使用最有逼格的log1p, 也就是 log(x1)避免了复值的问题。
记住哟如果我们这里把数据都给平滑化了那么最后算结果的时候要记得把预测到的平滑数据给变回去。
按照“怎么来的怎么去”原则log1p()就需要expm1(); 同理log()就需要exp(), … etc.
对于分类问题不需要对标签进行平滑处理因为其结果本来就是需要离散化的但是对于回归问题由于需要预测的是一个连续的值所以需要训练模型的数据的标签也是平滑的而对于训练集我们得到的标签往往又是离散的所以要先做平滑处理
注在比赛中由于训练集和测试集已经知道所以常常为了更大的得到好的结果常常将测试集和训练集先混合在一起然后在整体做数据的预处理但是在实际的过程中由于测试集是未知的所以先对训练集做处理再用相同的方法去处理测试集。
y_train np.log1p(train_df.pop(SalePrice))然后我们把剩下的部分合并起来
all_df pd.concat((train_df, test_df), axis0)此刻我们可以看到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: float64Step 3: 变量转化
类似『特征工程』。就是把不方便处理或者不unify的数据给统一了。
正确化变量属性
首先我们注意到MSSubClass 的值其实应该是一个category
但是Pandas是不会懂这些事儿的。使用DF的时候这类数字符号会被默认记成数字。
这种东西就很有误导性我们需要把它变回成string
all_df[MSSubClass].dtypesdtype(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], prefixMSSubClass).head()#将分类数据转换为数值型数据MSSubClass_120MSSubClass_150MSSubClass_160MSSubClass_180MSSubClass_190MSSubClass_20MSSubClass_30MSSubClass_40MSSubClass_45MSSubClass_50MSSubClass_60MSSubClass_70MSSubClass_75MSSubClass_80MSSubClass_85MSSubClass_90Id1000000000010000020000010000000000300000000001000004000000000001000050000000000100000
此刻MSSubClass被我们分成了12个column每一个代表一个category。是就是1不是就是0。
同理我们把所有的category数据都给One-Hot了
all_dummy_df pd.get_dummies(all_df)
all_dummy_df.head()LotFrontageLotAreaOverallQualOverallCondYearBuiltYearRemodAddMasVnrAreaBsmtFinSF1BsmtFinSF2BsmtUnfSF...SaleType_ConLwSaleType_NewSaleType_OthSaleType_WDSaleCondition_AbnormlSaleCondition_AdjLandSaleCondition_AllocaSaleCondition_FamilySaleCondition_NormalSaleCondition_PartialId165.084507520032003196.0706.00.0150.0...0001000010280.0960068197619760.0978.00.0284.0...0001000010368.0112507520012002162.0486.00.0434.0...0001000010460.0955075191519700.0216.00.0540.0...0001100000584.0142608520002000350.0655.00.0490.0...0001000010
5 rows × 303 columns
处理好numerical变量
就算是numerical的变量也还会有一些小问题。
比如有一些数据是缺失 的
all_dummy_df.isnull().sum().sort_values(ascendingFalse).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: float64all_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_colsIndex([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],dtypeobject)计算标准分布(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, cv10, scoringneg_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);可见大概alpha10~20的时候可以把score达到0.135左右。
Random Forest
from sklearn.ensemble import RandomForestRegressormax_features [.1, .3, .5, .7, .9, .99]
test_scores []
for max_feat in max_features:clf RandomForestRegressor(n_estimators200, max_featuresmax_feat)test_score np.sqrt(-cross_val_score(clf, X_train, y_train, cv5, scoringneg_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(alpha15)
rf RandomForestRegressor(n_estimators500, max_features.3)ridge.fit(X_train, y_train)
rf.fit(X_train, y_train)RandomForestRegressor(bootstrapTrue, criterionmse, max_depthNone,max_features0.3, max_leaf_nodesNone,min_impurity_decrease0.0, min_impurity_splitNone,min_samples_leaf1, min_samples_split2,min_weight_fraction_leaf0.0, n_estimators500, n_jobs1,oob_scoreFalse, random_stateNone, verbose0, warm_startFalse)上面提到了因为最前面我们给label做了个log(1x), 于是这里我们需要把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)IdSalePrice01461120284.85093811462151366.17966321463174792.13312031464190099.60594541465195500.17043651466175876.56350261467177675.12891471468169318.65132181469184796.69992191470122328.836416
走你~