百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

每日一课 Kaggle 练习讲解House Prices(上)

toyiye 2024-06-21 12:36 9 浏览 0 评论

每天一道Kaggle题,学习机器学习!

今天给大家来讲讲《House Prices: Advanced Regression Techniques》(房价预测模型)的思路:

  • (1) 数据可视化和数据分布变换
  • (2) 缺省值处理
  • (3) 数据特征变换
  • (4) 数据建模及交叉检验
  • (5) 模型组合

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import seaborn as sns

from scipy import stats

from scipy.stats import norm, skew

from scipy.special import boxcox1p

from scipy.stats import boxcox_normmax

from sklearn.model_selection import KFold, cross_val_score

from sklearn.preprocessing import LabelEncoder

%matplotlib inline

加载数据

去除ID

In [2]:

train_path = "http://kaggle.shikanon.com/house-prices-advanced-regression-techniques/train.csv"
test_path = "http://kaggle.shikanon.com/house-prices-advanced-regression-techniques/test.csv"
train_df = pd.read_csv(train_path)
test_df = pd.read_csv(test_path)

我们在分析之前要先了解个字段的意思:

  • MSSubClass: 建筑的等级,类型:类别型
  • MSZoning: 区域分类,类型:类别型
  • LotFrontage: 距离街道的直线距离,类型:数值型,单位:英尺
  • LotArea: 地皮面积,类型:数值型,单位:平方英尺
  • Street: 街道类型,类型:类别型
  • Alley: 巷子类型,类型:类别型
  • LotShape: 房子整体形状,类型:类别型
  • LandContour: 平整度级别,类型:类别型
  • Utilities: 公共设施类型,类型:类别型
  • LotConfig: 房屋配置,类型:类别型
  • LandSlope: 倾斜度,类型:类别型
  • Neighborhood: 市区物理位置,类型:类别型
  • Condition1: 主干道或者铁路便利程度,类型:类别型
  • Condition2: 主干道或者铁路便利程度,类型:类别型
  • BldgType: 住宅类型,类型:类别型
  • HouseStyle: 住宅风格,类型:类别型
  • OverallQual: 整体材料和饰面质量,类型:数值型
  • OverallCond: 总体状况评价,类型:数值型
  • YearBuilt: 建筑年份,类型:数值型
  • YearRemodAdd: 改建年份,类型:数值型
  • RoofStyle: 屋顶类型,类型:类别型
  • RoofMatl: 屋顶材料,类型:类别型
  • Exterior1st: 住宅外墙,类型:类别型
  • Exterior2nd: 住宅外墙,类型:类别型
  • MasVnrType: 砌体饰面类型,类型:类别型
  • MasVnrArea: 砌体饰面面积,类型:数值型,单位:平方英尺
  • ExterQual: 外部材料质量,类型:类别型
  • ExterCond: 外部材料的现状,类型:类别型
  • Foundation: 地基类型,类型:类别型
  • BsmtQual: 地下室高度,类型:类别型
  • BsmtCond: 地下室概况,类型:类别型
  • BsmtExposure: 花园地下室墙,类型:类别型
  • BsmtFinType1: 地下室装饰质量,类型:类别型
  • BsmtFinSF1: 地下室装饰面积,类型:类别型
  • BsmtFinType2: 地下室装饰质量,类型:类别型
  • BsmtFinSF2: 地下室装饰面积,类型:类别型
  • BsmtUnfSF: 未装饰的地下室面积,类型:数值型,单位:平方英尺
  • TotalBsmtSF: 地下室总面积,类型:数值型,单位:平方英尺
  • Heating: 供暖类型,类型:类别型
  • HeatingQC: 供暖质量和条件,类型:类别型
  • CentralAir: 中央空调状况,类型:类别型
  • Electrical: 电力系统,类型:类别型
  • 1stFlrSF: 首层面积,类型:数值型,单位:平方英尺
  • 2ndFlrSF: 二层面积,类型:数值型,单位:平方英尺
  • LowQualFinSF: 低质装饰面积,类型:数值型,单位:平方英尺
  • GrLivArea: 地面以上居住面积,类型:数值型,单位:平方英尺
  • BsmtFullBath: 地下室全浴室,类型:数值
  • BsmtHalfBath: 地下室半浴室,类型:数值
  • FullBath: 高档全浴室,类型:数值
  • HalfBath: 高档半浴室,类型:数值
  • BedroomAbvGr: 地下室以上的卧室数量,类型:数值
  • KitchenAbvGr: 厨房数量,类型:数值
  • KitchenQual: 厨房质量,类型:类别型
  • TotRmsAbvGrd: 地上除卧室以外的房间数,类型:数值
  • Functional: 房屋功用性评级,类型:类别型
  • Fireplaces: 壁炉数量,类型:数值
  • FireplaceQu: 壁炉质量,类型:类别型
  • GarageType: 车库位置,类型:类别型
  • GarageYrBlt: 车库建造年份,类别:数值型
  • GarageFinish: 车库内饰,类型:类别型
  • GarageCars: 车库车容量大小,类别:数值型
  • GarageArea: 车库面积,类别:数值型,单位:平方英尺
  • GarageQual: 车库质量,类型:类别型
  • GarageCond: 车库条件,类型:类别型
  • PavedDrive: 铺的车道情况,类型:类别型
  • WoodDeckSF: 木地板面积,类型:数值型,单位:平方英尺
  • OpenPorchSF: 开放式门廊区面积,类型:数值型,单位:平方英尺
  • EnclosedPorch: 封闭式门廊区面积,类型:数值型,单位:平方英尺
  • 3SsnPorch: 三个季节门廊面积,类型:数值型,单位:平方英尺
  • ScreenPorch: 纱门门廊面积,类型:数值型,单位:平方英尺
  • PoolArea: 泳池面积,类型:数值型,单位:平方英尺
  • PoolQC:泳池质量,类型:类别型
  • Fence: 围墙质量,类型:类别型
  • MiscFeature: 其他特征,类型:类别型
  • MiscVal: 其他杂项特征值,类型:类别型
  • MoSold: 卖出月份,类别:数值型
  • YrSold: 卖出年份,类别:数值型
  • SaleType: 交易类型,类型:类别型
  • SaleCondition: 交易条件,类型:类别型

数据处理和特征分析

In [4]:

#Saving Ids
train_ID = train_df['Id']
test_ID = test_df['Id']
?
#Dropping Ids
train_df.drop("Id", axis = 1, inplace = True)
test_df.drop("Id", axis = 1, inplace = True)

数据观察和可视化

更加常识,一般和房价最相关的是居住面积,也就是GrLivArea,我们查看下GrLivArea和SalePrice的关系

In [5]:

fig, ax = plt.subplots()
ax.scatter(x = train_df['GrLivArea'], y = train_df['SalePrice'], c = "skyblue")
plt.ylabel('SalePrice', fontsize=8)
plt.xlabel('GrLivArea', fontsize=8)
plt.show()

我们发现有个别值特别的偏离,GrLivArea有两个点在4000以上,但其价格不到200000,首先这种点特别少(不到总数的3%),我们把他作为异常值去掉(其实是否去掉我们可以多做几次实验来验证)

In [6]:

train_df.drop(train_df[(train_df['GrLivArea']>4000)&(train_df['GrLivArea']<30000)].index,inplace=True)

In [7]:

fig, ax = plt.subplots()
ax.scatter(x = train_df['GrLivArea'], y = train_df['SalePrice'], c = "skyblue")
plt.ylabel('SalePrice', fontsize=8)
plt.xlabel('GrLivArea', fontsize=8)
plt.show()

  • 最后一行是 SalePrice, 我们可以看到她跟各变量的关系,还有各变量相互之间的关系

观察数据分布

在机器学习中,对数据的认识是很重要的,他会影响我们的特征构建和建模,特别对于偏态分布,我们要做一些变换

In [8]:

# 统计表述
train_df['SalePrice'].describe()

count 1456.000000

mean 180151.233516

std 76696.592530

min 34900.000000

25% 129900.000000

50% 163000.000000

75% 214000.000000

max 625000.000000

Name: SalePrice, dtype: float64

# 绘制分布图
sns.distplot(train_df['SalePrice'], 
 kde_kws={"color": "coral", "lw": 1, "label": "KDE"}, 
 hist_kws={"histtype": "stepfilled", "linewidth": 3, "alpha": 1, "color": "skyblue"});

Q-Q图,全称 Quantile Quantile Plot,中文名叫分位数图,Q-Q图是一个概率图,用于比较观测与预测值之间的概率分布差异,这里的比较对象一般采用正态分布,Q-Q图可以用于检验数据分布的相似性,而P-P图是根据变量的累积概率对应于所指定的理论分布累积概率绘制的散点图,两者基本一样

In [10]:

# 绘制P-P图
fig = plt.figure()
res = stats.probplot(train_df['SalePrice'], dist="norm", plot=plt)
plt.show()

红色线是正态分布,蓝色线是我们的数据,可以看出,我们的数据头尾都严重偏离了正太分布,我们尝试对数据做变换,常用的变换有指数变换、对数变换、幂函数等。

In [11]:

# 对数变换
?
train_df['SalePrice_Log'] = np.log(train_df['SalePrice'])
?
sns.distplot(train_df['SalePrice_Log'], 
 kde_kws={"color": "coral", "lw": 1, "label": "KDE"}, 
 hist_kws={"histtype": "stepfilled", "linewidth": 3, "alpha": 1, "color": "skyblue"});
 
# 偏度与峰值(skewness and kurtosis)
print("Skewness: %f" % train_df['SalePrice_Log'].skew())
print("Kurtosis: %f" % train_df['SalePrice_Log'].kurt())
?
fig = plt.figure()
res = stats.probplot(train_df['SalePrice_Log'], plot=plt)
plt.show()

Skewness: 0.065449

Kurtosis: 0.666438

In [12]:

# 指数变换
train_df['SalePrice_Exp'] = np.exp(train_df['SalePrice']/train_df['SalePrice'].mean())
?
sns.distplot(train_df['SalePrice_Exp'], 
 kde_kws={"color": "coral", "lw": 1, "label": "KDE"}, 
 hist_kws={"histtype": "stepfilled", "linewidth": 3, "alpha": 1, "color": "skyblue"});
 
# 偏度与峰值(skewness and kurtosis)
print("Skewness: %f" % train_df['SalePrice_Exp'].skew())
print("Kurtosis: %f" % train_df['SalePrice_Exp'].kurt())
?
fig = plt.figure()
res = stats.probplot(train_df['SalePrice_Exp'], plot=plt)
plt.show()

Skewness: 6.060076

Kurtosis: 56.822460

In [13]:

# 幂函数变换
train_df['SalePrice_Square'] = train_df['SalePrice']**0.5
?
sns.distplot(train_df['SalePrice_Square'], 
 kde_kws={"color": "coral", "lw": 1, "label": "KDE"}, 
 hist_kws={"histtype": "stepfilled", "linewidth": 3, "alpha": 1, "color": "skyblue"});
 
# 偏度与峰值(skewness and kurtosis)
print("Skewness: %f" % train_df['SalePrice_Square'].skew())
print("Kurtosis: %f" % train_df['SalePrice_Square'].kurt())
?
fig = plt.figure()
res = stats.probplot(train_df['SalePrice_Square'], plot=plt)
plt.show()

Skewness: 0.810797

Kurtosis: 1.245798

三个函数拟合对比,对数转换最吻合,但是我们知道对数意味着小于1的时候为负数,这明显和认知不符合,应该采用log(1+x),也就是log1p,保证了x数据的有效性,当x很小时,如: 10^{-16} ,由于太小超过数值有效性,用log(x+1)计算得到结果为0

In [14]:

# 对数变换
?
train_df['SalePrice_Log1p'] = np.log1p(train_df['SalePrice'])
?
sns.distplot(train_df['SalePrice_Log1p'], 
 kde_kws={"color": "coral", "lw": 1, "label": "KDE"}, 
 hist_kws={"histtype": "stepfilled", "linewidth": 3, "alpha": 1, "color": "skyblue"});
 
# 偏度与峰值(skewness and kurtosis)
print("Skewness: %f" % train_df['SalePrice_Log1p'].skew())
print("Kurtosis: %f" % train_df['SalePrice_Log1p'].kurt())
?
fig = plt.figure()
res = stats.probplot(train_df['SalePrice_Log1p'], plot=plt)
plt.show()

Skewness: 0.065460

Kurtosis: 0.666423

In [15]:

del train_df['SalePrice_Square']
del train_df["SalePrice_Exp"]
del train_df['SalePrice_Log']

In [16]:

del train_df["SalePrice"]

将测试数据和训练数据联合一起进行特征分析

In [17]:

size_train_df = train_df.shape[0]
size_test_df = test_df.shape[0]
target_variable = train_df['SalePrice_Log1p'].values
data = pd.concat((train_df, test_df),sort=False).reset_index(drop=True)
data.drop(['SalePrice_Log1p'], axis=1, inplace=True)

缺失值处理

缺失值是实际数据分析很重要的一块,在实际生产中一直都会有大量的缺失值存在,如何处理好缺失值是很关键也很重要的一步。

常见的缺失值处理有:

  • (1)把缺失值单独作为一类,比如对类别型用none。
  • (2)采用平均数、中值、众数等特定统计值来填充缺失值。
  • (3)采用函数预测等方法填充缺失值。

In [18]:

data.count().sort_values().head(20) # 通过 count 可以找出有缺失值的数据
Out[18]:

PoolQC 8

MiscFeature 105

Alley 198

Fence 570

FireplaceQu 1495

LotFrontage 2429

GarageCond 2756

GarageYrBlt 2756

GarageFinish 2756

GarageQual 2756

GarageType 2758

BsmtExposure 2833

BsmtCond 2833

BsmtQual 2834

BsmtFinType2 2835

BsmtFinType1 2836

MasVnrType 2891

MasVnrArea 2892

MSZoning 2911

BsmtFullBath 2913

dtype: int64

In [19]:

data_na = (data.isnull().sum() / len(data)) * 100
data_na.drop(data_na[data_na==0].index,inplace=True)
data_na = data_na.sort_values(ascending=False)
f, ax = plt.subplots(figsize=(10, 10))
plt.xticks(rotation='90')
sns.barplot(x=data_na.index, y=data_na)
plt.xlabel('Features', fontsize=10)
plt.ylabel('Percent of missing values', fontsize=10)
plt.title('Percent missing data by feature', fontsize=10)

Out[19]:

Text(0.5, 1.0, 'Percent missing data by feature')

In [20]:

var = 'Utilities'
train_var_count = train_df[var].value_counts()
fig = sns.barplot(x=train_var_count.index, y=train_var_count)
plt.xticks(rotation=90);

In [21]:

var = 'MSZoning'
train_var_count = train_df[var].value_counts()
fig = sns.barplot(x=train_var_count.index, y=train_var_count)
plt.xticks(rotation=90);

In [22]:

# 填充nil
features_fill_na_none = ['PoolQC','MiscFeature','Alley','Fence','FireplaceQu',
 'GarageQual','GarageCond','GarageFinish','GarageType',
 'BsmtExposure','BsmtCond','BsmtQual','BsmtFinType1','BsmtFinType2',
 'MasVnrType']
?
# 填充0
features_fill_na_0 = ['GarageYrBlt', 'GarageArea', 'GarageCars', 'MasVnrArea',
 'BsmtFullBath','BsmtHalfBath', 'BsmtFinSF1', 'BsmtFinSF2', 
 'BsmtUnfSF', 'TotalBsmtSF']
?
# 填众数
features_fill_na_mode = ["Functional", "MSZoning", "SaleType", "Electrical", 
 "KitchenQual", "Exterior2nd", "Exterior1st"]
?
for feature_none in features_fill_na_none:
 data[feature_none].fillna('None',inplace=True)
 
for feature_0 in features_fill_na_0:
 data[feature_0].fillna(0,inplace=True)
?
for feature_mode in features_fill_na_mode:
 mode_value = data[feature_mode].value_counts().sort_values(ascending=False).index[0]
 data[features_fill_na_mode] = data[features_fill_na_mode].fillna(mode_value)
?
# 用中值代替
data["LotFrontage"] = data.groupby("Neighborhood")["LotFrontage"].transform(
 lambda x: x.fillna(x.median()))
?
# 像 Utilities 这种总共才两个值,同时有一个值是作为主要的,这种字段是无意义的,应该删除
data.drop(['Utilities'], axis=1,inplace=True)

In [23]:

data_na = (data.isnull().sum() / len(data)) * 100
data_na.drop(data_na[data_na==0].index,inplace=True)
data_na = data_na.sort_values(ascending=False)
data_na # data_na 为空

Out[23]:

Series([], dtype: float64)

类型转换,将某些实际是类别类型但用数字表示的强制转换成文本,比如有些调查男表示1,女表示0,在这种情况下,如果我们直接通过dataframe类型判断会导致错误,我们要根据实际情况做转换

In [24]:

#MSSubClass=The building class
data['MSSubClass'] = data['MSSubClass'].apply(str)
?
?
#Changing OverallCond into a categorical variable
data['OverallCond'] = data['OverallCond'].astype(str)
?
?
#Year and month sold are transformed into categorical features.
data['YrSold'] = data['YrSold'].astype(str)
data['MoSold'] = data['MoSold'].astype(str)

绘制关系矩阵

关系矩阵可以很直观的告诉我们那些变量之间相关,哪些变量并不相关

In [25]:

# 关系矩阵
corrmat = train_df.corr()
corrmat

In [26]:

mask = np.zeros_like(corrmat) # 返回相同大小的0矩阵
mask[np.triu_indices_from(mask)] = True # triu_indices_from: 函数的上三角矩阵
mask

Out[26]:

array([[1., 1., 1., ..., 1., 1., 1.],

[0., 1., 1., ..., 1., 1., 1.],

[0., 0., 1., ..., 1., 1., 1.],

...,

[0., 0., 0., ..., 1., 1., 1.],

[0., 0., 0., ..., 0., 1., 1.],

[0., 0., 0., ..., 0., 0., 1.]])

In [27]:

# 绘制热力图
plt.subplots(figsize=(12,9))
sns.heatmap(corrmat, mask=mask, linewidths=.5, vmax=0.9, square=True, cmap="YlGnBu")

Out[27]:

<matplotlib.axes._subplots.AxesSubplot at 0x7f8c20d156d8>

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码