简单kaggle房价预测

在kaggle入门项目中房价预测项目,是更加接近我们工作会遇到的项目,数据属性很多、属性和标签之前的关系需要研究、属性需要取舍、类别数据需要转为数值化数据等等。

本练习按照如下几个步骤进行:

  1. 研究主要特征:特征和房价之间的关系
  2. 数据清除:对一些缺失数据、异常点和分类数据进行处理
  3. 训练
  4. 预测
# 导入需要的模块
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)

#部分数据截图如下

 

至此,我们简单的房价预测便完成了,当然这其中属性的选择和取舍还有很多很好方式,欢迎留言沟通。

如有问题欢迎指正。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是一个使用 PyTorch 实现 Kaggle 房价预测比赛中的线性回归模型的示例代码: ``` import pandas as pd import torch import torch.nn as nn from sklearn.model_selection import train_test_split # 加载数据集 train_df = pd.read_csv('train.csv') test_df = pd.read_csv('test.csv') # 数据预处理 train_df.fillna(0, inplace=True) test_df.fillna(0, inplace=True) X = train_df.drop(['Id', 'SalePrice'], axis=1).values y = train_df['SalePrice'].values # 划分训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42) # 转换为 PyTorch 张量 X_train = torch.tensor(X_train, dtype=torch.float32) X_val = torch.tensor(X_val, dtype=torch.float32) y_train = torch.tensor(y_train.reshape(-1, 1), dtype=torch.float32) y_val = torch.tensor(y_val.reshape(-1, 1), dtype=torch.float32) # 定义模型 class LinearRegression(nn.Module): def __init__(self, input_dim, output_dim): super(LinearRegression, self).__init__() self.linear = nn.Linear(input_dim, output_dim) def forward(self, x): out = self.linear(x) return out model = LinearRegression(X_train.shape[1], 1) # 定义优化器和损失函数 criterion = nn.MSELoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 训练模型 num_epochs = 1000 for epoch in range(num_epochs): # 前向传播和计算损失 outputs = model(X_train) loss = criterion(outputs, y_train) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() # 每 100 次迭代输出一次损失 if (epoch+1) % 100 == 0: print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item())) # 在验证集上测试模型 with torch.no_grad(): predicted = model(X_val) mse = criterion(predicted, y_val) print('Mean Squared Error on Validation Set: {:.4f}'.format(mse.item())) # 在测试集上生成预测结果 X_test = test_df.drop(['Id'], axis=1).values X_test = torch.tensor(X_test, dtype=torch.float32) with torch.no_grad(): predicted = model(X_test) predicted = predicted.numpy().reshape(-1) # 生成提交文件 submission_df = pd.DataFrame({'Id': test_df['Id'], 'SalePrice': predicted}) submission_df.to_csv('submission.csv', index=False) ``` 这个代码使用 PyTorch 的 nn 模块定义了一个简单的线性回归模型,然后使用 SGD 优化器和 MSE 损失函数训练模型,并在验证集上评估模型性能。最后,使用训练好的模型在测试集上生成预测结果,然后将结果保存到 CSV 文件中用于提交比赛。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值