前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爱数课实验 | 第八期-新加坡房价预测模型构建

爱数课实验 | 第八期-新加坡房价预测模型构建

作者头像
数据科学人工智能
发布2022-06-27 18:22:58
9720
发布2022-06-27 18:22:58
举报

爱数课:idatacourse.cn

领域:消费

简介:数据来源于新加坡的爱彼迎民宿数据,数据共计7907条,16个字段。本次实验我们通过Python的绘图库进行可视化分析,查看特征的取值分布以及特征之间的关系。构建回归模型,根据民宿的经度、纬度、房屋类型、行政区划等特征对民宿价格进行预测。

数据:

./dataset/listings.csv

目录

1. 数据准备

1.1 数据集介绍

数据来源于新加坡的爱彼迎民宿数据,数据共计7907条,16个字段。本次实验我们通过Python的绘图库对数据集进行可视化分析,查看特征的取值分布以及特征之间的关系。构建回归模型,根据民宿的经度、纬度、房屋类型、行政区划等特征对民宿价格进行预测。各数据字段含义如下表所示:

列名

含义

id

房间编号

name

房间名称

host_id

房东编号

host_name

房东名称

neighbourhood_group

所属区域组

neighbourhood

行政区划

latitude

纬度

longitude

经度

room_type

房间类型(整套、独立房间、合租)

price

价格

minimum_nights

最少住几晚

number_of_reviews

评论数

last_review

上一次评论时间

reviews_per_month

平均每月评论数

calculated_host_listings_count

房东拥有的可出租房屋数

availability_365

一年内可租用天数

代码语言:javascript
复制
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('white')

import warnings
warnings.filterwarnings('ignore')
plt.rcParams['font.sans-serif']='SimHei'
%config InlineBackend.figure_format = 'svg'
%matplotlib inline

1.2 数据读取

首先将数据加载进来,对数据有一定了解。

代码语言:javascript
复制
flat_data = pd.read_csv('./dataset/listings.csv')

使用Pandas中的read_csv()函数可以读取csv文件,结果会保存为一个DataFrame或Series对象,通过调用DataFrame或Series对象的shape方法查看数据集大小,调用head()方法查看前n行数据,默认为5。

代码语言:javascript
复制
print(flat_data.shape)
flat_data.head()

(7907, 16)

通过调用DataFrame对象的info()方法打印DataFrame对象的摘要,包括列的数据类型dtype、名称以及有无缺失值,数据框的维度以及占用的内存等信息。

flat_data.info()

数据集房间名称name,上次评论时间last_review,平均每月的评论数reviews_per_month三个字段有缺失值的存在,所以需要对缺失值进行处理。

代码语言:javascript
复制
#查看评论数、上次评论时间、平均每月评论数三列
flat_data[['number_of_reviews','last_review','reviews_per_month']]

可以看到上次评论时间last_review,平均每月的评论数reviews_per_month两个字段之所以有缺失值是因为评论数为0,即没有评论。在建模前进行数据预处理时,可以删除上次评论时间last_review这一列,对平均每月的评论数reviews_per_month缺失值用0进行填充。

2. 统计和可视化

2.1 每个分类特征的数量柱状图

使用Seaborn中的barplot()函数绘制柱状图,展示每个分类特征的数量

代码语言:javascript
复制
plt.figure(figsize=(8,5))

#可视化每个分类特征的数量
count_uniq = []
columns = ['neighbourhood_group','neighbourhood', 'room_type']
for column in columns:
    #统计这三个字段不同值的数量
    count_uniq.append(flat_data[column].nunique())
print(count_uniq)
    
sns.barplot(x=columns, y=count_uniq,palette='Set3')
plt.title('每个分类特征数量柱状图')

从上图可以看出,所属区划组有5个不同取值,行政区域共有43个不同取值,房屋类型有3个不同取值。

2.2 价格分布直方图

下面使用Seaborn中的distplot()函数绘制直方图,展示价格的分布情况

代码语言:javascript
复制
plt.figure(figsize=(8,5))
sns.distplot(flat_data["price"])  # 直方图
plt.title('价格分布直方图')

整体来看,价格分布在0到10000之间,但房价在1000到10000之间的房间数量极少,房屋价格绝大部分都在1000以下。

2.3 查看不同房型的房屋数量

下面使用Seaborn中的countplot()函数绘制柱状图,展示不同房型的房屋数量

代码语言:javascript
复制
plt.figure(figsize=(8,5))
sns.countplot(flat_data['room_type'],palette='Set2')
plt.title('不同房型房屋数量')

数量最多的房型是整租,其次是独立房间的房型,最少的是合租的房型。整租和独立房间两种房型占比较大,可能更受欢迎,合租的房间数量最少。

2.4 房屋的区域分布柱状图

下面使用Seaborn中的countplot()函数绘制柱状图,展示房屋的区域分布

代码语言:javascript
复制
plt.figure(figsize=(8,5))
sns.countplot(flat_data["neighbourhood_group"])
plt.title('房屋的区域分布柱状图')

从上图结果可以看出更多的房子位于中心地区,其次是西部地区、东部地区、东北部地区,北部地区的房间数量最少。

2.5 不同区域房屋类型分组柱状图

下面使用Seaborn中的countplot()函数绘制柱状图,展示不同区域的房屋类型

代码语言:javascript
复制
plt.figure(figsize=(8,5))
sns.countplot(data = flat_data,x='room_type',hue='neighbourhood_group')
plt.title('不同区域房屋类型分组柱状图')

中心地区整租的房屋数量最多,其他地区独立房间的房型最多,绝大多数的合租的房型分布在中部地区,可能是由于中心地区房价较高等原因。

2.6 不同地区房价箱线图

下面使用Seaborn中的boxplot()函数绘制箱线图,展示不同地区房价情况

代码语言:javascript
复制
plt.figure(figsize=(8,5))
sns.boxplot(x = 'neighbourhood_group',
            y = 'price',
            data = flat_data[flat_data['price']<=500] #取价格在500以内的房子进行分析
           )
plt.title('不同地区房价箱线图')

从箱线图中观察到:中心区域的房子价格分布更为广泛,价格的均值也高于其他位置。北部地区的平均价格最低。

2.7 房屋类型与价格关系箱线图

下面使用Seaborn中的boxplot()函数绘制箱线图,展示房屋类型与价格的关系

代码语言:javascript
复制
plt.figure(figsize=(8,5))
sns.boxplot(x = 'room_type',
            y = 'price',
            data = flat_data[flat_data['price']<=500] #取价格在500以内的房子进行分析
           )
plt.title('房屋类型与价格关系箱线图')

整租类型的房屋价格分布区见更广,并且价格均值高于其他两种类型,合租的房型平均价格最低。

2.8 房屋经纬度分布散点图

下面使用Seaborn中的scatterplot()函数绘制散点图,展示房屋经纬度分布的情况

代码语言:javascript
复制
plt.figure(figsize=(10,7))
#x轴为经度值,y轴为纬度值
sns.scatterplot(flat_data['longitude'],flat_data['latitude'],
                hue=flat_data['neighbourhood_group'])
plt.title('房屋经纬度分布散点图')

橙色部分为中心地区的房屋情况,绿色为东部地区的房屋情况,红色为西部地区的房屋情况,紫色为东北部地区的房屋情况,蓝色为北部地区的房屋情况。中心地区的房屋数量多并且分布较为密集,北部地区的房屋数量最少并且分布也相对分散。

2.9 房屋价格分布散点图

下面使用Seaborn中的scatterplot()函数绘制散点图,展示房屋价格的分布情况

代码语言:javascript
复制
#可视化价格
plt.figure(figsize=(10,7))
#x轴为经度值,y轴为纬度值
sns.scatterplot(flat_data['longitude'], flat_data['latitude'],
                hue=flat_data['price'])
plt.title('房屋价格分布散点图')

价格较高的房屋大部分分布在中心地区和西部地区,东部地区、东北部地区和北部地区价格较高的房屋数量很少。

3. 数据预处理

3.1 删除不需要的列

通过调用DataFrame对象的drop()方法,并设置axis=1,删除房间编号id、房间名称name、房东编号host_id等列。

代码语言:javascript
复制
#删除一些不需要的列
flat_data = flat_data.drop(['id', 'name','host_id','host_name', 'last_review', 'neighbourhood'],
                           axis=1)

3.2 缺失值处理

通过调用DataFrame对象的fillna()方法,用0对缺失值进行填充。

代码语言:javascript
复制
#用0填充缺失的数据,即平均每月的评论数用0进行填充
flat_data = flat_data.fillna(0)
代码语言:javascript
复制
flat_data.isnull().sum()

3.3 数值编码

导入sklearn库中的preprocessing模块的LabelEncoder

代码语言:javascript
复制
from sklearn.preprocessing import LabelEncoder
cols = ["neighbourhood_group","room_type"] #需要进行数值编码的列

for col in cols:
    #使用LabelEncoder()新建一个对象,命名为le
    le = LabelEncoder() 
    #调用fit()方法,创建特征取值与编码结果的映射
    le.fit(flat_data[col]) 
    #调用transform()方法对数据进行转换,转换为编码后的结果
    flat_data[col] = le.transform(flat_data[col])
代码语言:javascript
复制
flat_data.head()

neighbourhood_grouproom_type列变换成0、1、2等数值。

4. LightGBM模型构建

4.1 对数变换

对数变换是一种常用的特征工程方法,一般对于数值大于0的长尾分布数据,可以采取对数变换的方法来转换特征值,整体上减缓长尾分布这种极偏的分布状态,为低值这一端争取更多的空间,将高值这一端尽可能的压缩,使得整体分布更加合理。进而增强模型的效果。

代码语言:javascript
复制
#去掉价格为0的数据
flat_data = flat_data[flat_data['price']>0]
flat_data['price'] = np.log10(flat_data['price'])
flat_data.head()
代码语言:javascript
复制
flat_data['price'].describe()

4.2 目标、特征划分

代码语言:javascript
复制
X = flat_data.drop('price', axis=1)
y = flat_data['price']

4.3 模型构建

代码语言:javascript
复制
import lightgbm
代码语言:javascript
复制
#新建一个LGBMRegressor()对象,命名为model
model = lightgbm.LGBMRegressor()
代码语言:javascript
复制
#设置参数
params = {'n_estimators': [10,20,30,50,100,200,500], #基学习器数量
               'subsample': [0.6, 0.7, 0.8, 0.9, 1.0], #训练时采样一定比例的数据
               'colsample_bytree': [0.6, 0.7, 0.8, 0.9, 1.0], #特征采样占比
               'learning_rate' : [0.01,0.03,0.1,0.2,0.3], #学习率
               'reg_lambda':[0,0.1,0.2,0.5,0.7,0.9,1] #L2正则化
              }
代码语言:javascript
复制
#随机参数搜索
from sklearn.model_selection import RandomizedSearchCV
#新建一个RandomizedSearchCV对象
#cv:交叉验证的折数,默认为5
lgbm_search_cv = RandomizedSearchCV(model, params, cv=5, scoring='neg_mean_absolute_error')

lgbm_search_cv调用fit方法,带入X,y进行训练。

代码语言:javascript
复制
lgbm_search_cv.fit(X,y)

通过调用best_estimator_查看最优模型。

代码语言:javascript
复制
lgbm_search_cv.best_estimator_

通过lgbm_search_cv.best_score_得到最好的得分即MAE值的负数,通过abs()方法得到绝对值,即模型的MAE值

代码语言:javascript
复制
abs(lgbm_search_cv.best_score_)

通过调用best_estimator_.feature_importances_查看各个特征的重要性。

代码语言:javascript
复制
# 特征重要性,降序排序
pd.Series(lgbm_search_cv.best_estimator_.feature_importances_, index=X.columns).sort_values(ascending=False)
代码语言:javascript
复制
#通过调用barplot()函数,绘制条形图将特征重要性进行展示
plt.figure(figsize=(8,5))
sns.barplot(x=lgbm_search_cv.best_estimator_.feature_importances_,y=X.columns,palette="Set2")

特征重要性首先是房屋的经度longitude,纬度latitude,两者重要性相差不大。其次是一年内可出租的天数availability_365,和房东拥有的可出租房屋数calculated_host_listings_count。特征重要性最低的是所属区域组neighbourhood_group

代码语言:javascript
复制
# 还原为真实预测值并计算绝对误差
y_true = 10**y
y_predict = 10**(lgbm_search_cv.best_estimator_.predict(X))
absolute_error = abs(y_true.values-y_predict) #计算绝对误差
#转换成DataFrame对象
pd.DataFrame({"true":y_true, "predict": y_predict , "absolute error":absolute_error}).head()

5. 总结

首先我们读取数据集,查看了数据的基本信息,对数据集有一个基本的了解。然后对数据进行统计与可视化,绘制价格分布直方图、不同房型房屋数量柱状图、不同地区房价箱线图、房屋经纬度分布散点图等。然后对数据进行预处理,包括缺失值处理、数值编码、目标列对数变换等。然后构建LightGBM回归模型,通过随机搜索进行参数调优,并查看最优模型的MAE的值。

爱数课(iDataCourse)是一个面向院校的大数据和人工智能课程和资源平台。平台提供权威的课程资源、数据资源、案例实验资源,助力院校大数据和人工智能专业建设,课程建设和师资能力建设。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据科学人工智能 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 1. 数据准备
    • 1.1 数据集介绍
      • 1.2 数据读取
      • 2. 统计和可视化
        • 2.1 每个分类特征的数量柱状图
          • 2.2 价格分布直方图
            • 2.3 查看不同房型的房屋数量
              • 2.4 房屋的区域分布柱状图
                • 2.5 不同区域房屋类型分组柱状图
                  • 2.6 不同地区房价箱线图
                    • 2.7 房屋类型与价格关系箱线图
                      • 2.8 房屋经纬度分布散点图
                        • 2.9 房屋价格分布散点图
                        • 3. 数据预处理
                          • 3.1 删除不需要的列
                            • 3.2 缺失值处理
                              • 3.3 数值编码
                              • 4. LightGBM模型构建
                                • 4.1 对数变换
                                  • 4.2 目标、特征划分
                                    • 4.3 模型构建
                                    • 5. 总结
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档