简单kaggle房价预测
程序员文章站
2024-03-22 08:10:34
...
在kaggle入门项目中房价预测项目,是更加接近我们工作会遇到的项目,数据属性很多、属性和标签之前的关系需要研究、属性需要取舍、类别数据需要转为数值化数据等等。
本练习按照如下几个步骤进行:
- 研究主要特征:特征和房价之间的关系
- 数据清除:对一些缺失数据、异常点和分类数据进行处理
- 训练
- 预测
# 导入需要的模块
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
#seaborn 用于绘图,其中封装了matplotlib
import seaborn as sns
from scipy import stats
from scipy.stats import norm
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')
# 为了在jupyter notebook里作图,需要用到这个命令
%matplotlib inline
#读入数据
data_train = pd.read_csv('./dataset/house-prices/train.csv')
#大概看一下数据样式
data_train.head(10)
#分析“SalePrice”
data_train['SalePrice'].describe()
sns.distplot(data_train['SalePrice'])
#如下图可知价格分布情况
#看看都有哪些属性
data_train.columns
属性这么多,都要考虑进去吗,我们观察数据可知有些属性是共有的比如Utilities,Heating以及TotalBsmtSF&GrLivArea 也是说面积,和很多其他属性有重叠,像这些就不再考虑进去了而且属性中有的属性是数值型有的是类别型,综合考虑下来我们选择我们认为评估价格的时候是重要的、需要考虑进去因素来看看
此处加入一个知识点:需要了解 箱线图boxplot如下截图:
# CentralAir *空调
var = 'CentralAir'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000);
#如下图明显有*空调的房价更高
# OverallQual 总体评价
var = 'OverallQual'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000);
#很明显评分越高房价越高(此处评分估计也会考虑周边交通、学校、医院、大型商场、公园、社区治安等等)
# YearBuilt boxplot
var = 'YearBuilt'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
f, ax = plt.subplots(figsize=(26, 12))
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000);
#如下箱线图价格关系不明显(说不行30年前的房子大多在市中心呢,2年前的房子大多在郊区,所以整体关系不是很清楚)
# YearBuilt 用散点图看一下整体分布情况
var = 'YearBuilt'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
data.plot.scatter(x=var, y="SalePrice", ylim=(0, 800000))
#看来我们猜测也有一定的道理。不过依然能看到年份新的整体来说价格也是比较高的
# Neighborhood 地段
var = 'Neighborhood'
data = pd.concat([data_train['SalePrice'],data_train[var]],axis=1)
f,ax = plt.subplots(figsize=(26,12))
fig = sns.boxplot(x= var,y='SalePrice',data=data)
fig.axis(ymin=0,ymax=800000)
#地段看不出什么线性关系,但是还是可以看到有的地方价格高,有的地方价格低于,按照我们一般的理解地段肯定是和价格有很大关系了
var = 'LotArea' #地表面积
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000))
#看不出什么关系,暂不考虑
var = 'GrLivArea'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000))
#呈现线性趋势,所以可以考虑。
var = 'TotalBsmtSF'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000))
#呈现线性趋势,所以可以考虑。
var = 'MiscVal'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000))
#看不出什么关系暂不考虑
var = 'GarageArea'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000))
#由点图可以看出房价与车库面积呈现线性关系,所以入选主要特征。
var = 'GarageCars'
data = pd.concat([data_train['SalePrice'], data_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000))
#由上面点图可以看出房价与车库容纳车辆数呈现线性关系,所以入选主要特征。
大概总结起来,最后选择的属性有(GrLivArea生活面积)(TotalBsmtSF地下室总面积)(GarageArea/GarageCars车库)(YearBuilt建造年份)(CentralAir*空调)(OverallQual总体评价)(Neighborhood地段)
这些类别中有'CentralAir', 'Neighborhood'这个来两个属性是类别我们需要将他们转为数值型的
#数值化类别
from sklearn import preprocessing
f_names = ['CentralAir', 'Neighborhood']
for x in f_names:
label = preprocessing.LabelEncoder()
data_train[x] = label.fit_transform(data_train[x])
#大概看看转换过后的值
data_train['Neighborhood'][:5]
我们选择我们处理好的属性值,选择森林回归算法RandomForestRegressor
import numpy as np
from sklearn import preprocessing
from sklearn import linear_model,svm,gaussian_process
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
# 获取数据(为了方便观察预测值,我们没有将数据标准化)
cols = ['OverallQual','GrLivArea', 'GarageCars','TotalBsmtSF', 'FullBath', 'TotRmsAbvGrd', 'YearBuilt','Neighborhood']
x = data_train[cols].values
y = data_train['SalePrice'].values
X_train,X_test, y_train, y_test = train_test_split(x, y, test_size=0.33, random_state=42)
clf = RandomForestRegressor(n_estimators=400)
#训练
clf.fit(X_train, y_train)
#验证
y_pred = clf.predict(X_test)
#输出前100个测试结果
print(y_pred[:100])
#我们看一看被测试数据的标签
y_test[:100]
看上去相差也还能接受,说明我们前面的特征选择方向是对的(当然特征还可以选择其他的特征或者去掉一些特征)
#我们计算以下平均误差
sum(abs(y_pred - y_test))/len(y_pred)
#输出:18845.80631762497
#就平均误差来看有18845.8,貌似还能接受。
接下来我们预测一下我们的测试数据集合
#检验测试集数据
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
# 我们要测试的模型是之前训练的模型clf
rfr = clf
data_test = pd.read_csv('./dataset/house-prices/test.csv')
data_test[cols].isnull().sum()
#可以看到数据集中GarageCars/TotalBsmtSF有缺失值,
#这里我们把缺失值填充为均值,先看看有缺失属性的描述
data_test['GarageCars'].describe()
mean 1.766118
data_test['TotalBsmtSF'].describe()
mean 1046.117970
#选择我们认为和是的特征
cols2 = ['OverallQual','GrLivArea', 'FullBath', 'TotRmsAbvGrd', 'YearBuilt','Neighborhood']
#填充缺失值
cars = data_test['GarageCars'].fillna(1.766118)
bsmt = data_test['TotalBsmtSF'].fillna(1046.117970)
label = preprocessing.LabelEncoder()
#将Neighborhood 数值化
index = 'Neighborhood'
data_test[index] = label.fit_transform(data_test[index])
data_test_x = pd.concat( [data_test[cols2], cars, bsmt] ,axis=1)
#查看还有没有缺失值
data_test_x.isnull().sum()
#看样子是没有缺失值了
x = data_test_x.values
#预测
y_te_pred = rfr.predict(x)
print(y_te_pred)
print(y_te_pred.shape)
print(x.shape)
#输出:如下
#[ 96578.66 110238.375 143573.6525 ... 103747.85 96953.535
#182793.4125]
#(1459,)
#(1459, 8)
data_test_x
prediction = pd.DataFrame(y_te_pred, columns=['SalePrice'])
result = pd.concat([ data_test['Id'], prediction], axis=1)
result.columns
#输出:Index(['Id', 'SalePrice'], dtype='object')
# 保存预测结果,预测结果将保存在指定目录的文件中
result.to_csv('./Predictions_Result.csv', index=False)
#部分数据截图如下
至此,我们简单的房价预测便完成了,当然这其中属性的选择和取舍还有很多很好方式,欢迎留言沟通。
如有问题欢迎指正。