廣州鏈家二手房數(shù)據(jù)分析

分析目標(biāo)

1.了解廣州二手房各地區(qū)的房價情況
2.了解每個特征對房價的影響程度
3.對數(shù)據(jù)進(jìn)行建模,預(yù)測房價

數(shù)據(jù)獲取

從廣州鏈家網(wǎng)爬取共54573條數(shù)據(jù)至扰,數(shù)據(jù)特征如下:

price:二手房的總價格(萬元)

price_per_m2:二手房的每平米價格(元)

house_type:二手房的戶型

direction:二手房的朝向

area:二手房的面積

region:二手房所屬的區(qū)域

built_date:二手房建成時間

elevator:是否有電梯

floor:二手房的樓層

renovation:裝修情況

field:地段

xiaoqu:小區(qū)

數(shù)據(jù)導(dǎo)入

import pandas as pd
from pymongo import MongoClient
client = MongoClient('localhost')
db = client['lianjia']
def get_data():
    data = []
    for item in db['lianjiagz'].find():
        data.append(item)
    return data

data = get_data()
df = pd.DataFrame(data)
df.head()
1.png

首先查看數(shù)據(jù)整體情況纠俭,檢查是否存在缺失值雄可。

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 54573 entries, 0 to 54572
Data columns (total 12 columns):
price           54544 non-null object
price_pre_m2    54544 non-null object
house_type      54544 non-null object
direction       54544 non-null object
area            54544 non-null object
region          54544 non-null object
built_date      54544 non-null object
elevator        53593 non-null object
floor           54544 non-null object
renovation      54221 non-null object
field           54544 non-null object
xiaoqu          54544 non-null object
dtypes: object(12)
memory usage: 5.0+ MB

數(shù)據(jù)集總共包含54573條數(shù)據(jù)乌助,大部分特征都存在相同數(shù)量的缺失值呻率,推測是數(shù)據(jù)爬取失敗導(dǎo)致的空白躏将。此外電梯存在951條缺失值锄弱,裝修存在323條缺失值。

缺失值處理

刪除因爬取失敗導(dǎo)致的空白祸憋。

df.dropna(subset=['price'], inplace=True)

查看缺少evevator特征數(shù)據(jù)發(fā)現(xiàn)会宪,存在缺失的數(shù)據(jù),皆為地下室/低樓層/獨棟蚯窥,并非常規(guī)的商品房掸鹅,此處選擇將這些數(shù)據(jù)丟棄。

df.loc[df.elevator.isna(), ['elevator', 'floor']]
3.png
df.dropna(subset=['elevator'], inplace=True)
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 53593 entries, 0 to 54572
Data columns (total 12 columns):
price           53593 non-null object
price_pre_m2    53593 non-null object
house_type      53593 non-null object
direction       53593 non-null object
area            53593 non-null object
region          53593 non-null object
built_date      53593 non-null object
elevator        53593 non-null object
floor           53593 non-null object
renovation      53593 non-null object
field           53593 non-null object
xiaoqu          53593 non-null object
dtypes: object(12)
memory usage: 5.3+ MB

在處理elevator缺失值的過程中拦赠,renovation的缺失值也被舍棄了巍沙。

數(shù)據(jù)轉(zhuǎn)換

去除area的單位并轉(zhuǎn)換為float格式。

df.area = df.area.apply(lambda x: x.replace('平米', ''))
df.area = df.area.astype(float)

將x室x廳單獨提取出來荷鼠,創(chuàng)造兩個新特征句携,分別為living_room和room。

import re
def get_room(x):
    return re.search('(\d+)室.*?', x).group(1)

def get_living_room(x):
    return re.search('\d+室(\d+)廳', x).group(1)

df['room'] = df.house_type.apply(get_room).astype(int)
df['living_room'] = df.house_type.apply(get_living_room).astype(int)

將建成年份單獨提取出來允乐。

def get_built_year(x):
    if x.startswith('未知'):
        return pd.NaT
    else:
        return re.search('(\d+)年.*?', x).group(1)
df.built_date = df.built_date.apply(get_built_year)

對direction進(jìn)行處理矮嫉。查看direction數(shù)據(jù)可以發(fā)現(xiàn),存在一些奇怪的值牍疏,比如“東 東南 南 西南 西”這種無法理解的朝向蠢笋。編寫函數(shù)對direction處理后,每種方向只留下一個鳞陨。

from functools import reduce
def clean_direction(x):
    x = x.replace(' ', '')
    direction = []
    for i in x:
        if i not in direction:
            direction.append(i)
    direction.sort()
    return reduce(lambda x, y: x+y, direction)
df.direction = df.direction.apply(clean_direction)
df.direction.value_counts()
南       16989
北        9231
東南       7707
北南       4217
東        4041
東北       3275
南西       3012
北西       2092
西        2046
東西        380
東北南       206
北南西       118
東南西       116
東北南西      105
東北西        57
據(jù)數(shù)無暫        1
Name: direction, dtype: int64

將‘據(jù)數(shù)無暫’刪去昨寞。

df = df.loc[df.direction != '據(jù)數(shù)無暫', :]

處理floor特征,將低、中援岩、高樓層提取為floor_level特征熟史,將樓層總數(shù)提取為total_floor特征。

def get_floor_level(x):
    if re.search('(.*?)/.*?', x):
        return re.search('(.*?)/.*?', x).group(1)
    else:
        return pd.NaT

def get_total_floor(x):
    if re.search('.*?(\d+)層', x):
        return re.search('.*?(\d+)層', x).group(1)
    else:
        return pd.NaT
df['floor_level'] = df.floor.apply(get_floor_level)
df['total_floor'] = df.floor.apply(get_total_floor)

轉(zhuǎn)換后發(fā)現(xiàn)存在少量缺失值窄俏,此處選擇將缺失值刪去蹂匹。

df.floor_level.notna().value_counts()
False    53590
True         2
Name: floor_level, dtype: int64
df = df.loc[df.floor_level.notna(),:]

數(shù)據(jù)分析

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# 圖表正常顯示中文  
plt.rcParams['font.sans-serif']=['SimHei']
# 正常顯示符合
plt.rcParams['axes.unicode_minus']=False

描述性統(tǒng)計

df.describe()
4.png

可以看出,二手房平均總價為293.34萬元/套凹蜈,中位數(shù)為240萬元/套限寞。平均每平米房價為32125元/平米,中位數(shù)為29249元/平米仰坦。平均面積為91.1平米履植,最大面積為877.64平米∏幕危可以看出玫霎,由于一些超大戶型的影響,數(shù)據(jù)整體呈右偏趨勢妈橄。

房源數(shù)量分布

df.region.value_counts().sort_values(ascending=False)
番禺    10832
增城     7153
天河     6983
白云     6044
海珠     5928
花都     4574
越秀     3753
黃埔     2792
荔灣     2792
南沙     1701
從化     1038

數(shù)據(jù)可視化

plt.figure(figsize=(10, 5))
region_count = df.groupby('region', as_index=False).count().sort_values(by='price', ascending=False)
sns.barplot(x='region', y='price', data=region_count)
plt.title('各城區(qū)房源數(shù)量分布')
5.png

從化區(qū)房源最少庶近,不足2000套,番禺區(qū)房源最多眷蚓,超過10000套鼻种,其他區(qū)房源數(shù)量在2000-8000之間。其中番禺二手房源數(shù)量占全市全區(qū)二手房數(shù)量的20.21%沙热。

房源總面積及平均面積統(tǒng)計

房源總面積排序如下:

df.groupby('region').sum().area.sort_values(ascending=False)
番禺    1067891.33
增城     739562.84
天河     608179.56
白云     514934.24
花都     472354.17
海珠     465171.83
越秀     281218.75
黃埔     244319.00
荔灣     223256.17
南沙     169461.14

各城區(qū)二手房總面積分布柱形圖如下:

plt.figure(figsize=(10, 5))
area_sum = df.groupby('region', as_index=False).sum().sort_values(by='area', ascending=False)
sns.barplot(x='region', y='area', data=area_sum)
plt.title('各城區(qū)房源總面積分布')
6.png

各城區(qū)二手房面積分布基本與房源數(shù)量分布一致叉钥。
接下來查看各城區(qū)二手房平均面積分布。

df.groupby('region').mean().area.sort_values(ascending=False)
增城    103.391981
花都    103.269386
從化    102.541753
南沙     99.624421
番禺     98.586718
黃埔     87.506805
天河     87.094309
白云     85.197591
荔灣     79.962812
海珠     78.470282
越秀     74.931721

可視化

plt.figure(figsize=(10, 5))
area_mean = df.groupby('region', as_index=False).mean().sort_values(by='area', ascending=False)
sns.barplot(x='region', y='area', data=area_mean)
plt.title('各城區(qū)房源平均面積分布')
7.png

總體來說篙贸,增城投队、花都、從化爵川、南沙敷鸦、番禺等郊區(qū)的二手房平均面積相對較大,而黃埔雁芙、天河轧膘、白云、荔灣兔甘、海珠谎碍、越秀等老城區(qū)的二手房平均面積相對較小。推測可能原因為郊區(qū)土地價格較低洞焙,較低的成本允許開發(fā)商建造更大的戶型蟆淀。

全市房源戶型分布

以區(qū)間[0,50)拯啦、[50,100)、[100,150)熔任、[150,200)褒链、[200,+∞)為劃分標(biāo)準(zhǔn),將面積劃分為tinysmall疑苔、small甫匹、medium、big惦费、huge五個等級兵迅,分別對應(yīng)極小戶型、小戶型薪贫、中等戶型恍箭、大戶型和巨大戶型,并創(chuàng)造一個新特征值area_level瞧省。

df.loc[df.area < 50, 'area_level'] = 'tinysmall'
df.loc[(df.area >= 50) & (df.area < 100), 'area_level'] = 'small'
df.loc[(df.area >= 100) & (df.area < 150), 'area_level'] = 'medium'
df.loc[(df.area >= 150) & (df.area < 200), 'area_level'] = 'big'
df.loc[df.area >= 200, 'area_level'] = 'huge'

查看戶型分布情況

df.groupby('area_level').count().area.sort_values(ascending=False)
small        31401
medium       13443
tinysmall     5572
big           2231
huge           943

可視化

groupped_area_level = df.groupby('area_level').area.count().reset_index().sort_values(by='area',ascending=False)
plt.figure(figsize=(10,5))
plt.bar(groupped_area_level.area_level,groupped_area_level.area)
plt.title('上海市二手房戶型分布')
8.png

可見扯夭,廣州二手房以中小戶型為主,占總數(shù)的94%以上鞍匾,大戶型及超大戶型只占很小一部分交洗。

各城區(qū)二手房總價及單價分布

總價分布情況

plt.figure(figsize=(10, 5))
sns.boxplot(x='region', y='price', data=df)
plt.ylim(0, 1250)
plt.grid()
plt.title('各城區(qū)總價箱型圖')
9.png

各城區(qū)平均總價排名

天河    464.750766
越秀    383.557367
海珠    329.517072
荔灣    296.762178
白云    291.132429
番禺    278.156564
黃埔    268.663933
南沙    213.583892
增城    200.978499
花都    170.217403
從化    145.550482

1.天河平均總價排第一,為464.75萬元候学,箱型圖區(qū)間為[275, 550]藕筋, 中位數(shù)約為380萬元纵散,中位數(shù)比平均值小梳码,少數(shù)價格較高的數(shù)據(jù)把整體平均值拉高了,數(shù)據(jù)呈現(xiàn)右偏伍掀。
2.越秀平均總價排第二掰茶,為383.56萬元,箱型圖區(qū)間為[210蜜笤, 500]濒蒋,中位數(shù)約為370萬元,中位數(shù)與平均值相差不大把兔。
3.海珠沪伙、荔灣、白云二手房總價平均值和中位數(shù)都比較接近县好,且三者箱型圖下限也比較接近围橡,但箱型圖上限有所差別。

df.price.hist(bins=50)
plt.xlim(0, 3000)
10.png

約90%以上的二手房都在1000萬元以下缕贡,極少數(shù)房價突破1000萬元翁授。

單價分布情況

plt.figure(figsize=(10, 5))
sns.boxplot(x='region', y='price_pre_m2', data=df)
plt.ylim(0, 125000)
plt.grid()
plt.title('各城區(qū)單價箱型圖')
11.png

各城區(qū)平均單價排名

df.groupby('region').mean().price_pre_m2.sort_values(ascending=False)
天河    50782.225834
越秀    49305.911005
海珠    40221.435223
荔灣    35937.422994
白云    32755.814030
黃埔    29843.146848
番禺    27449.547360
南沙    21036.807760
增城    19520.788061
花都    16302.711412
從化    14006.782274

排名前三的分別是天河拣播,越秀,海珠收擦。
天河區(qū)均價為50782元贮配,價格區(qū)間大約為[38000, 60000]元。
越秀區(qū)均價為49305元塞赂,價格區(qū)間大約為[40000, 59000]元泪勒。
海珠區(qū)均價為40221元,價格區(qū)間大約為[32000, 48000]元宴猾。

plt.figure(figsize=(10, 5))
df.price_pre_m2.hist(bins=50)
plt.xlim(0, 150000)
plt.title('廣州市二手房單價分布')
12.png

二手房單價主要集中在60000元以下的區(qū)間酣藻,總體分布明顯右偏,存在少數(shù)價格高的數(shù)據(jù)嚴(yán)重拉高了單價均值鳍置。

各小區(qū)總價及單價排名

總價排名

首先過濾掉房源較少的小區(qū)辽剧,此處取20為閾值。

df1 = df.groupby('xiaoqu').count().area.reset_index().sort_values(by='area', ascending=False)
df1 = df1[df1.area > 20]
df1 = df.loc[df.xiaoqu.isin(df.xiaoqu)]
df1.groupby('xiaoqu', as_index=False).mean().sort_values(by='price', ascending=False)[:10]

查看總價均值排名前十的小區(qū)税产。

df1.groupby('xiaoqu').mean().price.sort_values(ascending=False)[:10]
嘉裕公館         1684.22
粵海麗江花園       1671.81
凱旋新世界楓丹麗舍    1563.47
中海璟暉華庭       1212.66
雋峰苑          1177.27
星匯云錦         1104.36
南國花園          951.25
東風(fēng)廣場          927.52
朱美拉公寓         909.83
西關(guān)海           895.60
plt.figure(figsize=(20, 5))
xiaoqu_price = df1.groupby('xiaoqu', as_index=False).mean().sort_values(by='price', ascending=False)[:10]
sns.barplot(x='xiaoqu', y='price', data=xiaoqu_price)
plt.title('全市總價排名前十的小區(qū)')
13.png

總價排名前10的小區(qū)均超過了895萬元怕轿,排前兩名的嘉裕公館和粵海麗江花園相差不大,總價都在1600萬元以上辟拷。

單價排名

xiaoqu_price_pre_m2 = df1.groupby('xiaoqu', as_index=False).mean().sort_values(by='price_pre_m2', ascending=False)[:10]
xiaoqu_price_pre_m2[['xiaoqu', 'price_pre_m2']]
14.png
plt.figure(figsize=(20, 5))
sns.barplot(x='xiaoqu', y='price_pre_m2', data=xiaoqu_price_pre_m2)
plt.title('全市單價排名前十的小區(qū)')
15.png

排名前十的小區(qū)單價均超過了8萬元/平米撞羽,其中嘉裕公館和凱旋新世界楓丹麗舍遙遙領(lǐng)先,其余小區(qū)之間的差距并不大衫冻。

房價與樓層的關(guān)系

plt.figure(figsize=(10, 5))
floor_level_price_per_m2 = df.groupby('floor_level', as_index=False).mean().sort_values(by='price_pre_m2', ascending=False)
sns.barplot(x='floor_level', y='price_pre_m2', data=floor_level_price_per_m2)
plt.title('不同樓層等級與房價的關(guān)系')
16.png

可以明顯看出诀紊,不同樓層等級之間,房價單價并沒有明顯的差距隅俘,都在30000元以上邻奠。不同樓層對房價沒有太大的影響。

plt.figure(figsize=(10, 5))
floor_price = df.groupby('total_floor', as_index=False).mean().sort_values(by='price_pre_m2', ascending=False)
sns.lineplot(x='total_floor', y='price_pre_m2', data=floor_price)
plt.title('不同樓層總數(shù)與房價的關(guān)系')
17.png

由上圖分析可知为居,隨著樓層數(shù)目的增加碌宴,房價也隨之升高。在40層之前蒙畴,房價隨樓層數(shù)增加而增加的趨勢比較線性贰镣,但是在這之后房價隨樓層數(shù)增加而增加的趨勢波動很大,可能的原因是樓層數(shù)超過40的住宅數(shù)量較小膳凝,超過40層的數(shù)據(jù)量比較小碑隆,容易產(chǎn)生誤差。

房價與朝向的關(guān)系

plt.figure(figsize=(20, 15))
direction_price = df.groupby('direction', as_index=False).mean().sort_values(by='price_pre_m2', ascending=False)
sns.barplot(x='direction', y='price_pre_m2', data=direction_price)
18.png

可以看出蹬音,朝向?qū)Ψ績r有一定的影響上煤,但由于朝向數(shù)值比較復(fù)雜,并不是單一的東南西北祟绊,無法具體推測房價到底受什么朝向影響楼入。

房價與戶型的關(guān)系

上文中已將戶型拆分為房間數(shù)(room)和客廳數(shù)(living_room)哥捕,下文將分別探索這兩個特征與房價的關(guān)系。

room

df.room.value_counts()
3     22674
2     19293
1      5897
4      4577
5       930
6       152
7        39
8        10
0         5
9         4
12        2
13        1
10        1

房間數(shù)以1-4個為主嘉熊,占全部數(shù)據(jù)的90%以上遥赚。此外,存在一些數(shù)據(jù)量較少的房間數(shù)阐肤,這里選擇將數(shù)量為100以下的房間數(shù)都刪去凫佛。

df2 = df.groupby('room').count().area.reset_index().sort_values(by='area', ascending=False)
df2 = df2[df2.area > 20]
df2 = df.loc[df.room.isin(df2.room)]
5    35080.61
6    33549.43
1    33417.01
4    33253.89
2    32815.55
3    30831.33
plt.figure(figsize=(10, 5))
df2.groupby('room').mean().sort_values(by='price_pre_m2', ascending=False)[:10].price_pre_m2.plot(kind='bar')
plt.title('房間數(shù)對房價的影響')
19.png

房間數(shù)量對房價影響程度較低,側(cè)面反映了在選購二手房時孕惜,買房對房間數(shù)量沒有特別的偏好愧薛。

living_room

df2.living_room.value_counts()
2    31221
1    20587
0     1441
3      253
4       18
5        3

客廳數(shù)量主要為0-3個,過濾掉不足20條數(shù)據(jù)的living_room衫画。

df3 = df2.groupby('living_room').count().area.reset_index().sort_values(by='area', ascending=False)
df3 = df3[df3.area > 20]
df3 = df.loc[df.living_room.isin(df3.living_room)]
df3.groupby('living_room').mean().price_pre_m2.sort_values(ascending=False)
1    33904.73
3    33371.71
0    33300.13
2    30885.00
plt.figure(figsize=(10, 5))
df3.groupby('living_room').mean().sort_values(by='price_pre_m2', ascending=False)[:10].price_pre_m2.plot(kind='bar')
plt.title('客廳數(shù)對房價的影響')
20.png

平均單價最高的是1客廳的小戶型毫炉,3客廳及0客廳緊隨其后,三者之間單價相差不大削罩。平均單價最低的是2客廳的戶型瞄勾。可能原因是弥激,隨著房價的上漲进陡,小戶型由于總價較低的原因,更受市場的青睞微服。

房屋與建成年代的關(guān)系

plt.figure(figsize=(10, 5))
df.groupby('built_date').count().area.plot()
plt.title('建成年份-房源數(shù)量分布')
21.png

圖形呈雙峰狀態(tài)趾疚,分別在1999年和2013年出現(xiàn)了兩個房屋建筑的高峰。

plt.figure(figsize=(10, 5))
df.groupby('built_date').mean().price.plot()
plt.title('建成年份-房屋平均總價')
22.png

1973年以前建成的房屋總價最高以蕴,可能原因是早年間房屋都在城市的核心區(qū)域即市中心建成糙麦。1973年后房價逐漸上升,在2009年達(dá)到高峰舒裤,之后開始下滑喳资。可能原因是腾供,1973年后房屋大多在郊區(qū)建成,由于較低的土地成本鲜滩,郊區(qū)的房屋面積更大伴鳖,總價便水漲船高。2009年后房屋總價逐漸下滑的原因可能是徙硅,09年后房屋大多在增城榜聂、從化等地建成,由于其相對其他城區(qū)較低的房價嗓蘑,房屋總價也在逐漸下降须肆。

plt.figure(figsize=(10, 5))
df.groupby('built_date').mean().price_pre_m2.plot()
plt.title('建成年份-房屋平均單價')
23.png

由建成年份-房屋單價圖可以看出匿乃,其趨勢符合上文的推測,即早年間的房屋建在市中心故單價較高豌汇。其后房屋大多建在郊區(qū)幢炸,單價逐漸下降。

電梯與房價的關(guān)系

df.loc[df.elevator == '暫無數(shù)據(jù)', ['elevator', 'total_floor']]
24.png

可以看出拒贱,elevator特征存在1043行缺失值宛徊,此處考慮基于樓層總數(shù)填補(bǔ)缺失值。一般默認(rèn)大于7層樓的住宅擁有電梯逻澳,小于7層樓的住宅沒有電梯闸天。此處將暫無數(shù)據(jù)進(jìn)行替換。

df.loc[(df.elevator == '暫無數(shù)據(jù)') & (df.total_floor > 7), 'elevator'] = 1
df.loc[(df.elevator == '暫無數(shù)據(jù)') & (df.total_floor <= 7), 'elevator'] = 0

查看一下電梯數(shù)量分布斜做。

plt.figure(figsize=(10, 5))
sns.countplot(x='elevator', data=df)
plt.title('電梯數(shù)量分布')
25.png

可以看出苞氮,超過60%的房屋都擁有電梯,無電梯的房屋數(shù)量只占有電梯的一半瓤逼。

plt.figure(figsize=(10, 5))
sns.barplot(x='elevator', y='price_pre_m2', data=df)
plt.title('電梯數(shù)量-房屋單價')
26.png

由圖看出葱淳,有電梯的房屋單價比沒有電梯的房屋單價要高,這也符合我們的常識抛姑。

特征工程

首先對categorical類型的特征進(jìn)行one-hot處理赞厕。

def get_dummies(column, prefix):
    global df
    dummies = pd.get_dummies(df[column], prefix=prefix)
    df = pd.concat([df, dummies], axis=1)
    
needed_get_dummies = ['renovation', 'direction', 'region', 'floor_level', 'field', 'xiaoqu', 'area_level']
for needed in needed_get_dummies:
    get_dummies(needed, prefix=needed)
    df.drop(needed, axis=1, inplace=True)

其次對連續(xù)型變量進(jìn)行標(biāo)準(zhǔn)化處理,此處用到的是MinMaxScaler

from sklearn.preprocessing import MinMaxScaler
def scaler(column):
    global df
    scaler = MinMaxScaler()
    df[column] = scaler.fit_transform(df[column].values.reshape(-1, 1))

needed_scale = ['area', 'room', 'living_room', 'total_floor']
for needed in needed_scale:
    scaler(needed)

將房屋單價作為模型的target定硝,并歸一化皿桑。

y = df.pop('price_pre_m2')
y = MinMaxScaler().fit_transform(y.values.reshape(-1, 1))
df.drop(['price', 'house_type', 'built_date', 'floor'], axis=1, inplace=True)

特征選擇

df.shape
(53585, 5400)

由于特征數(shù)量較多,需要用特征選擇蔬啡,選出有用變量诲侮,刪去無用變量∠潴。可以使用隨機(jī)森林沟绪、gbdt等模型進(jìn)行特征選擇。對于回歸問題空猜,通常采用的是方差或者最小二乘擬合绽慈。當(dāng)訓(xùn)練決策樹的時候,可以計算出每個特征減少了多少樹的不純度辈毯。對于一個決策樹森林來說坝疼,可以算出每個特征平均減少了多少不純度,并把它平均減少的不純度作為特征選擇的值谆沃。
此處采用的是gbdt模型進(jìn)行特征選擇钝凶,保留feature_importance累計前99%的特征。

from sklearn.ensemble import GradientBoostingRegressor
X = df.values
names = df.columns
def get_importance(X, y, names):
    gbdt = GradientBoostingRegressor(n_estimators=500)
    gbdt.fit(X, y)
    feature_importance = pd.Series(dict(zip(names, map(lambda x: round(x, 4), gbdt.feature_importances_))))
    return feature_importance
feature_importance = get_importance(X, y, names)
feature_importance = feature_importance.sort_values(ascending=False)
sum = 0
features = []
for k, v in enumerate(feature_importance):
    if sum > 0.99:
        break
    else:
        sum += v
        features.append(feature_importance.index[k])
print(len(features))
233

通過gbdt模型進(jìn)行特征選擇唁影,保留了233個特征耕陷。

X = df[features]

建模

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=0)

將數(shù)據(jù)分為訓(xùn)練集和測試集掂名,由于數(shù)據(jù)量有5萬多條,此處選擇測試集的test_size為0.1哟沫。用更多的數(shù)據(jù)進(jìn)行訓(xùn)練饺蔑。
使用keras建立神經(jīng)網(wǎng)絡(luò)模型。

import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense, BatchNormalization, Activation
from tensorflow.keras.optimizers import Adam, RMSprop, SGD
from tensorflow.keras.regularizers import l2
from tensorflow.keras.callbacks import ReduceLROnPlateau, ModelCheckpoint, LearningRateScheduler
def create_model():
  input = Input(shape=(X.shape[1],))
  x = Dense(128, kernel_regularizer=l2(0.1))(input)
  x = Activation('relu')(x)
  x = BatchNormalization(axis=-1)(x)
  x = Dense(256, kernel_regularizer=l2(0.1))(x)
  x = Activation('relu')(x)
  x = BatchNormalization(axis=-1)(x)
  x = Dense(256, kernel_regularizer=l2(0.1))(x)
  x = Activation('relu')(x)
  x = BatchNormalization(axis=-1)(x)
  x = Dense(128, kernel_regularizer=l2(0.1))(x)
  x = Activation('relu')(x)
  x = BatchNormalization(axis=-1)(x)
  x = Dense(64, kernel_regularizer=l2(0.1))(x)
  x = Activation('relu')(x)
  x = BatchNormalization(axis=-1)(x)
  x = Dense(64, kernel_regularizer=l2(0.1))(x)
  x = Activation('relu')(x)
  x = BatchNormalization(axis=-1)(x)
  x = Dense(1)(x)
  model = Model(inputs=input, outputs=x)
  return model

model = create_model()
model.compile(optimizer=SGD(1e-2), loss='mean_squared_error', metrics=['mse', 'mae'])

建立了一個7層神經(jīng)網(wǎng)絡(luò)模型南用,其每層神經(jīng)元數(shù)量分別是128,256,256,128,64,64,1膀钠。除了最后一層輸出層外,每一層都加入了一個l2正則項裹虫,正則化系數(shù)為0.1肿嘲,目的是防止過擬合。激活函數(shù)使用的是relu激活函數(shù)筑公,在激活函數(shù)后加入了一個batch normalization層雳窟,可以加快收斂速度。模型的優(yōu)化器使用sgd即隨機(jī)梯度下降匣屡,初始學(xué)習(xí)率定為1e-2封救,loss為均方差。

lrReduce = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=10)
filepath="/content/drive/My Drive/tmp/sgd4_weights-improvement-{epoch:03d}-{val_loss:.4f}.hdf5"
checkpoint= ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')

def scheduler(epoch):
  lr_base = 1e-2
  decay = 0.3
  lr = lr_base * (0.95 ** epoch)
  return lr
lrScheduler = LearningRateScheduler(scheduler)

為模型加入了三個回調(diào)對象捣作。分別是LearningRateScheduler即衰減學(xué)習(xí)率誉结。ReduceLROnPlateau用于監(jiān)視學(xué)習(xí)率,當(dāng)loss不再下降時券躁,將學(xué)習(xí)率減半惩坑。ModelCheckpoint,作用分別是保存最好的模型也拜。

history = model.fit(X_train, y_train, batch_size=128, epochs=200, validation_data=(X_test, y_test), callbacks=[lrReduce, checkpoint])

開始訓(xùn)練以舒,訓(xùn)練200個epochs,batch_size選128慢哈。

Epoch 00199: val_loss improved from 0.30553 to 0.30284, saving model to /content/drive/My Drive/tmp/sgd4_weights-improvement-199-0.3028.hdf5

訓(xùn)練完成后可見蔓钟,最小的驗證集誤差為0.30284。

mse = history.history['mean_squared_error']
val_mse = history.history['val_mean_squared_error']
plt.figure(figsize=(10, 5))
plt.plot(range(1, 201), mse, c='b', label='mse')
plt.plot(range(1, 201), val_mse, c='r', label='val_mse')
plt.grid()
plt.ylim(0, 3)
plt.legend()
image.png

繪制訓(xùn)練集-測試集誤差曲線卵贱,可以看出測試集誤差整體隨訓(xùn)練集誤差下降滥沫。在100個epoch前測試集誤差會有較大的波動,之后逐漸趨于平穩(wěn)艰赞,最終收斂不再下降佣谐。

from tensorflow.keras.models import load_model
model1 = load_model('/content/drive/My Drive/tmp/sgd4_weights-improvement-199-0.3028.hdf5')
print(r2_score(y_test, model1.predict(X_test)))
0.8750705820051174

模型在測試集上的r2系數(shù)為0.875,預(yù)測準(zhǔn)確度還算可以方妖。

總結(jié)

1.二手房單價受地理因素影響較大,不同城區(qū)之間房屋單價差異較大罚攀,最高的天河區(qū)平均單價為50782元/平米党觅,最低的從化區(qū)平均單價為14006元/平米同一城區(qū)不同小區(qū)的房屋單價也有較大的差異雌澄。最貴的小區(qū),房屋單價高達(dá)10萬元杯瞻,遠(yuǎn)遠(yuǎn)超過城區(qū)的均價镐牺。
2.二手房的數(shù)量和總面積可以反映市場的大小。番禺區(qū)二手房源數(shù)量10832套魁莉,占全市所有房源的20.21%睬涧,其二手房總面積為1067891.33平米為全市最高。不管從數(shù)量還是面積來看旗唁,番禺的二手房市場都是全區(qū)最大的畦浓,主要原因為其平均單價為27000元/平米,僅為天河區(qū)的一半检疫。
3.樓層讶请、戶型、朝向屎媳、電梯等要素對二手房的單價也有影響夺溢,但影響并不顯著。
4.建成年份可以反映房屋的建造時間烛谊,進(jìn)一步可以推測房屋大概的建造地點风响,從而推測房價。越早建成的房屋越傾向于建于市中心丹禀,反之則傾向于建在郊區(qū)状勤。
5.模型對測試集的r2系數(shù)為0.875,不算特別好湃崩。后續(xù)可以通過爬取更多的特征荧降、創(chuàng)建更多的特征、優(yōu)化模型結(jié)構(gòu)攒读、調(diào)參等方式來優(yōu)化模型的表現(xiàn)朵诫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市薄扁,隨后出現(xiàn)的幾起案子剪返,更是在濱河造成了極大的恐慌,老刑警劉巖邓梅,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脱盲,死亡現(xiàn)場離奇詭異,居然都是意外死亡日缨,警方通過查閱死者的電腦和手機(jī)钱反,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人面哥,你說我怎么就攤上這事哎壳。” “怎么了尚卫?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵归榕,是天一觀的道長。 經(jīng)常有香客問我吱涉,道長刹泄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任怎爵,我火速辦了婚禮特石,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疙咸。我一直安慰自己县匠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布撒轮。 她就那樣靜靜地躺著乞旦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪题山。 梳的紋絲不亂的頭發(fā)上兰粉,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機(jī)與錄音顶瞳,去河邊找鬼玖姑。 笑死,一個胖子當(dāng)著我的面吹牛慨菱,可吹牛的內(nèi)容都是我干的焰络。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼符喝,長吁一口氣:“原來是場噩夢啊……” “哼闪彼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起协饲,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤畏腕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后茉稠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體描馅,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年而线,在試婚紗的時候發(fā)現(xiàn)自己被綠了铭污。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恋日。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖况凉,靈堂內(nèi)的尸體忽然破棺而出枪蘑,到底是詐尸還是另有隱情嚷往,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布坊罢,位于F島的核電站烤黍,受9級特大地震影響知市,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜速蕊,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一嫂丙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧规哲,春花似錦跟啤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至袄简,卻和暖如春腥放,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绿语。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工秃症, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吕粹。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓种柑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親匹耕。 傳聞我的和親對象是個殘疾皇子聚请,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容