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)
MSSubClassMSZoningLotFrontageLotAreaStreetAlleyLotShapeLandContourUtilitiesLotConfig...PoolAreaPoolQCFenceMiscFeatureMiscValMoSoldYrSoldSaleTypeSaleConditionSalePrice
Id
160RL65.08450PaveNaNRegLvlAllPubInside...0NaNNaNNaN022008WDNormal208500
220RL80.09600PaveNaNRegLvlAllPubFR2...0NaNNaNNaN052007WDNormal181500
360RL68.011250PaveNaNIR1LvlAllPubInside...0NaNNaNNaN092008WDNormal223500
470RL60.09550PaveNaNIR1LvlAllPubCorner...0NaNNaNNaN022006WDAbnorml140000
560RL84.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>]],dtype=object)

png

可见,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_120MSSubClass_150MSSubClass_160MSSubClass_180MSSubClass_190MSSubClass_20MSSubClass_30MSSubClass_40MSSubClass_45MSSubClass_50MSSubClass_60MSSubClass_70MSSubClass_75MSSubClass_80MSSubClass_85MSSubClass_90
Id
10000000000100000
20000010000000000
30000000000100000
40000000000010000
50000000000100000

此刻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_Partial
Id
165.084507520032003196.0706.00.0150.0...0001000010
280.0960068197619760.0978.00.0284.0...0001000010
368.0112507520012002162.0486.00.0434.0...0001000010
460.0955075191519700.0216.00.0540.0...0001100000
584.0142608520002000350.0655.00.0490.0...0001000010

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");

png

可见,大概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");

png

用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)
IdSalePrice
01461120284.850938
11462151366.179663
21463174792.133120
31464190099.605945
41465195500.170436
51466175876.563502
61467177675.128914
71468169318.651321
81469184796.699921
91470122328.836416

走你~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445514.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用github中的pull request功能?

* pull request是社会化编程的象征&#xff0c;通过这个功能&#xff0c;你可以参与到别人开发的项目中&#xff0c;并做出自己的贡献。pull request是自己修改源代码后&#xff0c;请求对方仓库采纳的一种行为*–《github入门与实践》 下面具体说一下github中使用pull reque…

「假装努力」

有多少人在「假装努力」&#xff1f; 又有多少人在「真正成长」&#xff1f; 再努力努力 回想起当年毕业后&#xff0c;在北京和室友合租的日子。 那时&#xff0c;我在工作&#xff0c;室友在培训。 一天&#xff0c;我下班回来&#xff0c;听见他在电话里和家人争吵&…

如何阅读论文?

本文主要讲述了如何才能高效的阅读一篇论文&#xff01;&#xff01;

数据结构课上笔记8

串的概念&#xff1a;串&#xff08;字符串&#xff09;&#xff1a;是由 0 个或多个字符组成的有限序列。 通常记为&#xff1a;s ‘ a1 a2 a3 … ai …an ’ ( n≥0 )。 串的逻辑结构和线性表极为相似。 一些串的类型&#xff1a; 空串&#xff1a;不含任何字符的串&#x…

Numpy 入门

Numpy 入门 Numpy简介 官网链接&#xff1a;http://www.numpy.org/NumPy是Python语言的一个扩充程序库。支持高级大量的维度数组与矩阵运算&#xff0c;此外也针对数组运算提供大量的数学函数库 Numpy的基本功能 快速高效的多维数组对象ndarray用于对数组执行元素级计算以…

数据结构课上笔记10

树 树的定义&#xff1a;树(Tree)是 n(n≥0)个结点的有限集。若 n0&#xff0c;称为空树&#xff1b;若 n > 0&#xff0c;则它满足如下两个条件&#xff1a; (1) 有且仅有一个特定的称为根 (Root) 的结点&#xff1b; (2) 其余结点可分为 m (m≥0) 个互不相交的有限…

pandasStudyNoteBook

pandas 入门培训 pandas简介 - 官网链接&#xff1a;http://pandas.pydata.org/ - pandas pannel data data analysis - Pandas是python的一个数据分析包 , Pandas最初被作为金融数据分析工具而开发出来&#xff0c;因此&#xff0c;pandas为时间序列分析提供了很好的支持 …

二叉树最长路径

分析&#xff1a; 暴力求每一段距离也可。 对于以本节点为根的二叉树&#xff0c;最远距离有三种可能&#xff1a; 1&#xff09;最远路径来自左子树 2 &#xff09;最远路径来自右子树&#xff08;图示与左子树同理&#xff09; 3&#xff09;最远路径为左右子树距离根最远…

判断完全二叉树

完全二叉树的定义: 一棵二叉树&#xff0c;除了最后一层之外都是完全填充的&#xff0c;并且最后一层的叶子结点都在左边。 https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91/7773232?fraladdin 百度定义 思路&#xff1a;层序遍历二叉树 如果…

判断二叉搜索树

二叉查找树&#xff08;Binary Search Tree&#xff09;&#xff0c;&#xff08;又&#xff1a;二叉搜索树&#xff0c;二叉排序树&#xff09;它或者是一棵空树&#xff0c;或者是具有下列性质的二叉树&#xff1a; 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于…

剑指offer_01

文章目录[toc]第一章 面试流程1.1 面试官谈面试1.2 面试3种形式1.3 面试的3个环节第一章 面试流程 1.1 面试官谈面试 初级的程序员谈算法和数据结构&#xff0c;高级的程序员谈项目经验要对公司近况和项目情况了解不要紧张&#xff0c;不要马上上手写代码 1.2 面试3种形式 …

求完全二叉树的结点个数

第一次见这个题&#xff0c;看时间小于O(N)。。。。。 只能是二分啊。 但是怎么二分&#xff0c;条件是什么&#xff0c;真的想不到。 后来知道了&#xff0c;我们要找最深一层最右边那个结点。借此确定结点个数。 我们知道&#xff0c;满二叉树的结点个数和深度是有公式的&a…

剑指offer_03

文章目录第三章 高质量代码1.1 面试官谈高质量代码1.2 代码的规范性1.3 代码的完整性1.4 代码的鲁棒性第三章 高质量代码 1.1 面试官谈高质量代码 代码应该考虑异常状况和垃圾回收问题&#xff0c;不能忽视边界情况变量&#xff0c;函数命名应该要统一&#xff0c;备注要恰到…

先序中序后序两两结合重建二叉树

遍历是对树的一种最基本的运算&#xff0c;所谓遍历二叉树&#xff0c;就是按一定的规则和顺序走遍二叉树的所有结点&#xff0c;使每一个结点都被访问一次&#xff0c;而且只被访问一次。由于二叉树是非线性结构&#xff0c;因此&#xff0c;树的遍历实质上是将二叉树的各个结…

先序中序数组推后序数组

二叉树遍历 所谓遍历(Traversal)是指沿着某条搜索路线&#xff0c;依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一&#xff0c;是二叉树上进行其它运算之基础。 从二叉树的递归定义可知&#xff0c;一…

剑指offer_06

文章目录第六章 面试中的各项能力1.1 面试官谈能力1.2 沟通能力和学习能力1.3 知识迁移能力1.4 抽象建模能力1.5 发散思维能力第六章 面试中的各项能力 1.1 面试官谈能力 1.礼貌平和&#xff0c;不卑不亢的和面试官沟通&#xff1b;逻辑清楚&#xff0c;详略得到的介绍项目经…

数据结构课上笔记11

满二叉树 (Full binary tree) 除最后一层无任何子节点外&#xff0c;每一层上的所有结点都有两个子结点二叉树。 国内教程定义&#xff1a;一个二叉树&#xff0c;如果每一个层的结点数都达到最大值&#xff0c;则这个二叉树就是满二叉树。也就是说&#xff0c;如果一个二叉树…

数据结构课上笔记12

二叉树的存储结构 顺序存储结构 完全二叉树&#xff1a;用一组地址连续的 存储单元依次自上而下、自左至右存 储结点元素&#xff0c;即将编号为 i 的结点元 素存储在一维数组中下标为 i –1 的分量中。 一般二叉树&#xff1a;将其每个结点与完 全二叉树上的结点相对照&…

kaggle(01)-泰坦尼克号问题

经典又兼具备趣味性的Kaggle案例泰坦尼克号问题 大家都熟悉的『Jack and Rose』的故事&#xff0c;豪华游艇倒了&#xff0c;大家都惊恐逃生&#xff0c;可是救生艇的数量有限&#xff0c;无法人人都有&#xff0c;副船长发话了『lady and kid first&#xff01;』&#xff0c…

数据结构课上笔记13

树存储结构 父节点表示法 数据域&#xff1a;存放结点本身信息。 双亲域&#xff1a;指示本结点的双亲结点在数组中的位置。 对应的树&#xff1a; /* 树节点的定义 */ #define MAX_TREE_SIZE 100typedef struct{TElemType data;int parent; /* 父节点位置域 */ } PTNode;type…