Sklearn:房租租⾦模型預測 版本二

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)


Sklearn:房租租⾦模型預測 版本一

Sklearn:房租租⾦模型預測 版本二 


數據集下載鏈接:https://pan.baidu.com/s/13OtaUv6j4x8dD7cgD4sL5g 
提取碼:7tze 


庫安裝:pip install xgboost


數據初步分析 

In [1]:

import matplotlib.pyplot as plt

import pandas as pd

import numpy as np

import seaborn as sns

import warnings

warnings.filterwarnings('ignore')#忽略一些警告

# plt.rcParams['font.sans-serif']=['SimHei']

# plt.rcParams['axes.unicode_minus']=False

導入數據

In [2]:

train=pd.read_csv("data/train.csv")

test=pd.read_csv("data/test.csv")

train.head()

Out[2]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金
0 1 3072 0.128906 2 0.236364 0.008628 東南 NaN 1 1 1 NaN 11.0 118.0 2.0 40.0 0.764167 NaN 5.602716
1 1 3152 0.132812 1 0.381818 0.017046 NaN 1 0 0 NaN 10.0 100.0 4.0 58.0 0.709167 NaN 16.977929
2 1 5575 0.042969 0 0.290909 0.010593 東南 NaN 2 1 2 NaN 12.0 130.0 5.0 37.0 0.572500 NaN 8.998302
3 1 3103 0.085938 2 0.581818 0.019199 NaN 3 2 2 NaN 7.0 90.0 2.0 63.0 0.658333 NaN 5.602716
4 1 5182 0.214844 0 0.545455 0.010427 東北 NaN 2 1 1 NaN 3.0 31.0 NaN NaN NaN NaN 7.300509

In [4]:

train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 196539 entries, 0 to 196538
Data columns (total 19 columns):
時間          196539 non-null int64
小區名         196539 non-null int64
小區房屋出租數量    195538 non-null float64
樓層          196539 non-null int64
總樓層         196539 non-null float64
房屋面積        196539 non-null float64
房屋朝向        196539 non-null object
居住狀態        20138 non-null float64
臥室數量        196539 non-null int64
廳的數量        196539 non-null int64
衛的數量        196539 non-null int64
出租方式        24230 non-null float64
區           196508 non-null float64
位置          196508 non-null float64
地鐵線路        91778 non-null float64
地鐵站點        91778 non-null float64
距離          91778 non-null float64
裝修情況        18492 non-null float64
月租金         196539 non-null float64
dtypes: float64(12), int64(6), object(1)
memory usage: 28.5+ MB

In [5]:

train.describe()

Out[5]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金
count 196539.000000 196539.000000 195538.000000 196539.000000 196539.000000 196539.000000 20138.000000 196539.000000 196539.000000 196539.000000 24230.000000 196508.000000 196508.000000 91778.000000 91778.000000 91778.000000 18492.000000 196539.000000
mean 2.115229 3224.116562 0.124151 0.955449 0.408711 0.013139 2.725196 2.236635 1.299625 1.223818 0.900289 7.905139 67.945982 3.284850 57.493735 0.551202 3.589228 7.949313
std 0.786980 2023.073726 0.133299 0.851511 0.183100 0.008104 0.667763 0.896961 0.613169 0.487234 0.299621 4.025696 43.522394 1.477147 35.191414 0.247268 1.996912 6.310609
min 1.000000 0.000000 0.007812 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1.000000 0.001667 1.000000 0.000000
25% 1.000000 1388.000000 0.039062 0.000000 0.290909 0.009268 3.000000 2.000000 1.000000 1.000000 1.000000 4.000000 33.000000 2.000000 23.000000 0.356667 2.000000 4.923599
50% 2.000000 3086.000000 0.082031 1.000000 0.418182 0.012910 3.000000 2.000000 1.000000 1.000000 1.000000 9.000000 61.000000 4.000000 59.000000 0.554167 2.000000 6.621392
75% 3.000000 5199.000000 0.160156 2.000000 0.563636 0.014896 3.000000 3.000000 2.000000 1.000000 1.000000 11.000000 103.000000 5.000000 87.000000 0.745833 6.000000 8.998302
max 3.000000 6627.000000 1.000000 2.000000 1.000000 1.000000 3.000000 11.000000 8.000000 8.000000 1.000000 14.000000 152.000000 5.000000 119.000000 1.000000 6.000000 100.000000

數據探索

基本信息

In [6]:

train.head()

Out[6]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金
0 1 3072 0.128906 2 0.236364 0.008628 東南 NaN 1 1 1 NaN 11.0 118.0 2.0 40.0 0.764167 NaN 5.602716
1 1 3152 0.132812 1 0.381818 0.017046 NaN 1 0 0 NaN 10.0 100.0 4.0 58.0 0.709167 NaN 16.977929
2 1 5575 0.042969 0 0.290909 0.010593 東南 NaN 2 1 2 NaN 12.0 130.0 5.0 37.0 0.572500 NaN 8.998302
3 1 3103 0.085938 2 0.581818 0.019199 NaN 3 2 2 NaN 7.0 90.0 2.0 63.0 0.658333 NaN 5.602716
4 1 5182 0.214844 0 0.545455 0.010427 東北 NaN 2 1 1 NaN 3.0 31.0 NaN NaN NaN NaN 7.300509

 

缺失值比例

In [7]:

train_missing = (train.isnull().sum()/len(train))*100# 每列的缺失值個數/總行數

train_missing = train_missing.drop(train_missing[train_missing==0].index).sort_values(ascending=False)#去掉缺失比例爲0的列

miss_data = pd.DataFrame({'缺失百分比':train_missing})

miss_data

Out[7]:

  缺失百分比
裝修情況 90.591180
居住狀態 89.753688
出租方式 87.671658
距離 53.302907
地鐵站點 53.302907
地鐵線路 53.302907
小區房屋出租數量 0.509314
位置 0.015773
0.015773

目標值分佈

In [8]:

plt.figure(figsize=(12,6))

plt.subplot(211)

plt.title('月租金分佈')

sns.distplot(train['月租金'])#價格的數量分佈曲線

plt.subplot(212)

plt.scatter(range(train.shape[0]),np.sort(train['月租金'].values))

plt.show()

所有特徵分佈

直方圖和柱狀分佈圖

In [9]:

train.hist(figsize=(20,20),bins=50,grid=False)

plt.show()

相關性分析

連續特徵和目標值的散點圖

In [10]:

train.columns

Out[10]:

Index(['時間', '小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積', '房屋朝向', '居住狀態', '臥室數量',
       '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', '月租金'],
      dtype='object')

In [11]:

#通過散點圖觀察特徵和目標值之間的關係

continuous_cols=['時間','小區房屋出租數量', '總樓層','房屋面積',  '臥室數量',

       '廳的數量', '衛的數量', '距離']

for col in continuous_cols:

    sns.jointplot(x=col,y='月租金',data=train,alpha=0.3,size=4)

特徵和目標相關性分析

皮爾森相關性熱力圖

In [12]:

columns=['時間', '小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積', '房屋朝向', '居住狀態', '臥室數量',

       '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', '月租金']

corrmat = train.corr()#計算皮爾森相關性

plt.figure(figsize=(12,12))

sns.heatmap(corrmat, vmax=.8, square=True,annot=True);

 

皮爾森相關

In [13]:

plt.figure(figsize=(12,6))

train.corr()['月租金'][continuous_cols].sort_values(ascending=False).plot(

    'barh',figsize=(12,6),title='特徵和月租金皮爾森相關性分析'

)

plt.show()

斯皮爾曼相關

In [14]:

from scipy.stats import spearmanr

rs=[]

for key in continuous_cols:

    r,p=spearmanr(train[key],train['月租金']) #計算特徵與目標值之間的斯皮爾曼相關性

    rs.append(r)

rs=pd.Series(data=rs,index=continuous_cols).dropna()

rs.sort_values(ascending=False).plot(

    'barh',figsize=(12,6),title='特徵和月租金斯皮爾曼相關性分析'

)

plt.show()

離散特徵和月租金關係分析

均值比較

In [15]:

import math

#負責繪製每個特徵不同組的月租金均值圖

def plot(names,ylabel,data,cols=3):

    n=len(data)

    rows=math.ceil(n/cols)

    fig,ax=plt.subplots(nrows=rows,ncols=cols,figsize=(20,rows*8))

    for i in range(n):

        x=range(data[i].shape[0])

        y=data[i].values

        xticks=data[i].index

        r=i//cols

        c=i%cols

        ax[r][c].bar(x,y)

        ax[r][c].set_xticks(x)

        ax[r][c].set_xticklabels(xticks)

        ax[r][c].set_xlabel(names[i])

        ax[r][c].set_ylabel(ylabel)

        ax[r][c].set_title(names[i]+str(i)+ylabel+"均值比較")

    plt.show()  

In [16]:

category_cols=['時間','小區名','樓層',  '房屋朝向', '居住狀態', 

       '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '裝修情況']

means=[]        

for key in category_cols:

    means.append(train.groupby(key)['月租金'].mean())

In [17]:

plot(category_cols,"月租金",means)

繪製箱線圖

In [18]:

def plot_box(names,x,data,cols=1):

    n=len(names)

    for i in range(n):

        plt.figure(figsize=(12,10))

        sns.boxplot(y=names[i],x=x,data=data,orient='h')#繪製箱線圖

        plt.show()

In [19]:

category_cols2=['時間','樓層', '居住狀態', 

       '出租方式', '區',  '地鐵線路',  '裝修情況']

plot_box(category_cols2,"月租金",train)

異常值分析

這裏我們主要分析跟月租金相關性較大的房屋面積的異常值

In [20]:

def plot_reg(xs,y,data,cols=1):

    n=len(xs)

    for i in range(n):

        plt.figure(figsize=(10,10))

        sns.regplot(x=data[xs[i]],y=data[y])

        plt.show()

In [21]:

reg_cols=['房屋面積']

plot_reg(reg_cols,"月租金",train)

問題數據

房間朝向列有多個值

In [22]:

train['房屋朝向'].value_counts()

Out[22]:

南            54770
東南           54359
東            31962
西南           17470
北            10428
             ...  
東南 南 西南 西        1
東 西南 北           1
東南 西 北           1
南 西南 西 西北        1
西南 西 東北          1
Name: 房屋朝向, Length: 64, dtype: int64

In [24]:

def split(text,i):

    """

    實現對字符串進行分割,並取出結果中下標i對應的值

    """

    items=text.split(" ")

    if i<len(items):

        return items[i]

    else:

        return np.nan

for i in range(5):

    train['朝向_'+str(i)]=train['房屋朝向'].map(lambda x:split(x,i))

# train['房屋地鐵站點朝向'].map(lambda x:x.split(" ")).map(lambda x:len(x)).max()

In [ ]:

names=["朝向_{}".format(i) for i in range(5)]

train[names].info()

同一個小區屬於不同的區

In [25]:

train.columns

Out[25]:

Index(['時間', '小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積', '房屋朝向', '居住狀態', '臥室數量',
       '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', '月租金',
       '朝向_0', '朝向_1', '朝向_2', '朝向_3', '朝向_4'],
      dtype='object')

In [26]:

#去掉'小區名','區','位置'三個列重複之後  有5578個不重複值

neighbors1=train[['小區名','區','位置']]

neighbors1.shape

Out[26]:

(196539, 3)

In [27]:

#去掉'小區名','區','位置'三個列重複之後  有5577個不重複值

neighbors1=train[['小區名','位置']].drop_duplicates().dropna()

neighbors1.shape

Out[27]:

(5577, 2)

In [28]:

#而有位置的小區名只有5547個不重複值  說明有31個小區位於不同的位置

train[train['位置'].notnull()].drop_duplicates(['小區名']).shape

Out[28]:

(5546, 24)

In [29]:

#neighbors1按照小區名分組後保留分組條數大於1的小區名

count=neighbors1.groupby('小區名')['位置'].count()

ids=count[count>1].index

ids

Out[29]:

Int64Index([ 284,  385,  418,  701,  783, 1455, 1870, 2228, 2468, 2513, 2611,
            2916, 3183, 3268, 3482, 3645, 3967, 4054, 4071, 4471, 4767, 4859,
            5320, 5699, 5844, 5968, 6020, 6122, 6515, 6626, 6627],
           dtype='int64', name='小區名')

In [30]:

#在原數據中篩選出這些小區的信息

neighbors_has_problem=train[['小區名','位置']][train['小區名'].isin(ids)].sort_values(by='小區名')

neighbors_has_problem

Out[30]:

  小區名 位置
105800 284 102.0
105988 284 102.0
105228 284 102.0
105076 284 102.0
105074 284 102.0
... ... ...
131530 6627 86.0
158621 6627 136.0
56569 6627 86.0
39956 6627 86.0
161162 6627 136.0

843 rows × 2 columns

In [31]:

#找到每個小區的位置衆數

#這裏要注意x.mode有可能返回多個衆數,所以用一個np.max拿到最值最大的衆數作爲最終的結果

position_mode_of_neighbors=neighbors_has_problem.groupby('小區名').apply(lambda x:np.max(x['位置'].mode()))

#位置缺失值就用這個數據來進行填充,對於已有的一個小區位於不同的位置,考慮到可能是因爲小區太大導致,並不能認爲是邏輯錯誤,保持不變

position_mode_of_neighbors

Out[31]:

小區名
284     102.0
385     108.0
418     122.0
701      92.0
783     134.0
1455     40.0
1870    106.0
2228    101.0
2468     43.0
2513     86.0
2611    112.0
2916     31.0
3183    136.0
3268     86.0
3482     64.0
3645    121.0
3967    100.0
4054      1.0
4071    129.0
4471     15.0
4767     18.0
4859     73.0
5320     95.0
5699    120.0
5844    143.0
5968     40.0
6020    109.0
6122     18.0
6515    130.0
6626     86.0
6627     86.0
dtype: float64

同一個小區地鐵線路不同的問題

In [32]:

#去掉'小區名','地鐵線路'兩個列重複之後  有3412個不重複值

lines=train[['小區名','地鐵線路']].drop_duplicates().dropna()

lines.shape

Out[32]:

(3412, 2)

In [33]:

#而有地鐵的小區名只有3330個不重複值  說明有112個小區有多個地鐵線路

train[train['地鐵線路'].notnull()].drop_duplicates(['小區名']).shape

Out[33]:

(3330, 24)

In [34]:

#lines按照小區名分組後保留分組條數大於1的小區名   最終有多條地鐵的小區有79個

#這個地鐵線路分位置可能有關係  因爲同一個小區位於不同的位置,地鐵線路也有可能不同

count=lines.groupby('小區名')['地鐵線路'].count()

ids=count[count>1].index

ids.shape

Out[34]:

(79,)

研究一下位置和地鐵線路的關係

In [35]:

#去掉'位置','地鐵線路'兩個列重複之後  有184個不重複值

pos_lines=train[['位置','地鐵線路']].drop_duplicates().dropna()

pos_lines.shape

Out[35]:

(184, 2)

In [36]:

#我們在來看一下有地鐵的位置中有多少個不同的   120個    

pos_lines['位置'].value_counts()

Out[36]:

113.0    4
100.0    4
118.0    3
63.0     3
106.0    3
        ..
22.0     1
34.0     1
151.0    1
28.0     1
99.0     1
Name: 位置, Length: 120, dtype: int64

In [37]:

#pos_lines按照位置分組後保留分組條數大於1的位置  最終有多條地鐵的位置有49個

count=pos_lines.groupby('位置')['地鐵線路'].count()

ids=count[count>1].index

ids.shape

Out[37]:

(49,)

研究一下位置和地鐵站點的關係

In [38]:

#去掉'位置','地鐵站點'兩個列重複之後  有339個不重複值

pos_stations=train[['位置','地鐵站點']].drop_duplicates().dropna()

pos_stations.shape

Out[38]:

(339, 2)

In [39]:

#我們在來看一下有地鐵的位置中有多少個不同的   120個    

pos_stations['位置'].value_counts()

Out[39]:

63.0     9
136.0    7
106.0    6
100.0    6
143.0    6
        ..
17.0     1
12.0     1
67.0     1
82.0     1
148.0    1
Name: 位置, Length: 120, dtype: int64

In [40]:

#pos_stations按照位置分組後保留分組條數大於1的位置  最終有多個站點的位置有97個

count=pos_stations.groupby('位置')['地鐵站點'].count()

ids=count[count>1].index

ids.shape

Out[40]:

(97,)

研究一下小區名,位置,地鐵線路,站點的關係

In [41]:

#去掉'位置','地鐵站點'兩個列重複之後  有3575個不重複值

neighbor_pos_stations=train[['小區名','位置','地鐵線路','地鐵站點']].drop_duplicates().dropna()

neighbor_pos_stations.shape

Out[41]:

(3575, 4)

In [42]:

 

#看一下是否存在下小區名,位置一樣的情況下,地鐵線路不一樣的情況

#可以看出:3575-3414=161條小區名,位置,地鐵線路同樣的情況下,地鐵站點不一樣

#3414-3342=72條小區名,位置一樣,地鐵線路不一樣

#這種情況可能是因爲數據錯誤,也有可能是實際情況,後面對此我們不做處理

print(neighbor_pos_stations[['小區名','位置','地鐵線路']].drop_duplicates().dropna().shape)

print(neighbor_pos_stations[['小區名','位置']].drop_duplicates().dropna().shape)

(3414, 3)
(3342, 2)

研究一下是否有換乘站的存在

用站點分組,然後統計地鐵線路數

In [43]:

#結果說明沒有換乘站點存在,因爲每個站點僅僅屬於一條地鐵線路

train[['地鐵線路','地鐵站點']].drop_duplicates().dropna().groupby('地鐵站點').count().max(0)

Out[43]:

地鐵線路    1
dtype: int64

研究一下每個位置的地鐵線路數和站點數

In [44]:

#每個位置的線路數 這個可以作爲新特徵加入

a=train[['位置','地鐵線路']].drop_duplicates().dropna().groupby('位置').count()

a

Out[44]:

  地鐵線路
位置  
0.0 1
1.0 2
2.0 1
3.0 2
4.0 1
... ...
146.0 2
147.0 2
148.0 1
150.0 1
151.0 1

120 rows × 1 columns

In [45]:

#每個位置的站點數   也可以作爲新特徵加入

b=train[['位置','地鐵站點']].drop_duplicates().dropna().groupby('位置').count()

b

Out[45]:

  地鐵站點
位置  
0.0 1
1.0 3
2.0 1
3.0 4
4.0 1
... ...
146.0 3
147.0 2
148.0 1
150.0 4
151.0 1

120 rows × 1 columns

In [46]:

#兩者的相關性

al=pd.concat([a,b],axis=1)

al.corr()

Out[46]:

  地鐵線路 地鐵站點
地鐵線路 1.000000 0.685211
地鐵站點 0.685211 1.000000

 

研究一下位置缺失的樣本地鐵站點是否也是缺失的

In [47]:

#發現存在地鐵線路爲缺失而位置缺失的情況   說明後面在填充位置缺失值的時候可以用地鐵站點來進行填充

pos_lines=train[['位置','地鐵站點']].drop_duplicates()

pos_lines['位置'].isnull().sum()

Out[47]:

15

In [48]:

#每個站點的位置數   也可以作爲新特徵加入

train[['位置','地鐵站點']].drop_duplicates().dropna().groupby('地鐵站點').count()

Out[48]:

  位置
地鐵站點  
1.0 4
2.0 1
3.0 5
4.0 1
5.0 5
... ...
115.0 3
116.0 2
117.0 1
118.0 2
119.0 4

118 rows × 1 columns

位置和區的關係校驗

In [49]:

#說明每個位置僅僅屬於一個區,不存在同一個位置屬於兩個區的現象

train[['位置','區']].drop_duplicates().dropna().groupby('位置').count().max()

Out[49]:

區    1
dtype: int64

小區名和位置的關係

In [50]:

train[train['小區名']==6626]

Out[50]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 ... 地鐵線路 地鐵站點 距離 裝修情況 月租金 朝向_0 朝向_1 朝向_2 朝向_3 朝向_4
1513 1 6626 0.050781 0 0.581818 0.009070 NaN 1 1 ... 1.0 10.0 0.965000 NaN 5.942275 NaN NaN NaN NaN
6622 1 6626 0.050781 2 0.545455 0.022840 NaN 3 3 ... 5.0 16.0 0.974167 NaN 4.244482 NaN NaN NaN NaN
10951 1 6626 0.050781 0 0.581818 0.009103 西 NaN 1 1 ... 1.0 10.0 0.965000 NaN 5.602716 西 NaN NaN NaN NaN
12327 1 6626 0.050781 1 0.545455 0.014234 東南 NaN 3 1 ... 5.0 16.0 0.974167 NaN 6.960951 東南 NaN NaN NaN NaN
14738 1 6626 0.050781 1 0.545455 0.008039 NaN 1 1 ... 5.0 16.0 0.974167 NaN 5.602716 NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
177641 3 6626 0.085938 0 0.545455 0.014068 東南 1.0 2 1 ... 5.0 16.0 0.974167 2.0 7.300509 東南 NaN NaN NaN NaN
177725 3 6626 0.085938 1 0.545455 0.014234 東南 NaN 3 1 ... 5.0 16.0 0.974167 NaN 6.960951 東南 NaN NaN NaN NaN
191611 3 6626 0.085938 1 0.545455 0.014730 3.0 3 2 ... 5.0 16.0 0.974167 6.0 8.998302 NaN NaN NaN NaN
194534 3 6626 0.085938 2 0.581818 0.013846 東南 3.0 2 1 ... 1.0 10.0 0.965000 2.0 8.319185 東南 NaN NaN NaN NaN
195236 3 6626 0.085938 0 0.581818 0.012744 東南 NaN 2 1 ... 1.0 10.0 0.965000 NaN 5.602716 東南 NaN NaN NaN NaN

105 rows × 24 columns

In [51]:

#在數據清洗的過程中發現一個問題  3269這個小區可能比較特殊
train[train['小區名']==3269].shape

Out[51]:

(31, 24)

In [52]:

#正好位置缺失31條
train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 196539 entries, 0 to 196538
Data columns (total 24 columns):
時間          196539 non-null int64
小區名         196539 non-null int64
小區房屋出租數量    195538 non-null float64
樓層          196539 non-null int64
總樓層         196539 non-null float64
房屋面積        196539 non-null float64
房屋朝向        196539 non-null object
居住狀態        20138 non-null float64
臥室數量        196539 non-null int64
廳的數量        196539 non-null int64
衛的數量        196539 non-null int64
出租方式        24230 non-null float64
區           196508 non-null float64
位置          196508 non-null float64
地鐵線路        91778 non-null float64
地鐵站點        91778 non-null float64
距離          91778 non-null float64
裝修情況        18492 non-null float64
月租金         196539 non-null float64
朝向_0        196539 non-null object
朝向_1        9285 non-null object
朝向_2        322 non-null object
朝向_3        45 non-null object
朝向_4        4 non-null object
dtypes: float64(12), int64(6), object(6)
memory usage: 36.0+ MB

我們看一下小區名和位置,地鐵站點的關係

上面可以看出3269這個小區位置缺失,但是我們發現他的地鐵線路和站點非常多,這有些異常,我們對比一下其他小區的情況

In [53]:

#可以看出,正常的小區最多屬於不同的2個位置

train[['位置','小區名']].drop_duplicates().dropna().groupby('小區名').count().max()

Out[53]:

位置    2
dtype: int64

In [54]:

#可以看出,除了3269這個小區外,其他小區最多隻有4個站點相關

#因此可以斷定3269這個小區是統計不祥的數據,可以作爲異常值丟棄

counts=train[['地鐵站點','小區名']].drop_duplicates().dropna().groupby('小區名').count()

counts[counts['地鐵站點']>3]

Out[54]:

  地鐵站點
小區名  
602 4
1728 4
3269 14

看一下小區名過多的問題

In [4]:

neighbors=train['小區名'].value_counts()

In [5]:

neighbors

Out[5]:

5512    1880
1085    1155
5208    1136
6221    1066
6011    1020
        ... 
5829       1
1351       1
711        1
327        1
0          1
Name: 小區名, Length: 5547, dtype: int64

In [8]:

#觀察條目數超過50的小區有多少

(neighbors>50).sum()

Out[8]:

933

In [9]:

#觀察條目數超過100的小區有多少

(neighbors>100).sum()

Out[9]:

511

數據清洗

In [8]:

import matplotlib.pyplot as plt

import pandas as pd

import numpy as np

import seaborn as sns

import warnings

warnings.filterwarnings('ignore')#忽略一些警告

#顯示所有結果

plt.rcParams['font.sans-serif']=['SimHei']

plt.rcParams['axes.unicode_minus']=False

 

導入數據

In [66]:

train=pd.read_csv("data/train.csv")

test=pd.read_csv("data/test.csv")

train.head()

Out[66]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金
0 1 3072 0.128906 2 0.236364 0.008628 東南 NaN 1 1 1 NaN 11.0 118.0 2.0 40.0 0.764167 NaN 5.602716
1 1 3152 0.132812 1 0.381818 0.017046 NaN 1 0 0 NaN 10.0 100.0 4.0 58.0 0.709167 NaN 16.977929
2 1 5575 0.042969 0 0.290909 0.010593 東南 NaN 2 1 2 NaN 12.0 130.0 5.0 37.0 0.572500 NaN 8.998302
3 1 3103 0.085938 2 0.581818 0.019199 NaN 3 2 2 NaN 7.0 90.0 2.0 63.0 0.658333 NaN 5.602716
4 1 5182 0.214844 0 0.545455 0.010427 東北 NaN 2 1 1 NaN 3.0 31.0 NaN NaN NaN NaN 7.300509

In [67]:

train.shape

Out[67]:

(196539, 19)

In [68]:

# train["出租方式"].value_counts()

# train["裝修情況"].value_counts()

train["居住狀態"].value_counts()

Out[68]:

3.0    17087
1.0     2483
2.0      568
Name: 居住狀態, dtype: int64

In [69]:

train.drop_duplicates(['小區名','地鐵線路'])[['小區名','地鐵線路']].sort_values(by='小區名')

Out[69]:

  小區名 地鐵線路
107337 0 3.0
3620 1 3.0
41286 2 5.0
8211 4 NaN
55962 5 NaN
... ... ...
45347 6625 NaN
6622 6626 5.0
1513 6626 1.0
1727 6627 NaN
2542 6627 1.0

6052 rows × 2 columns

設置後面要用的填充量

In [70]:

space_threshold=0.3

dist_value_for_fill=2#爲什麼是2,因爲距離的最大值是1,沒有地鐵 意味着很遠

line_value_for_fill=0

station_value_for_fill=0

area_value_for_fill=train["區"].mode().values[0]

# 拿到每個區的位置衆數

position_by_area=train.groupby('區').apply(lambda x:x["位置"].mode())

position_value_for_fill=position_by_area[position_by_area.index==area_value_for_fill].values[0][0]

state_value_for_fill=0#train["居住狀態"].mode().values[0]

decration_value_for_fill=-1#train["裝修情況"].mode().values[0]

rent_value_for_fill=-1#train["出租方式"].mode().values[0]

In [38]:

#拿到每個小區房屋出租數量的衆數

ratio_by_neighbor=train.groupby('小區名').apply(lambda x:x["小區房屋出租數量"].mode())

index=[x[0] for x in ratio_by_neighbor.index]

ratio_by_neighbor.index=index

ratio_by_neighbor=ratio_by_neighbor.to_dict()

ratio_mode=train["小區房屋出租數量"].mode().values[0]

缺失值處理

缺失值的處理方式有:

  • 刪除帶有缺失值的特徵,最簡單也最浪費信息的方式
  • 用均值,衆數或固定的數等填充,比1好,但仍不夠好
  • 考慮缺失的含義,把缺失值作爲一種信息
  • 用未缺失的數據訓練模型,預測缺失的數據(分類型變量用分類算法,數值型變量用迴歸)

思路:

  1. 首先利用沒有缺失值的小區名以及有值的地鐵站點信息,填充區和位置缺失值
  2. 利用小區和位置信息填充地鐵線路和地鐵站點和距離
  3. 還沒有填充的地鐵站點和地鐵線路用固定值填充,單獨作爲一類(即沒有地鐵),同時對應的距離填充爲2(即距離地鐵較遠)
  4. 按照同名小區的小區房屋出租數量的衆數來填充小區房屋出租數量

缺失值比例

In [71]:

# 缺失值比例

def ratio_of_null():

    train_missing = (train.isnull().sum()/len(train))*100

    train_missing = train_missing.drop(train_missing[train_missing==0].index).sort_values(ascending=False)

    return pd.DataFrame({'缺失百分比':train_missing})

ratio_of_null()

Out[71]:

  缺失百分比
裝修情況 90.591180
居住狀態 89.753688
出租方式 87.671658
距離 53.302907
地鐵站點 53.302907
地鐵線路 53.302907
小區房屋出租數量 0.509314
位置 0.015773
0.015773

填充區和位置

根據數據初步分析時的情況可以看出,位置缺失的就是3269這個小區的,所以選擇全部丟棄

In [72]:

train=train[train['小區名']!=3269]

In [73]:

ratio_of_null()

Out[73]:

  缺失百分比
裝修情況 90.591732
居住狀態 89.754107
出租方式 87.673275
距離 53.303682
地鐵站點 53.303682
地鐵線路 53.303682
小區房屋出租數量 0.508885

地鐵站點,距離 處理

  1. 先用每個同名小區名和同位置的地鐵線路,地鐵站點,距離衆數來填充
  2. 剩下的地鐵站點,距離,地鐵線路的缺失值作爲一種特徵,表示該房屋附近沒有地鐵

In [92]:

1.#先按照小區名和位置分組,然後獲取每組的站點衆數

station_by_nb_pos=train[['小區名','位置','地鐵站點','距離']].drop_duplicates().dropna().groupby(['小區名','位置'])['地鐵站點','距離'].apply(lambda x:np.max(x.mode()))

station_by_nb_pos

Out[92]:

    地鐵站點 距離
小區名 位置    
0 59.0 57.0 0.478333
1 59.0 57.0 0.563333
2 40.0 33.0 0.971667
11 24.0 103.0 0.914167
12 28.0 69.0 0.633333
... ... ... ...
6625 41.0 88.0 0.931667
6626 86.0 16.0 0.974167
136.0 16.0 0.974167
6627 86.0 10.0 0.985000
136.0 10.0 0.985000

3342 rows × 2 columns

In [93]:

station_by_nb=train[['小區名','地鐵站點','距離']].drop_duplicates().dropna().groupby('小區名')['地鐵站點','距離'].apply(lambda x:np.max(x.mode()))

station_by_nb

Out[93]:

  地鐵站點 距離
小區名    
0 57.0 0.478333
1 57.0 0.563333
2 33.0 0.971667
11 103.0 0.914167
12 69.0 0.633333
... ... ...
6622 25.0 0.245000
6623 119.0 0.410000
6625 88.0 0.931667
6626 16.0 0.974167
6627 10.0 0.985000

3329 rows × 2 columns

In [84]:

#拿到每個站點對應的線路

lines_by_station=train[['地鐵站點','地鐵線路']].drop_duplicates().dropna().groupby('地鐵站點')['地鐵線路'].min()

In [97]:

def fill_stations(line,s_by_np,s_by_n,l_by_s):

    """

    s_by_np:接收station_by_nb_pos

    s_by_n:接收station_by_nb

    l_by_s:接收lines_by_station

    """

    #首先判斷line行地鐵站點是否缺失

    #注意這裏最好用pd.isna,不要用np.isnull

    if not pd.isna(line['地鐵站點']):#不是空,就直接返回原行  

        return line

    #如果小區名和位置組合在數據索引中,就查找進行填充

    if (line['小區名'],line['位置']) in s_by_np:

        line['地鐵站點']=s_by_np.loc[(line['小區名'],line['位置']),'地鐵站點']

        line['距離']=s_by_np.loc[(line['小區名'],line['位置']),'距離']

        line['地鐵線路']=l_by_s[line['地鐵站點']]

    elif line['小區名'] in s_by_n.index:

        line['地鐵站點']=s_by_n.loc[line['小區名'],'地鐵站點']#用小區衆數填充

        line['距離']=s_by_n.loc[line['小區名'],'距離']

        line['地鐵線路']=l_by_s[line['地鐵站點']]

    else:#小區名也找不到的情況下  單獨作爲一類,即沒有地鐵

        line['地鐵站點']=0

        line['距離']=2#距離用2填充

        line['地鐵線路']=0

    return line

train=train.apply(fill_stations,s_by_np=station_by_nb_pos,s_by_n=station_by_nb,l_by_s=lines_by_station,axis=1)

ratio_of_null()

Out[97]:

  缺失百分比
裝修情況 90.591732
居住狀態 89.754107
出租方式 87.673275
小區房屋出租數量 0.508885

小區房屋出租數量處理

用每個小區的房屋出租數量衆數填充

In [105]:

#拿到每個小區房屋出租數量的衆數

ratio_by_neighbor=train[['小區名','小區房屋出租數量']].dropna().groupby('小區名').apply(lambda x:np.mean(x["小區房屋出租數量"].mode()))

ratio_by_neighbor

Out[105]:

小區名
0       0.007812
1       0.011719
2       0.007812
4       0.017578
5       0.009766
          ...   
6623    0.011719
6624    0.013672
6625    0.011719
6626    0.076172
6627    0.093750
Length: 5535, dtype: float64

In [99]:

 

#拿到所有小區的“小區房屋出租數量”衆數
ratio_mode=train["小區房屋出租數量"].mode().values[0]
ratio_mode

Out[99]:

0.01953125

In [106]:

def fill_by_key(x,k,v,values,mode):

    if not pd.isna(x[v]):

        return x

    else:

        if x[k] in values.index:

            x[v]=values[x[k]]

        else:

            x[v]=mode

        return x

# train['小區房屋出租數量']=train['小區房屋出租數量'].map()

train=train.apply(fill_by_key,k="小區名",v="小區房屋出租數量",values=ratio_by_neighbor,mode=ratio_mode,axis=1)

 

In [107]:

ratio_of_null()

Out[107]:

  缺失百分比
裝修情況 90.591732
居住狀態 89.754107
出租方式 87.673275

裝修,居住狀態,出租方式--作爲單獨一類

In [108]:

train["出租方式"]=train["出租方式"].fillna(int(-1))

train["裝修情況"]=train["裝修情況"].fillna(int(-1))

train["居住狀態"]=train["居住狀態"].fillna(int(0))

In [109]:

ratio_of_null()

Out[109]:

清除異常樣本

針對房屋面集存在的異常值,去掉房屋面積異常的樣本

In [110]:

train=train[train['房屋面積']<space_threshold]

train.shape

Out[110]:

(196499, 19)

糾偏

針對目標值月租金普遍分佈過散,進行對數平滑

In [111]:

train["log_rent"] = np.log1p(train["月租金"])#np.log1p  log(1+x)   inf

In [112]:

#糾正之前

plt.figure(figsize=(10,5))

sns.boxplot(x="月租金",data=train,orient='h')

plt.show()

In [113]:

#糾正之後

plt.figure(figsize=(10,5))

sns.boxplot(x="log_rent",data=train,orient='h')

plt.show()

In [114]:

train.head()

Out[114]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金 log_rent
0 1 3072 0.128906 2 0.236364 0.008628 東南 0.0 1 1 1 -1.0 11.0 118.0 2.0 40.0 0.764167 -1.0 5.602716 1.887481
1 1 3152 0.132812 1 0.381818 0.017046 0.0 1 0 0 -1.0 10.0 100.0 4.0 58.0 0.709167 -1.0 16.977929 2.889145
2 1 5575 0.042969 0 0.290909 0.010593 東南 0.0 2 1 2 -1.0 12.0 130.0 5.0 37.0 0.572500 -1.0 8.998302 2.302415
3 1 3103 0.085938 2 0.581818 0.019199 0.0 3 2 2 -1.0 7.0 90.0 2.0 63.0 0.658333 -1.0 5.602716 1.887481
4 1 5182 0.214844 0 0.545455 0.010427 東北 0.0 2 1 1 -1.0 3.0 31.0 0.0 0.0 2.000000 -1.0 7.300509 2.116317

問題數據處理

房間朝向列有多個值,這裏我們只要第一個

In [115]:

def split(text,i):

    items=text.split(" ")

    if i<len(items):

        return items[i]

    else:

        return np.nan

train['新朝向']=train['房屋朝向'].map(lambda x:split(x,0))

In [116]:

train.head()
train['新朝向'].value_counts()

Out[116]:

南     59605
東南    55854
東     34282
西南    17750
北     10490
西      9972
西北     5259
東北     3287
Name: 新朝向, dtype: int64

存儲數據

In [117]:

train.to_csv("data/train_etl.csv",index=None)

In [30]:

import pickle

time_for_fill=train_data['時間'].mode().values[0]

neighbor_for_fill=train_data['小區名'].mode().values[0]

ting_for_fill=train_data['廳的數量'].mode().values[0]

wei_for_fill=train_data['衛的數量'].mode().values[0]

bed_for_fill=train_data['臥室數量'].mode().values[0]

direction_for_fill=train_data['新朝向'].mode().values[0]

mianji_for_fill=train_data['房屋面積'].mean()

louceng_for_fill=train_data['樓層'].mode().values[0]

zonglouceng_for_fill=train_data['總樓層'].mode().values[0]

values={

    '距離':dist_value_for_fill,

    '地鐵線路':line_value_for_fill,

    '地鐵站點':station_value_for_fill,

    '區':area_value_for_fill,

    '位置':position_value_for_fill,

    '居住狀態':state_value_for_fill,

    '裝修情況':decration_value_for_fill,

    '出租方式':rent_value_for_fill,

    'ratio_by_neighbor':ratio_by_neighbor,

    '小區房屋出租數量':ratio_mode,

    '時間':time_for_fill,

    '小區名':neighbor_for_fill,

    '廳的數量':ting_for_fill,

    '衛的數量':wei_for_fill,

    '臥室數量':bed_for_fill,

    '新朝向':direction_for_fill,

    '房屋面積':mianji_for_fill,

    '樓層':louceng_for_fill,

    '總樓層':zonglouceng_for_fill,

    '所有朝向':list(np.unique(train_data['新朝向']))

}

with open("data/values.pkl",'wb') as f:

    pickle.dump(values,f)

In [31]:

values

Out[31]:

{'距離': 2,
 '地鐵線路': 0,
 '地鐵站點': 0,
 '區': 12.0,
 '位置': 52.0,
 '居住狀態': 0,
 '裝修情況': -1,
 '出租方式': -1,
 'ratio_by_neighbor': {0: 0.0078125,
  1: 0.01171875,
  2: 0.0078125,
  4: 0.01953125,
  5: 0.01171875,
  8: 0.0078125,
  9: 0.0234375,
。。。。。。
  1181: 0.0078125,
  1183: 0.01171875,
  ...},
 '小區房屋出租數量': 0.01953125,
 '時間': 3,
 '小區名': 5512,
 '廳的數量': 1,
 '衛的數量': 1,
 '臥室數量': 2,
 '新朝向': '南',
 '房屋面積': 0.013104835639490475,
 '樓層': 0,
 '總樓層': 0.3090909090909091,
 '所有朝向': ['東', '東北', '東南', '北', '南', '西', '西北', '西南']}

特徵工程

In [1]:

import matplotlib.pyplot as plt

import pandas as pd

import numpy as np

import seaborn as sns

import warnings

warnings.filterwarnings('ignore')#忽略一些警告

In [2]:

train=pd.read_csv("data/train_etl.csv")

train.head()

Out[2]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 ... 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金 log_rent 新朝向
0 1 3072 0.128906 2 0.236364 0.008628 東南 0.0 1 1 ... -1.0 11.0 118.0 2.0 40.0 0.764167 -1.0 5.602716 1.887481 東南
1 1 3152 0.132812 1 0.381818 0.017046 0.0 1 0 ... -1.0 10.0 100.0 4.0 58.0 0.709167 -1.0 16.977929 2.889145
2 1 5575 0.042969 0 0.290909 0.010593 東南 0.0 2 1 ... -1.0 12.0 130.0 5.0 37.0 0.572500 -1.0 8.998302 2.302415 東南
3 1 3103 0.085938 2 0.581818 0.019199 0.0 3 2 ... -1.0 7.0 90.0 2.0 63.0 0.658333 -1.0 5.602716 1.887481
4 1 5182 0.214844 0 0.545455 0.010427 東北 0.0 2 1 ... -1.0 3.0 31.0 0.0 0.0 2.000000 -1.0 7.300509 2.116317 東北

5 rows × 21 columns

In [3]:

train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 196499 entries, 0 to 196498
Data columns (total 21 columns):
時間          196499 non-null int64
小區名         196499 non-null int64
小區房屋出租數量    196499 non-null float64
樓層          196499 non-null int64
總樓層         196499 non-null float64
房屋面積        196499 non-null float64
房屋朝向        196499 non-null object
居住狀態        196499 non-null float64
臥室數量        196499 non-null int64
廳的數量        196499 non-null int64
衛的數量        196499 non-null int64
出租方式        196499 non-null float64
區           196499 non-null float64
位置          196499 non-null float64
地鐵線路        196499 non-null float64
地鐵站點        196499 non-null float64
距離          196499 non-null float64
裝修情況        196499 non-null float64
月租金         196499 non-null float64
log_rent    196499 non-null float64
新朝向         196499 non-null object
dtypes: float64(13), int64(6), object(2)
memory usage: 31.5+ MB

根據房間,廳,衛,房屋面積構造新特徵

In [4]:

train["房+衛+廳"]=train["臥室數量"]+train["廳的數量"]+train["衛的數量"]

train["房/總"]=train["臥室數量"]/(train["房+衛+廳"]+1)

train["衛/總"]=train["衛的數量"]/(train["房+衛+廳"]+1)

train["廳/總"]=train["廳的數量"]/(train["房+衛+廳"]+1)

train['臥室面積']=train['房屋面積']/(train['臥室數量']+1)#加1是爲了防止分母=0出現結果爲inf無窮大的現象

train['樓層比']=train['樓層']/(train["總樓層"]+1)#加1是爲了防止分母=0出現結果爲inf無窮大的現象

train['戶型']=train[['臥室數量','廳的數量','衛的數量']].apply(lambda x:str(x['臥室數量'])+str(x['廳的數量'])+str(x['衛的數量']),axis=1)

構建租金平均值特徵

In [5]:

rent_means=train[['小區名','新朝向','地鐵站點','位置','log_rent']].groupby(['小區名','新朝向','地鐵站點','位置'],as_index=False).mean()

rent_means.columns=['小區名','新朝向','地鐵站點','位置','平均值特徵1']

train=pd.merge(train,rent_means,how='left',on=['小區名','新朝向','地鐵站點','位置'])

In [6]:

rent_means2=train[['小區名','log_rent']].groupby(['小區名'],as_index=False).mean()

rent_means2.columns=['小區名','小區平均值特徵']

train=pd.merge(train,rent_means2,how='left',on=['小區名'])

In [7]:

rent_means3=train[['新朝向','log_rent']].groupby(['新朝向'],as_index=False).mean()

rent_means3.columns=['新朝向','朝向平均值特徵']

train=pd.merge(train,rent_means3,how='left',on=['新朝向'])

In [8]:

rent_means4=train[['地鐵站點','log_rent']].groupby(['地鐵站點'],as_index=False).mean()

rent_means4.columns=['地鐵站點','站點平均值特徵']

train=pd.merge(train,rent_means4,how='left',on=['地鐵站點'])

In [9]:

rent_means5=train[['位置','log_rent']].groupby(['位置'],as_index=False).mean()

rent_means5.columns=['位置','位置平均值特徵']

train=pd.merge(train,rent_means5,how='left',on=['位置'])

構造是否有地鐵

In [10]:

train["有地鐵"]=(train["地鐵站點"]>-1).map(int)

In [11]:

train.columns

Out[11]:

Index(['時間', '小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積', '房屋朝向', '居住狀態', '臥室數量',
       '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', '月租金',
       'log_rent', '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型',
       '平均值特徵1', '小區平均值特徵', '朝向平均值特徵', '站點平均值特徵', '位置平均值特徵', '有地鐵'],
      dtype='object')

構造聚類特徵

In [12]:

from sklearn.preprocessing import StandardScaler

from sklearn.cluster import KMeans

features=train[['房屋面積','臥室數量','廳的數量','衛的數量','距離','樓層比']]

trans=StandardScaler()

new_features=trans.fit_transform(features)

kmeans=KMeans(n_clusters=5)

kmeans.fit(new_features)

train['聚類特徵']=kmeans.predict(new_features).astype(str)

#計算每個聚類特徵的月租金平均值

cluster_means=train[['聚類特徵','log_rent']].groupby('聚類特徵',as_index=False).mean()

cluster_means.columns=['聚類特徵','平均值特徵2']

train=pd.merge(train,cluster_means,how='left',on=['聚類特徵'])

保存標準化和聚類模型

In [13]:

import pickle 

with open("data/kmeans.pkl",'wb') as f:

    pickle.dump({

        "std_transer":trans,

        "kmeans":kmeans

    },f)

構造地鐵線路數特徵

In [14]:

lines_count1=train[['小區名','地鐵線路']].drop_duplicates().groupby('小區名').count()

lines_count2=train[['位置','地鐵線路']].drop_duplicates().groupby('位置').count()

lines_count2.columns=['位置線路數']

lines_count1.columns=['小區線路數']

In [15]:

train=pd.merge(train,lines_count1,how='left',on=['小區名'])

train=pd.merge(train,lines_count2,how='left',on=['位置'])

去掉出現數量較少的小區

In [16]:

neighbors=train['小區名'].value_counts()

train['新小區名']=train.apply(lambda x: x['小區名'] if neighbors[x['小區名']]>100 else -1,axis=1)

train['小區條數大於100']=train.apply(lambda x: 1 if neighbors[x['小區名']]>100 else 0,axis=1)

In [17]:

train.info()

train['新小區名'].value_counts()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 196499 entries, 0 to 196498
Data columns (total 40 columns):
時間           196499 non-null int64
小區名          196499 non-null int64
小區房屋出租數量     196499 non-null float64
樓層           196499 non-null int64
總樓層          196499 non-null float64
房屋面積         196499 non-null float64
房屋朝向         196499 non-null object
居住狀態         196499 non-null float64
臥室數量         196499 non-null int64
廳的數量         196499 non-null int64
衛的數量         196499 non-null int64
出租方式         196499 non-null float64
區            196499 non-null float64
位置           196499 non-null float64
地鐵線路         196499 non-null float64
地鐵站點         196499 non-null float64
距離           196499 non-null float64
裝修情況         196499 non-null float64
月租金          196499 non-null float64
log_rent     196499 non-null float64
新朝向          196499 non-null object
房+衛+廳        196499 non-null int64
房/總          196499 non-null float64
衛/總          196499 non-null float64
廳/總          196499 non-null float64
臥室面積         196499 non-null float64
樓層比          196499 non-null float64
戶型           196499 non-null object
平均值特徵1       196499 non-null float64
小區平均值特徵      196499 non-null float64
朝向平均值特徵      196499 non-null float64
站點平均值特徵      196499 non-null float64
位置平均值特徵      196499 non-null float64
有地鐵          196499 non-null int64
聚類特徵         196499 non-null object
平均值特徵2       196499 non-null float64
小區線路數        196499 non-null int64
位置線路數        196499 non-null int64
新小區名         196499 non-null int64
小區條數大於100    196499 non-null int64
dtypes: float64(24), int64(12), object(4)
memory usage: 61.5+ MB

Out[17]:

-1       72488
 5512     1880
 1085     1155
 5208     1136
 6221     1066
         ...  
 244       102
 6461      102
 5906      102
 1654      102
 5196      101
Name: 新小區名, Length: 512, dtype: int64

轉換類型

In [41]:

#將離散特徵轉換成字符串類型

colunms = ['時間', '小區名', '居住狀態', '出租方式', '區','位置','地鐵線路','地鐵站點','裝修情況']

for col in colunms:

    train[col] = train[col].astype(str)

In [14]:

train.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 196499 entries, 0 to 196498
Data columns (total 34 columns):
時間          196499 non-null object
小區名         196499 non-null object
小區房屋出租數量    196499 non-null float64
樓層          196499 non-null int64
總樓層         196499 non-null float64
房屋面積        196499 non-null float64
房屋朝向        196499 non-null object
居住狀態        196499 non-null object
臥室數量        196499 non-null int64
廳的數量        196499 non-null int64
衛的數量        196499 non-null int64
出租方式        196499 non-null object
區           196499 non-null object
位置          196499 non-null object
地鐵線路        196499 non-null object
地鐵站點        196499 non-null object
距離          196499 non-null float64
裝修情況        196499 non-null object
月租金         196499 non-null float64
log_rent    196499 non-null float64
新朝向         196499 non-null object
房+衛+廳       196499 non-null int64
房/總         196499 non-null float64
衛/總         196499 non-null float64
廳/總         196499 non-null float64
臥室面積        196499 non-null float64
樓層比         196499 non-null float64
戶型          196499 non-null object
平均值特徵1      196499 non-null float64
有地鐵         196499 non-null int64
聚類特徵        196499 non-null object
平均值特徵2      196499 non-null float64
小區線路數       196499 non-null int64
位置線路數       196499 non-null int64
dtypes: float64(13), int64(8), object(13)
memory usage: 52.5+ MB

In [18]:

#保存處理後的數據

train.to_csv("data/onehot_feature.csv")

In [11]:

x_columns=['時間', '小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積','居住狀態', '臥室數量',

       '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', 

       '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型',

       '有地鐵']

x=train[x_columns]

y=train['月租金']

構建數據清洗和特徵工程函數

In [61]:

#     'dist_value_for_fill':dist_value_for_fill,

#     'line_value_for_fill':line_value_for_fill,

#     'station_value_for_fill':station_value_for_fill,

#     'area_value_for_fill':area_value_for_fill,

#     'position_value_for_fill':position_value_for_fill,

#     'state_value_for_fill':state_value_for_fill,

#     'decration_value_for_fill':decration_value_for_fill,

#     'rent_value_for_fill':rent_value_for_fill,

#     'ratio_by_neighbor':ratio_by_neighbor,

#     'ratio_mode':ratio_mode,

#     'time_for_fill':time_for_fill,

#     'neighbor_for_fill':neighbor_for_fill,

#     'ting_for_fill':ting_for_fill,

#     'wei_for_fill':wei_for_fill,

#     'bed_for_fill':bed_for_fill,

#     'direction_for_fill':direction_for_fill,

#     'mianji_for_fill':mianji_for_fill,

#     'louceng_for_fill':louceng_for_fill,

#     'zonglouceng_for_fill':zonglouceng_for_fill

# def process(x,values,models):

#     x=x.to_dict()

#     keys=['時間', '小區名', '樓層', '總樓層', '房屋面積',  '居住狀態', '臥室數量',

#        '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況']

#     #原特徵缺失值填充

#     for key in keys:

#         if pd.isna(x[key]):

#             x[key]=values[key]

#     #小區房屋出租數量

#     if pd.isna(str(x['小區房屋出租數量'])):

#         if x['小區名'] in values['ratio_by_neighbor']:

#             x['小區房屋出租數量']=values['ratio_by_neighbor'][x['小區名']]

#         else:

#             x['小區房屋出租數量']=values['小區房屋出租數量']

#     #房屋朝向問題

# #     print(x['房屋朝向'])

#     if pd.isna(x['房屋朝向']):

#         x['新朝向']=values['新朝向']

#     else:

#         chaoxiang=x['房屋朝向'].split(" ")[0]

#         if chaoxiang in values['所有朝向']:

#             x['新朝向']=chaoxiang

#         else:

#             x['新朝向']=values['新朝向']

#     #構造特徵

#     x["房+衛+廳"]=x["臥室數量"]+x["廳的數量"]+x["衛的數量"]

#     x["房/總"]=x["臥室數量"]/x["房+衛+廳"]

#     x["衛/總"]=x["衛的數量"]/x["房+衛+廳"]

#     x["廳/總"]=x["廳的數量"]/x["房+衛+廳"]

#     x['臥室面積']=x['房屋面積']/x['臥室數量']

#     x['樓層比']=x['樓層']/(x["總樓層"]+1)#加1是爲了防止分母=0出現結果爲inf無窮大的現象

#     x['戶型']=str(x['臥室數量'])+str(x['廳的數量'])+str(x['衛的數量'])

#     if x["地鐵站點"]>-1:

#         x["有地鐵"]=1

#     else:

#         x["有地鐵"]=0

#     #構造聚類特徵

#     features=np.array([[x['房屋面積'],x['臥室數量'],x['廳的數量'],x['衛的數量'],x['距離'],x['樓層比']]])

#     models['std_transer'].transform(features)

#     x['聚類特徵']=models['kmeans'].predict(new_features).astype(str)[0]

#     return pd.Series(x)

In [66]:

test=pd.read_csv('data/test.csv')

test.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 56279 entries, 0 to 56278
Data columns (total 19 columns):
id          56279 non-null int64
時間          56279 non-null int64
小區名         56279 non-null int64
小區房屋出租數量    56257 non-null float64
樓層          56279 non-null int64
總樓層         56279 non-null float64
房屋面積        56279 non-null float64
房屋朝向        56279 non-null object
居住狀態        4483 non-null float64
臥室數量        56279 non-null int64
廳的數量        56279 non-null int64
衛的數量        56279 non-null int64
出租方式        4971 non-null float64
區           56269 non-null float64
位置          56269 non-null float64
地鐵線路        26494 non-null float64
地鐵站點        26494 non-null float64
距離          26494 non-null float64
裝修情況        4207 non-null float64
dtypes: float64(11), int64(7), object(1)
memory usage: 8.2+ MB

In [46]:

with open("data/kmeans.pkl",'rb') as f:

    models=pickle.load(f)

In [47]:

with open("data/values.pkl",'rb') as f:

    values=pickle.load(f)

In [65]:

test.iloc[:100,:].apply(process,models=models,values=values,axis=1)

Out[65]:

  id 時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 ... 新朝向 房+衛+廳 房/總 衛/總 廳/總 臥室面積 樓層比 戶型 有地鐵 聚類特徵
0 1 4 6011 0.382812 1 0.600000 0.007117 3.0 2 ... 4 0.500000 0.250000 0.250000 0.003558 0.625000 211 1 2
1 2 4 1697 0.152344 1 0.472727 0.007448 0.0 2 ... 4 0.500000 0.250000 0.250000 0.003724 0.679012 211 1 2
2 3 4 754 0.207031 2 0.709091 0.014068 東南 0.0 3 ... 東南 7 0.428571 0.285714 0.285714 0.004689 1.170213 322 1 2
3 4 4 1285 0.011719 0 0.090909 0.008937 0.0 2 ... 4 0.500000 0.250000 0.250000 0.004469 0.000000 211 1 2
4 5 4 4984 0.035156 1 0.218182 0.008606 東南 0.0 2 ... 東南 4 0.500000 0.250000 0.250000 0.004303 0.820896 211 1 2
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
95 96 4 5239 0.433594 0 0.545455 0.006202 0.0 1 ... 2 0.500000 0.500000 0.000000 0.006202 0.000000 101 1 2
96 97 4 1027 0.046875 0 0.727273 0.007779 0.0 2 ... 4 0.500000 0.250000 0.250000 0.003889 0.000000 211 1 2
97 98 4 300 0.140625 2 0.454545 0.013744 西 0.0 2 ... 西 5 0.400000 0.200000 0.400000 0.006872 1.375000 221 1 2
98 99 4 1021 0.269531 0 0.581818 0.013860 東南 0.0 3 ... 東南 7 0.428571 0.285714 0.285714 0.004620 0.000000 322 1 2
99 100 4 2644 0.300781 0 0.309091 0.014896 東南 0.0 3 ... 東南 6 0.500000 0.166667 0.333333 0.004965 0.000000 321 1 2

100 rows × 29 columns


建模

In [21]:

import matplotlib.pyplot as plt

import pandas as pd

import numpy as np

import seaborn as sns

import warnings

import xgboost as xgb

import copy

from sklearn.model_selection import train_test_split,GridSearchCV

from sklearn.feature_extraction import DictVectorizer

from sklearn.ensemble import RandomForestRegressor,GradientBoostingRegressor

from sklearn.metrics import mean_squared_error

warnings.filterwarnings('ignore')#忽略一些警告

 

讀取數據

In [22]:

data=pd.read_csv("data/onehot_feature.csv")

data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 196499 entries, 0 to 196498
Data columns (total 41 columns):
Unnamed: 0    196499 non-null int64
時間            196499 non-null int64
小區名           196499 non-null int64
小區房屋出租數量      196499 non-null float64
樓層            196499 non-null int64
總樓層           196499 non-null float64
房屋面積          196499 non-null float64
房屋朝向          196499 non-null object
居住狀態          196499 non-null float64
臥室數量          196499 non-null int64
廳的數量          196499 non-null int64
衛的數量          196499 non-null int64
出租方式          196499 non-null float64
區             196499 non-null float64
位置            196499 non-null float64
地鐵線路          196499 non-null float64
地鐵站點          196499 non-null float64
距離            196499 non-null float64
裝修情況          196499 non-null float64
月租金           196499 non-null float64
log_rent      196499 non-null float64
新朝向           196499 non-null object
房+衛+廳         196499 non-null int64
房/總           196499 non-null float64
衛/總           196499 non-null float64
廳/總           196499 non-null float64
臥室面積          196499 non-null float64
樓層比           196499 non-null float64
戶型            196499 non-null int64
平均值特徵1        196499 non-null float64
小區平均值特徵       196499 non-null float64
朝向平均值特徵       196499 non-null float64
站點平均值特徵       196499 non-null float64
位置平均值特徵       196499 non-null float64
有地鐵           196499 non-null int64
聚類特徵          196499 non-null int64
平均值特徵2        196499 non-null float64
小區線路數         196499 non-null int64
位置線路數         196499 non-null int64
新小區名          196499 non-null int64
小區條數大於100     196499 non-null int64
dtypes: float64(24), int64(15), object(2)
memory usage: 61.5+ MB

In [23]:

#將離散特徵轉換成字符串類型

colunms = ['時間', '新小區名', '居住狀態', '出租方式', '區','位置','地鐵線路','地鐵站點','裝修情況','戶型','聚類特徵']

for col in colunms:

    data[col] = data[col].astype(str)

獲取x和y

In [24]:

data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 196499 entries, 0 to 196498
Data columns (total 41 columns):
Unnamed: 0    196499 non-null int64
時間            196499 non-null object
小區名           196499 non-null int64
小區房屋出租數量      196499 non-null float64
樓層            196499 non-null int64
總樓層           196499 non-null float64
房屋面積          196499 non-null float64
房屋朝向          196499 non-null object
居住狀態          196499 non-null object
臥室數量          196499 non-null int64
廳的數量          196499 non-null int64
衛的數量          196499 non-null int64
出租方式          196499 non-null object
區             196499 non-null object
位置            196499 non-null object
地鐵線路          196499 non-null object
地鐵站點          196499 non-null object
距離            196499 non-null float64
裝修情況          196499 non-null object
月租金           196499 non-null float64
log_rent      196499 non-null float64
新朝向           196499 non-null object
房+衛+廳         196499 non-null int64
房/總           196499 non-null float64
衛/總           196499 non-null float64
廳/總           196499 non-null float64
臥室面積          196499 non-null float64
樓層比           196499 non-null float64
戶型            196499 non-null object
平均值特徵1        196499 non-null float64
小區平均值特徵       196499 non-null float64
朝向平均值特徵       196499 non-null float64
站點平均值特徵       196499 non-null float64
位置平均值特徵       196499 non-null float64
有地鐵           196499 non-null int64
聚類特徵          196499 non-null object
平均值特徵2        196499 non-null float64
小區線路數         196499 non-null int64
位置線路數         196499 non-null int64
新小區名          196499 non-null object
小區條數大於100     196499 non-null int64
dtypes: float64(17), int64(11), object(13)
memory usage: 61.5+ MB

In [25]:

x_columns=['時間', '新小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積','居住狀態', '臥室數量',

       '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', 

       '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型','平均值特徵1',

       '平均值特徵2','有地鐵','小區線路數','位置線路數','小區條數大於100','小區平均值特徵','朝向平均值特徵',

           '站點平均值特徵','位置平均值特徵']

y_label='log_rent'

x=data[x_columns]

y=data[y_label]

y.isnull().sum()

Out[25]:

0

構建訓練函數

In [26]:

def feature_transformer(x,y,test_size=0.3,random_state=12):

    """

    負責分割數據集並轉換onehot特徵,返回轉換後的稀疏矩陣和特徵名

    """

    #1.重新命名列名

    #原列名

    cols=['時間', '新小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積','居住狀態', '臥室數量',

       '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', 

       '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型','平均值特徵1',

       '平均值特徵2','有地鐵','小區線路數','位置線路數','小區條數大於100','小區平均值特徵','朝向平均值特徵',

           '站點平均值特徵','位置平均值特徵']

    #新列名

    new_cols=[chr(65+s)+str(i) for s in range(len(cols)//10+1) for i in range(10)]

    new_cols=new_cols[:len(cols)]

    #特徵名映射字典

    cols_map={k:v for k,v in zip(cols,new_cols)}

    #重新命名列

    x.columns=[cols_map[k] for k in x.columns]

    #2.分割數據集

    train_x,test_x,train_y,test_y=train_test_split(x,y,test_size=test_size,random_state=random_state)

    #3.轉換onehot特徵

    #返回稀疏矩陣,有兩個優點:

    #1.佔用內存大幅減小,讓並行成爲可能,不然並行的話,內存爆掉

    #2.可以加速xgboost訓練

    vector=DictVectorizer(sparse=True)

    x_train=vector.fit_transform(train_x.to_dict(orient='records'))

    x_test=vector.transform(test_x.to_dict(orient='records'))

    features=vector.get_feature_names()

    #4.構建原始特徵對應的新下標字典  

    #原始特徵名

    #離散列特徵下標字典

    feature_map={k:[] for k in cols}

    for i in range(len(features)):

        for col in cols:

            if features[i].startswith(cols_map[col]):#如果新特徵以老特徵開頭

                feature_map[col].append(i)

                break

    return (x_train,x_test,train_y,test_y),feature_map,cols_map

def train(cols,data,feature_map,num_round = 500):

    """

    負責完成一次xgboost訓練,返回測試集rmse

    """

    #1.獲取數據集

    train_x,test_x,train_y,test_y=data

    #獲取原始特徵對應的新特徵下標

    index=[]

    for col in cols:

        index.extend(feature_map[col])

    x_train=train_x[:,index]

    x_test=test_x[:,index]

    #3.構建數據格式

    #構建DMatrix數據,可以有效利用硬盤緩存,減少內存佔用

    dtrain = xgb.DMatrix(x_train,train_y)

    dtest = xgb.DMatrix(x_test,test_y)

    #4.設置訓練參數

    param = {'max_depth':5, 

             'eta':0.01, 

             'verbosity':1, 

             'objective':'reg:linear',

             'silent': 1,

             'gamma': 0.01,

             'min_child_weight': 1,

            }

    #5.模型訓練

    bst = xgb.train(param, dtrain, num_round)

    #6.模型預測

    preds = bst.predict(dtest)

    preds=np.exp(preds)-1#轉換成真實的租金

    y_true=np.exp(test_y)-1

    #7.模型評估

    return np.sqrt(mean_squared_error(y_true,preds))

In [27]:

#完成特徵分割和轉換

d,f_map,c_map=feature_transformer(x,y)

 

模型特徵篩選

In [26]:

# #構造列名類

# class ColData:

#     cols=np.array(['時間', '小區名', '小區房屋出租數量', '樓層', '總樓層', '房屋面積','居住狀態', '臥室數量',

#        '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', 

#        '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型','平均值特徵1',

#        '有地鐵','聚類特徵','小區線路數','位置線路數'])

#     def __init__(self,ids):

#         self.ids=ids

#     def include_names(self):

#         print(type(ColData.cols))

#         return list(ColData.cols[self.ids])

#     def exclude_names(self):

#         non_ids=list(set(range(ColData.cols.shape[0]))-set(self.ids))

#         return list(ColData.cols[non_ids])

In [28]:

#構造篩選特徵函數

def select_features(cols,min_score):

    include_features=cols

    exclude_features=[]

    cols=np.array(cols)

    for i in range(cols.shape[0]):

        #選中的特徵

        features=list(cols[list(set(range(cols.shape[0]))-set([i]))])

        print("開始第{}次訓練:".format(i))

        print("未選中特徵:",cols[i])

        rmse=train(features,d,f_map,2500)

        print("開始第{}次訓練測試集成績{}:".format(i,rmse))

        print("-"*10)

        if rmse<=min_score:

            exclude_features=cols[i]

            include_features=features

            min_score=rmse

    return min_score,include_features,exclude_features  

In [29]:

min_score=train(x_columns,d,f_map)

In [30]:

features=x_columns

min_score

Out[30]:

2.627438015769018

In [31]:

i=1

while len(features)>0:

    print("開始第{}輪篩選:\n".format(i))

    ms,include_f,exclude_f=select_features(features,min_score)

    if len(exclude_f)<=0:

        break

    features=include_f

    min_score=ms

    print("第{}次篩選成績:{}\n".format(i,min_score))

    i=i+1

    print("保留特徵:",include_f)

    print("排除特徵:",exclude_f)

    print("\n*************************\n")

print("最終特徵:",features)

print("最好成績:",min_score)

開始第1輪篩選:

開始第0次訓練:
未選中特徵: 時間
開始第0次訓練測試集成績2.3425739100557874:
----------
開始第1次訓練:
未選中特徵: 新小區名
開始第1次訓練測試集成績2.3159098956260884:
----------
開始第2次訓練:
未選中特徵: 小區房屋出租數量
開始第2次訓練測試集成績2.3610726419651975:
----------
開始第3次訓練:
未選中特徵: 樓層
開始第3次訓練測試集成績2.3482224666430156:
----------
開始第4次訓練:
未選中特徵: 總樓層
開始第4次訓練測試集成績2.3548737824509476:
----------
開始第5次訓練:
未選中特徵: 房屋面積
開始第5次訓練測試集成績2.3528631046347734:
----------
開始第6次訓練:
未選中特徵: 居住狀態
開始第6次訓練測試集成績2.343644368107605:
----------
開始第7次訓練:
未選中特徵: 臥室數量
開始第7次訓練測試集成績2.3447264002503947:
----------
開始第8次訓練:
未選中特徵: 廳的數量
開始第8次訓練測試集成績2.3488349025371353:
----------
開始第9次訓練:
未選中特徵: 衛的數量
開始第9次訓練測試集成績2.3455068228561444:
----------
開始第10次訓練:
未選中特徵: 出租方式
開始第10次訓練測試集成績2.347907742954758:
----------
開始第11次訓練:
未選中特徵: 區
開始第11次訓練測試集成績2.3470549409629813:
----------
開始第12次訓練:
未選中特徵: 位置
開始第12次訓練測試集成績2.3442351978396916:
----------
開始第13次訓練:
未選中特徵: 地鐵線路
開始第13次訓練測試集成績2.3457640963554747:
----------
開始第14次訓練:
未選中特徵: 地鐵站點
開始第14次訓練測試集成績2.3514284469336877:
----------
開始第15次訓練:
未選中特徵: 距離
開始第15次訓練測試集成績2.3536807483560542:
----------
開始第16次訓練:
未選中特徵: 裝修情況
開始第16次訓練測試集成績2.3748498709037094:
----------
開始第17次訓練:
未選中特徵: 新朝向
開始第17次訓練測試集成績2.3442905601261614:
----------
開始第18次訓練:
未選中特徵: 房+衛+廳
開始第18次訓練測試集成績2.340930304773355:
----------
開始第19次訓練:
未選中特徵: 房/總
開始第19次訓練測試集成績2.3480559804451464:
----------
開始第20次訓練:
未選中特徵: 衛/總
開始第20次訓練測試集成績2.3465279974923803:
----------
開始第21次訓練:
未選中特徵: 廳/總
開始第21次訓練測試集成績2.348225921086065:
----------
開始第22次訓練:
未選中特徵: 臥室面積
開始第22次訓練測試集成績2.352140741124247:
----------
開始第23次訓練:
未選中特徵: 樓層比
開始第23次訓練測試集成績2.3495753059171336:
----------
開始第24次訓練:
未選中特徵: 戶型
開始第24次訓練測試集成績2.355693315193697:
----------
開始第25次訓練:
未選中特徵: 平均值特徵1
開始第25次訓練測試集成績2.544232443156709:
----------
開始第26次訓練:
未選中特徵: 平均值特徵2
開始第26次訓練測試集成績2.3445018995961795:
----------
開始第27次訓練:
未選中特徵: 有地鐵
開始第27次訓練測試集成績2.3481264617837376:
----------
開始第28次訓練:
未選中特徵: 小區線路數
開始第28次訓練測試集成績2.3481264617837376:
----------
開始第29次訓練:
未選中特徵: 位置線路數
開始第29次訓練測試集成績2.3504238672632107:
----------
開始第30次訓練:
未選中特徵: 小區條數大於100
開始第30次訓練測試集成績2.3481264617837376:
----------
開始第31次訓練:
未選中特徵: 小區平均值特徵
開始第31次訓練測試集成績2.349284024062191:
----------
開始第32次訓練:
未選中特徵: 朝向平均值特徵
開始第32次訓練測試集成績2.3424697168707467:
----------
開始第33次訓練:
未選中特徵: 站點平均值特徵
開始第33次訓練測試集成績2.357579803345613:
----------
開始第34次訓練:
未選中特徵: 位置平均值特徵
開始第34次訓練測試集成績2.370372655988748:
----------
第1次篩選成績:2.3159098956260884

保留特徵: ['時間', '小區房屋出租數量', '樓層', '總樓層', '房屋面積', '居住狀態', '臥室數量', '廳的數量', '衛的數量', '出租方式', '區', '位置', '地鐵線路', '地鐵站點', '距離', '裝修情況', '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型', '平均值特徵1', '平均值特徵2', '有地鐵', '小區線路數', '位置線路數', '小區條數大於100', '小區平均值特徵', '朝向平均值特徵', '站點平均值特徵', '位置平均值特徵']
排除特徵: 新小區名

*************************

開始第2輪篩選:

開始第0次訓練:
未選中特徵: 時間
開始第0次訓練測試集成績2.319998668753389:
----------
開始第1次訓練:
未選中特徵: 小區房屋出租數量
開始第1次訓練測試集成績2.322355105258432:
----------
開始第2次訓練:
未選中特徵: 樓層
開始第2次訓練測試集成績2.3158954168386106:
----------
開始第3次訓練:
未選中特徵: 總樓層
開始第3次訓練測試集成績2.329094243429236:
----------
開始第4次訓練:
未選中特徵: 房屋面積
開始第4次訓練測試集成績2.3258240532005727:
----------
開始第5次訓練:
未選中特徵: 居住狀態
開始第5次訓練測試集成績2.318009433185204:
----------
開始第6次訓練:
未選中特徵: 臥室數量
開始第6次訓練測試集成績2.317658870332904:
----------
開始第7次訓練:
未選中特徵: 廳的數量
開始第7次訓練測試集成績2.317469293657488:
----------
開始第8次訓練:
未選中特徵: 衛的數量

 

In [21]:

cols=['小區房屋出租數量','房屋面積', '居住狀態', '出租方式', '位置', '地鐵站點', '距離', '裝修情況', '新朝向', '房+衛+廳', '房/總', '衛/總',  '臥室面積', '樓層比', '平均值特徵1', '平均值特徵2', '小區線路數', '位置線路數','小區條數大於100']

train(cols,d,f_map)

Out[21]:

1.6355982447085897

參數搜索

構建交叉驗證和參數搜索函數

In [32]:

from sklearn.model_selection import KFold

#構建交叉驗證函數

def train_cv(data,target,params,num_round=200,k_fold=5,silent=0):

    """

    負責完成一種參數組合的情況下k_flod折交叉驗證的平均rmse值

    """

    rmses=[]

    #數據分割

    kfold= KFold(n_splits=k_fold,random_state =None,shuffle=True)

    for i,(train_index,val_index) in zip(range(k_fold),kfold.split(data,target)):

        train_x,val_x,train_y,val_y=data[train_index,:],data[val_index,:],target[train_index],target[val_index]

        #構建DMatrix數據

        dtrain = xgb.DMatrix(train_x,train_y)

        dtest = xgb.DMatrix(val_x,val_y)

        if silent==0:

            print("開始第{}/{}折驗證:".format(i,k_fold))

        #模型訓練

        bst = xgb.train(params, dtrain, num_round)

        #6.模型預測

        preds = bst.predict(dtest)

        preds=np.exp(preds)-1#轉換成真實的租金

        y_true=np.exp(val_y)-1

        rmse=np.sqrt(mean_squared_error(y_true,preds))

        if silent==0:

            print("第{}/{}折驗證rmse:{}".format(i,k_fold,rmse))

        rmses.append(rmse)

    return sum(rmses)/k_fold

 

def search_params(x,y,params_grid,n_estimators=200,cv=3,silent=0):

    min_rmse=9999

    best_params=None

    params_list=[[]]

    #根據參數表格構建所有參數組合

    for k,v in params_grid.items():

        if isinstance(v,list):

            temp=params_list

            params_list=[i+[j] for j in v for i in temp]

        else:

            params_list=[i+[v] for i in params_list]

    params_list=[{k:v for k,v in zip(params_grid.keys(),v_list)} for v_list in params_list]

    for i,params in zip(range(len(params_list)),params_list):

        if silent==0:

            print("開始實驗第{}組參數:".format(i),params)

        rmse=train_cv(data=x,target=y,params=params,num_round=n_estimators,k_fold=cv)

        if silent==0:

            print("第{}組參數平均rmse:{}".format(i,rmse))

            print("-"*50)

        if rmse<min_rmse:

            min_rmse=rmse

            best_params=params

    return min_rmse,best_params


 

開始搜索

In [34]:

params_dict={

    "objective":'reg:linear',

    'eta':[0.01,0.1,0.5],

    'gamma': [0.01,0.05,0.1],

    'silent': 1,

    'max_depth':[15,25,35], 

    'min_child_weight':[0.5,1,3],

}

cols=['小區房屋出租數量', '樓層', '總樓層', '房屋面積','居住狀態', '臥室數量',

       '衛的數量',  '位置',  '地鐵站點', '距離', '裝修情況', 

       '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型','平均值特徵1',

       '平均值特徵2','有地鐵','小區線路數','位置線路數','小區條數大於100','小區平均值特徵','朝向平均值特徵',

           '站點平均值特徵','位置平均值特徵']

#1.獲取數據集

train_x,test_x,train_y,test_y=d

#獲取原始特徵對應的新特徵下標

index=[]

for col in cols:

    index.extend(f_map[col])

x_train=train_x[:50000,index]#只用前50000條數據做運算

x_test=test_x[:,index]

#由於要用新下標訪問,所以要重置索引

train_y=train_y.reset_index(drop=True)[:50000]

test_y=test_y.reset_index(drop=True)

search_params(x=x_train,y=train_y,params_grid=params_dict,n_estimators=1000)

開始實驗第0組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.1063645180292268
開始第1/3折驗證:
第1/3折驗證rmse:2.270438488734099
開始第2/3折驗證:
第2/3折驗證rmse:2.140966941345831
第0組參數平均rmse:2.172589982703052
--------------------------------------------------
開始實驗第1組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.1029110307375034
開始第1/3折驗證:
第1/3折驗證rmse:2.151089425447841
開始第2/3折驗證:
第2/3折驗證rmse:2.2555141001168315
第1組參數平均rmse:2.169838185434059
--------------------------------------------------
開始實驗第2組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.4535784391141995
開始第1/3折驗證:
第1/3折驗證rmse:2.424286846886855
開始第2/3折驗證:
第2/3折驗證rmse:2.1266645639199573
第2組參數平均rmse:2.334843283307004
--------------------------------------------------
開始實驗第3組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.1509258765444517
開始第1/3折驗證:
第1/3折驗證rmse:2.2639212917057883
開始第2/3折驗證:
第2/3折驗證rmse:2.208002017298694
第3組參數平均rmse:2.207616395182978
--------------------------------------------------
開始實驗第4組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.224230101453484
開始第1/3折驗證:
第1/3折驗證rmse:2.194730061107077
開始第2/3折驗證:
第2/3折驗證rmse:2.104946600682978
第4組參數平均rmse:2.1746355877478463
--------------------------------------------------
開始實驗第5組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.4173987601952147
開始第1/3折驗證:
第1/3折驗證rmse:2.3193751890787064
開始第2/3折驗證:
第2/3折驗證rmse:2.350550916955072
第5組參數平均rmse:2.362441622076331
--------------------------------------------------
開始實驗第6組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.150912061182521
開始第1/3折驗證:
第1/3折驗證rmse:2.1842688983958243
開始第2/3折驗證:
第2/3折驗證rmse:2.4129215673670013
第6組參數平均rmse:2.249367508981782
--------------------------------------------------
開始實驗第7組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.2327447467966457
開始第1/3折驗證:
第1/3折驗證rmse:2.4065138418376923
開始第2/3折驗證:
第2/3折驗證rmse:2.286097658735343
第7組參數平均rmse:2.30845208245656
--------------------------------------------------
開始實驗第8組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.3313455873087507
開始第1/3折驗證:
第1/3折驗證rmse:2.4397538237904057
開始第2/3折驗證:
第2/3折驗證rmse:2.31328569652659
第8組參數平均rmse:2.361461702541915
--------------------------------------------------
開始實驗第9組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.351802702595958
開始第1/3折驗證:
第1/3折驗證rmse:2.230930544499273
開始第2/3折驗證:
第2/3折驗證rmse:2.251661755576135
第9組參數平均rmse:2.278131667557122
--------------------------------------------------
開始實驗第10組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.327051827692085
開始第1/3折驗證:
第1/3折驗證rmse:2.3296903644220945
開始第2/3折驗證:
第2/3折驗證rmse:2.384475189364813
第10組參數平均rmse:2.347072460492998
--------------------------------------------------
開始實驗第11組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.630278587228796
開始第1/3折驗證:
第1/3折驗證rmse:2.222563695431261
開始第2/3折驗證:
第2/3折驗證rmse:2.2461094587201518
第11組參數平均rmse:2.366317247126736
--------------------------------------------------
開始實驗第12組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.125414735583022
開始第1/3折驗證:
第1/3折驗證rmse:2.2014928222849846
開始第2/3折驗證:
第2/3折驗證rmse:2.097238703895008
第12組參數平均rmse:2.141382087254338
--------------------------------------------------
開始實驗第13組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.4197639273877596
開始第1/3折驗證:
第1/3折驗證rmse:2.146503225999798
開始第2/3折驗證:
第2/3折驗證rmse:2.1724123431688636
第13組參數平均rmse:2.2462264988521405
--------------------------------------------------
開始實驗第14組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.512321338137171
開始第1/3折驗證:
第1/3折驗證rmse:2.4320489841732864
開始第2/3折驗證:
第2/3折驗證rmse:2.283527320349841
第14組參數平均rmse:2.4092992142200997
--------------------------------------------------
開始實驗第15組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.1677308366792225
開始第1/3折驗證:
第1/3折驗證rmse:2.255620150072001
開始第2/3折驗證:
第2/3折驗證rmse:2.3948376802971194
第15組參數平均rmse:2.272729555682781
--------------------------------------------------
開始實驗第16組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.347093266421053
開始第1/3折驗證:
第1/3折驗證rmse:2.3134536451552785
開始第2/3折驗證:
第2/3折驗證rmse:2.2327661973592092
第16組參數平均rmse:2.297771036311847
--------------------------------------------------
開始實驗第17組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.3748013645667525
開始第1/3折驗證:
第1/3折驗證rmse:2.358196569845885
開始第2/3折驗證:
第2/3折驗證rmse:2.4795866533195476
第17組參數平均rmse:2.404194862577395
--------------------------------------------------
開始實驗第18組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.240512423440991
開始第1/3折驗證:
第1/3折驗證rmse:2.1091848489427965
開始第2/3折驗證:
第2/3折驗證rmse:2.288639830011804
第18組參數平均rmse:2.212779034131864
--------------------------------------------------
開始實驗第19組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.1775090908414034
開始第1/3折驗證:
第1/3折驗證rmse:2.202914246471916
開始第2/3折驗證:
第2/3折驗證rmse:2.3757522648670806
第19組參數平均rmse:2.2520585340601333
--------------------------------------------------
開始實驗第20組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.412426495391516
開始第1/3折驗證:
第1/3折驗證rmse:2.3243322412870735
開始第2/3折驗證:
第2/3折驗證rmse:2.3949040510708914
第20組參數平均rmse:2.377220929249827
--------------------------------------------------
開始實驗第21組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.269681476252998
開始第1/3折驗證:
第1/3折驗證rmse:2.146913481367659
開始第2/3折驗證:
第2/3折驗證rmse:2.2304382113812
第21組參數平均rmse:2.2156777230006193
--------------------------------------------------
開始實驗第22組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.438955492998712
開始第1/3折驗證:
第1/3折驗證rmse:2.1329319198071146
開始第2/3折驗證:
第2/3折驗證rmse:2.124099501339859
第22組參數平均rmse:2.2319956380485624
--------------------------------------------------
開始實驗第23組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.503644611663843
開始第1/3折驗證:
第1/3折驗證rmse:2.528994032876117
開始第2/3折驗證:
第2/3折驗證rmse:2.312941463640303
第23組參數平均rmse:2.4485267027267543
--------------------------------------------------
開始實驗第24組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.237095467623757
開始第1/3折驗證:
第1/3折驗證rmse:2.4029885243008007
開始第2/3折驗證:
第2/3折驗證rmse:2.2734978813307447
第24組參數平均rmse:2.3045272910851007
--------------------------------------------------
開始實驗第25組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.306825279691586
開始第1/3折驗證:
第1/3折驗證rmse:2.244977467458515
開始第2/3折驗證:
第2/3折驗證rmse:2.1922851419755007
第25組參數平均rmse:2.2480292963752
--------------------------------------------------
開始實驗第26組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 0.5}
開始第0/3折驗證:
第0/3折驗證rmse:2.3549137991155114
開始第1/3折驗證:
第1/3折驗證rmse:2.592401863979216
開始第2/3折驗證:
第2/3折驗證rmse:2.29801882782804
第26組參數平均rmse:2.4151114969742555
--------------------------------------------------
開始實驗第27組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.171764054695917
開始第1/3折驗證:
第1/3折驗證rmse:2.2142377501924937
開始第2/3折驗證:
第2/3折驗證rmse:2.284722624617894
第27組參數平均rmse:2.223574809835435
--------------------------------------------------
開始實驗第28組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.1858975633007525
開始第1/3折驗證:
第1/3折驗證rmse:2.4068418601897177
開始第2/3折驗證:
第2/3折驗證rmse:2.0969563799576494
第28組參數平均rmse:2.229898601149373
--------------------------------------------------
開始實驗第29組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.388813347279593
開始第1/3折驗證:
第1/3折驗證rmse:2.284844842576387
開始第2/3折驗證:
第2/3折驗證rmse:2.4146204135428695
第29組參數平均rmse:2.362759534466283
--------------------------------------------------
開始實驗第30組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.2487871387994858
開始第1/3折驗證:
第1/3折驗證rmse:2.1714058400384646
開始第2/3折驗證:
第2/3折驗證rmse:2.184533044019575
第30組參數平均rmse:2.2015753409525085
--------------------------------------------------
開始實驗第31組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.2972859501336935
開始第1/3折驗證:
第1/3折驗證rmse:2.2362463997194886
開始第2/3折驗證:
第2/3折驗證rmse:2.2898365113716483
第31組參數平均rmse:2.2744562870749436
--------------------------------------------------
開始實驗第32組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.419329912099752
開始第1/3折驗證:
第1/3折驗證rmse:2.6154375686147384
開始第2/3折驗證:
第2/3折驗證rmse:2.230305815806549
第32組參數平均rmse:2.4216910988403466
--------------------------------------------------
開始實驗第33組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.200577515646503
開始第1/3折驗證:
第1/3折驗證rmse:2.2299424412995243
開始第2/3折驗證:
第2/3折驗證rmse:2.3140760122142896
第33組參數平均rmse:2.2481986563867724
--------------------------------------------------
開始實驗第34組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.57849663446406
開始第1/3折驗證:
第1/3折驗證rmse:2.116087043730732
開始第2/3折驗證:
第2/3折驗證rmse:2.274100944461905
第34組參數平均rmse:2.3228948742188993
--------------------------------------------------
開始實驗第35組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.3050644007916503
開始第1/3折驗證:
第1/3折驗證rmse:2.5075464973857162
開始第2/3折驗證:
第2/3折驗證rmse:2.3930588500403567
第35組參數平均rmse:2.4018899160725744
--------------------------------------------------
開始實驗第36組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.276957221983997
開始第1/3折驗證:
第1/3折驗證rmse:2.3703205041784905
開始第2/3折驗證:
第2/3折驗證rmse:2.1867592895461
第36組參數平均rmse:2.278012338569529
--------------------------------------------------
開始實驗第37組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.2507333499616866
開始第1/3折驗證:
第1/3折驗證rmse:2.2480253735311346
開始第2/3折驗證:
第2/3折驗證rmse:2.2176798693697006
第37組參數平均rmse:2.238812864287507
--------------------------------------------------
開始實驗第38組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.2951887068467824
開始第1/3折驗證:
第1/3折驗證rmse:2.3602517398138096
開始第2/3折驗證:
第2/3折驗證rmse:2.3994056671768162
第38組參數平均rmse:2.351615371279136
--------------------------------------------------
開始實驗第39組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.1837643392924027
開始第1/3折驗證:
第1/3折驗證rmse:2.2504664193983692
開始第2/3折驗證:
第2/3折驗證rmse:2.135889446314574
第39組參數平均rmse:2.190040068335115
--------------------------------------------------
開始實驗第40組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.0869573705948192
開始第1/3折驗證:
第1/3折驗證rmse:2.2127491322380353
開始第2/3折驗證:
第2/3折驗證rmse:2.3164522580246296
第40組參數平均rmse:2.2053862536191615
--------------------------------------------------
開始實驗第41組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.188863229863099
開始第1/3折驗證:
第1/3折驗證rmse:2.400519116701612
開始第2/3折驗證:
第2/3折驗證rmse:2.4379628348438347
第41組參數平均rmse:2.3424483938028486
--------------------------------------------------
開始實驗第42組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.454450166538962
開始第1/3折驗證:
第1/3折驗證rmse:2.0656417463376475
開始第2/3折驗證:
第2/3折驗證rmse:2.3655598707868464
第42組參數平均rmse:2.295217261221152
--------------------------------------------------
開始實驗第43組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.1824157942948537
開始第1/3折驗證:
第1/3折驗證rmse:2.3676364588012406
開始第2/3折驗證:
第2/3折驗證rmse:2.145039852244817
第43組參數平均rmse:2.2316973684469708
--------------------------------------------------
開始實驗第44組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.396458431999462
開始第1/3折驗證:
第1/3折驗證rmse:2.4112866277165343
開始第2/3折驗證:
第2/3折驗證rmse:2.383011977510674
第44組參數平均rmse:2.39691901240889
--------------------------------------------------
開始實驗第45組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.3398767792743698
開始第1/3折驗證:
第1/3折驗證rmse:2.150834454625684
開始第2/3折驗證:
第2/3折驗證rmse:2.3983698308079955
第45組參數平均rmse:2.296360354902683
--------------------------------------------------
開始實驗第46組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.1467337553620087
開始第1/3折驗證:
第1/3折驗證rmse:2.067141831677618
開始第2/3折驗證:
第2/3折驗證rmse:2.246084426708412
第46組參數平均rmse:2.1533200045826795
--------------------------------------------------
開始實驗第47組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.291145736550947
開始第1/3折驗證:
第1/3折驗證rmse:2.4679262622671856
開始第2/3折驗證:
第2/3折驗證rmse:2.3334840777758163
第47組參數平均rmse:2.3641853588646495
--------------------------------------------------
開始實驗第48組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.2070883532476704
開始第1/3折驗證:
第1/3折驗證rmse:2.0854684885544548
開始第2/3折驗證:
第2/3折驗證rmse:2.190895382039525
第48組參數平均rmse:2.1611507412805504
--------------------------------------------------
開始實驗第49組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.2406075908241965
開始第1/3折驗證:
第1/3折驗證rmse:2.1997157111560504
開始第2/3折驗證:
第2/3折驗證rmse:2.3159740377238247
第49組參數平均rmse:2.2520991132346904
--------------------------------------------------
開始實驗第50組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.4411125744725406
開始第1/3折驗證:
第1/3折驗證rmse:2.45578081917117
開始第2/3折驗證:
第2/3折驗證rmse:2.2108615863413847
第50組參數平均rmse:2.3692516599950317
--------------------------------------------------
開始實驗第51組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.3555601196130684
開始第1/3折驗證:
第1/3折驗證rmse:2.1563837142863638
開始第2/3折驗證:
第2/3折驗證rmse:2.2789944615773194
第51組參數平均rmse:2.2636460984922504
--------------------------------------------------
開始實驗第52組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.2950794012987616
開始第1/3折驗證:
第1/3折驗證rmse:2.2213071464839884
開始第2/3折驗證:
第2/3折驗證rmse:2.169220925172176
第52組參數平均rmse:2.2285358243183087
--------------------------------------------------
開始實驗第53組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 1}
開始第0/3折驗證:
第0/3折驗證rmse:2.3781817980568287
開始第1/3折驗證:
第1/3折驗證rmse:2.2231348209756074
開始第2/3折驗證:
第2/3折驗證rmse:2.452517601712933
第53組參數平均rmse:2.3512780735817898
--------------------------------------------------
開始實驗第54組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.1697340094788573
開始第1/3折驗證:
第1/3折驗證rmse:2.1152437442840575
開始第2/3折驗證:
第2/3折驗證rmse:2.2024548685544176
第54組參數平均rmse:2.162477540772444
--------------------------------------------------
開始實驗第55組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.209310097715091
開始第1/3折驗證:
第1/3折驗證rmse:2.138762610248193
開始第2/3折驗證:
第2/3折驗證rmse:2.2925897483081115
第55組參數平均rmse:2.2135541520904654
--------------------------------------------------
開始實驗第56組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.396555278419278
開始第1/3折驗證:
第1/3折驗證rmse:2.363139367149146
開始第2/3折驗證:
第2/3折驗證rmse:2.2318443518447233
第56組參數平均rmse:2.330512999137716
--------------------------------------------------
開始實驗第57組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.350916617214958
開始第1/3折驗證:
第1/3折驗證rmse:2.426769178733778
開始第2/3折驗證:
第2/3折驗證rmse:2.1294132232677314
第57組參數平均rmse:2.3023663397388225
--------------------------------------------------
開始實驗第58組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.2718710349597204
開始第1/3折驗證:
第1/3折驗證rmse:2.2724245754078067
開始第2/3折驗證:
第2/3折驗證rmse:2.1415978768994695
第58組參數平均rmse:2.228631162422332
--------------------------------------------------
開始實驗第59組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.501290093920802
開始第1/3折驗證:
第1/3折驗證rmse:2.381049210488406
開始第2/3折驗證:
第2/3折驗證rmse:2.2750317759288943
第59組參數平均rmse:2.3857903601127006
--------------------------------------------------
開始實驗第60組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.3181114399810796
開始第1/3折驗證:
第1/3折驗證rmse:2.2154998493769624
開始第2/3折驗證:
第2/3折驗證rmse:2.4049210337342464
第60組參數平均rmse:2.3128441076974293
--------------------------------------------------
開始實驗第61組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.3851664509564388
開始第1/3折驗證:
第1/3折驗證rmse:2.3030068446632947
開始第2/3折驗證:
第2/3折驗證rmse:2.280847797963317
第61組參數平均rmse:2.3230070311943503
--------------------------------------------------
開始實驗第62組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 15, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.417937402473705
開始第1/3折驗證:
第1/3折驗證rmse:2.3997823968592797
開始第2/3折驗證:
第2/3折驗證rmse:2.380405546022984
第62組參數平均rmse:2.399375115118656
--------------------------------------------------
開始實驗第63組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.174178876935193
開始第1/3折驗證:
第1/3折驗證rmse:2.266418809440447
開始第2/3折驗證:
第2/3折驗證rmse:2.045909029982191
第63組參數平均rmse:2.16216890545261
--------------------------------------------------
開始實驗第64組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.1185599029996527
開始第1/3折驗證:
第1/3折驗證rmse:2.2976351878015926
開始第2/3折驗證:
第2/3折驗證rmse:2.371055913517158
第64組參數平均rmse:2.262417001439468
--------------------------------------------------
開始實驗第65組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.4192265174807486
開始第1/3折驗證:
第1/3折驗證rmse:2.547778062631276
開始第2/3折驗證:
第2/3折驗證rmse:2.453398370601104
第65組參數平均rmse:2.4734676502377098
--------------------------------------------------
開始實驗第66組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.3116700347493646
開始第1/3折驗證:
第1/3折驗證rmse:2.142077163214947
開始第2/3折驗證:
第2/3折驗證rmse:2.1577471460239233
第66組參數平均rmse:2.203831447996078
--------------------------------------------------
開始實驗第67組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.260847355749237
開始第1/3折驗證:
第1/3折驗證rmse:2.038611778956116
開始第2/3折驗證:
第2/3折驗證rmse:2.5484310808888635
第67組參數平均rmse:2.2826300718647388
--------------------------------------------------
開始實驗第68組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.3981763646113885
開始第1/3折驗證:
第1/3折驗證rmse:2.2875108174804377
開始第2/3折驗證:
第2/3折驗證rmse:2.414449111458425
第68組參數平均rmse:2.3667120978500837
--------------------------------------------------
開始實驗第69組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.28888986741368
開始第1/3折驗證:
第1/3折驗證rmse:2.2767189333146267
開始第2/3折驗證:
第2/3折驗證rmse:2.33555813056071
第69組參數平均rmse:2.3003889770963393
--------------------------------------------------
開始實驗第70組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.1262568065515675
開始第1/3折驗證:
第1/3折驗證rmse:2.2618381987583054
開始第2/3折驗證:
第2/3折驗證rmse:2.1984332633424066
第70組參數平均rmse:2.1955094228840935
--------------------------------------------------
開始實驗第71組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 25, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.503310188661614
開始第1/3折驗證:
第1/3折驗證rmse:2.3547656436918927
開始第2/3折驗證:
第2/3折驗證rmse:2.305990528979543
第71組參數平均rmse:2.3880221204443495
--------------------------------------------------
開始實驗第72組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.121248127368896
開始第1/3折驗證:
第1/3折驗證rmse:2.297606544576462
開始第2/3折驗證:
第2/3折驗證rmse:2.127186689902887
第72組參數平均rmse:2.1820137872827483
--------------------------------------------------
開始實驗第73組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.1410764654177217
開始第1/3折驗證:
第1/3折驗證rmse:2.264051683017106
開始第2/3折驗證:
第2/3折驗證rmse:2.272036190864403
第73組參數平均rmse:2.225721446433077
--------------------------------------------------
開始實驗第74組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.01, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.282223990590916
開始第1/3折驗證:
第1/3折驗證rmse:2.4344388315143215
開始第2/3折驗證:
第2/3折驗證rmse:2.1473976008596702
第74組參數平均rmse:2.2880201409883028
--------------------------------------------------
開始實驗第75組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.2557078363373244
開始第1/3折驗證:
第1/3折驗證rmse:2.012167036686711
開始第2/3折驗證:
第2/3折驗證rmse:2.187687495347084
第75組參數平均rmse:2.151854122790373
--------------------------------------------------
開始實驗第76組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.2177760911023863
開始第1/3折驗證:
第1/3折驗證rmse:2.06291663889677
開始第2/3折驗證:
第2/3折驗證rmse:2.2830701173735686
第76組參數平均rmse:2.187920949124242
--------------------------------------------------
開始實驗第77組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.05, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.3170419334417427
開始第1/3折驗證:
第1/3折驗證rmse:2.366394134764698
開始第2/3折驗證:
第2/3折驗證rmse:2.3975321343351474
第77組參數平均rmse:2.3603227341805293
--------------------------------------------------
開始實驗第78組參數: {'objective': 'reg:linear', 'eta': 0.01, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.1943993462539413
開始第1/3折驗證:
第1/3折驗證rmse:2.389702628638741
開始第2/3折驗證:
第2/3折驗證rmse:2.087077836239587
第78組參數平均rmse:2.2237266037107566
--------------------------------------------------
開始實驗第79組參數: {'objective': 'reg:linear', 'eta': 0.1, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.183353747113912
開始第1/3折驗證:
第1/3折驗證rmse:2.209950759672495
開始第2/3折驗證:
第2/3折驗證rmse:2.2352641756192404
第79組參數平均rmse:2.209522894135216
--------------------------------------------------
開始實驗第80組參數: {'objective': 'reg:linear', 'eta': 0.5, 'gamma': 0.1, 'silent': 1, 'max_depth': 35, 'min_child_weight': 3}
開始第0/3折驗證:
第0/3折驗證rmse:2.3471298414272037
開始第1/3折驗證:
第1/3折驗證rmse:2.2745681485301392
開始第2/3折驗證:
第2/3折驗證rmse:2.386511745091769
第80組參數平均rmse:2.3360699116830372
--------------------------------------------------

Out[34]:

(2.141382087254338,
 {'objective': 'reg:linear',
  'eta': 0.01,
  'gamma': 0.05,
  'silent': 1,
  'max_depth': 25,
  'min_child_weight': 0.5})

In [35]:

#1.獲取數據集

train_x,test_x,train_y,test_y=d

#獲取原始特徵對應的新特徵下標

index=[]

for col in cols:

    index.extend(f_map[col])

x_train=train_x[:,index]

x_test=test_x[:,index]

#由於要用新下標訪問,所以要重置索引

train_y=train_y.reset_index(drop=True)

test_y=test_y.reset_index(drop=True)

利用搜索的參數訓練模型

In [36]:

# xgb_model = xgb.XGBRegressor(max_depth=5, learning_rate=0.01, n_estimators=500,verbosity=1, objective='reg:linear',random_state=12,)

# xgb_model.fit(new_train_x, train_y, early_stopping_rounds=10, eval_metric="rmse",

#         eval_set=[(new_test_x, test_y)])

params={

    "objective":'reg:linear',

    'eta':0.01,

    'gamma': 0.05,

    'silent': 1,

    'max_depth':25, 

    'min_child_weight':0.5,

    'sub_sample':0.6,

    'reg_alpha':0.5,

    'reg_lambda':0.8,

    'colsample_bytree':0.5

}

dtrain = xgb.DMatrix(x_train,train_y)

dtest = xgb.DMatrix(x_test,test_y)

bst = xgb.train(params, dtrain, num_boost_round=1500)

#6.模型預測

preds = bst.predict(dtest)

preds=np.exp(preds)-1#轉換成真實的租金

y_true=np.exp(test_y)-1

rmse=np.sqrt(mean_squared_error(y_true,preds))

rmse

Out[36]:

1.4322241873197603

In [124]:

# cv_params = {'n_estimators': [400, 500, 600, 700, 800]}

# other_params = {'learning_rate': 0.1, 'n_estimators': 500, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,

#                 'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}

# model = xgb.XGBRegressor(**other_params)

# optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5, verbose=1)

# optimized_GBM.fit(new_train_x, train_y)

# evalute_result = optimized_GBM.grid_scores_

# print('每輪迭代運行結果:{0}'.format(evalute_result))

# print('參數的最佳取值:{0}'.format(optimized_GBM.best_params_))

# print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))

rmse

Out[124]:

1.5180160328127699

模型融合

In [1]:

from sklearn.linear_model import RidgeCV,LassoCV,Ridge,Lasso

from sklearn.svm import LinearSVR,SVR

from sklearn.ensemble import RandomForestRegressor,AdaBoostRegressor,GradientBoostingRegressor

from sklearn.neural_network import MLPRegressor

from sklearn.model_selection import train_test_split,GridSearchCV

from sklearn.feature_extraction import DictVectorizer

from sklearn.preprocessing import StandardScaler,PolynomialFeatures

from sklearn.decomposition import PCA

import pandas as pd

import numpy as np

from sklearn.metrics import mean_squared_error

In [ ]:

#沒有用bagging和boosting

#stacking    先用幾個不同的模型做預測  輸出預測值  然後將這幾個模型輸出的預測值作爲特徵來訓練一個新的模型

獲取數據

In [2]:

data=pd.read_csv("data/onehot_feature.csv")

data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 196499 entries, 0 to 196498
Data columns (total 41 columns):
Unnamed: 0    196499 non-null int64
時間            196499 non-null int64
小區名           196499 non-null int64
小區房屋出租數量      196499 non-null float64
樓層            196499 non-null int64
總樓層           196499 non-null float64
房屋面積          196499 non-null float64
房屋朝向          196499 non-null object
居住狀態          196499 non-null float64
臥室數量          196499 non-null int64
廳的數量          196499 non-null int64
衛的數量          196499 non-null int64
出租方式          196499 non-null float64
區             196499 non-null float64
位置            196499 non-null float64
地鐵線路          196499 non-null float64
地鐵站點          196499 non-null float64
距離            196499 non-null float64
裝修情況          196499 non-null float64
月租金           196499 non-null float64
log_rent      196499 non-null float64
新朝向           196499 non-null object
房+衛+廳         196499 non-null int64
房/總           196499 non-null float64
衛/總           196499 non-null float64
廳/總           196499 non-null float64
臥室面積          196499 non-null float64
樓層比           196499 non-null float64
戶型            196499 non-null int64
平均值特徵1        196499 non-null float64
小區平均值特徵       196499 non-null float64
朝向平均值特徵       196499 non-null float64
站點平均值特徵       196499 non-null float64
位置平均值特徵       196499 non-null float64
有地鐵           196499 non-null int64
聚類特徵          196499 non-null int64
平均值特徵2        196499 non-null float64
小區線路數         196499 non-null int64
位置線路數         196499 non-null int64
新小區名          196499 non-null int64
小區條數大於100     196499 non-null int64
dtypes: float64(24), int64(15), object(2)
memory usage: 61.5+ MB

In [3]:

#將離散特徵轉換成字符串類型

colunms = ['時間', '新小區名', '居住狀態', '出租方式', '區','位置','地鐵線路','地鐵站點','裝修情況','戶型','聚類特徵']

for col in colunms:

    data[col] = data[col].astype(str)

In [4]:

x_columns=['小區房屋出租數量','新小區名', '樓層', '總樓層', '房屋面積','居住狀態', '臥室數量',

       '衛的數量',  '位置',  '地鐵站點', '距離', '裝修情況', 

       '新朝向', '房+衛+廳', '房/總', '衛/總', '廳/總', '臥室面積', '樓層比', '戶型','平均值特徵1',

       '平均值特徵2','有地鐵','小區線路數','位置線路數','小區條數大於100','小區平均值特徵','朝向平均值特徵',

           '站點平均值特徵','位置平均值特徵']

y_label='log_rent'

x=data[x_columns]

y=data[y_label]

In [5]:

#2.分割數據集

train_x,test_x,train_y,test_y=train_test_split(x,y,test_size=0.3,random_state=12)

In [6]:

#3.特徵轉換

vector=DictVectorizer(sparse=True)

x_train=vector.fit_transform(train_x.to_dict(orient='records'))

x_test=vector.transform(test_x.to_dict(orient='records'))

In [7]:

x_train.shape

Out[7]:

(137549, 964)

In [8]:

#4.降維----線性迴歸和svm可以採用降維後的特徵

pca=PCA(0.98)

pca_x_train=pca.fit_transform(x_train.toarray())

pca_x_test=pca.transform(x_test.toarray())

In [9]:

pca_x_train.shape

Out[9]:

(137549, 407)

In [10]:

#5.特徵標準化

trans=StandardScaler()

new_x_train=trans.fit_transform(pca_x_train)

new_x_test=trans.transform(pca_x_test)

In [11]:

new_x_train.shape

Out[11]:

(137549, 407)

In [12]:

# ploy=PolynomialFeatures(degree=2,interaction_only=True)

# ploy_x_train=ploy.fit_transform(new_x_train)

# ploy_x_test=ploy.transform(new_x_test)

In [13]:

# ploy_x_train.shape

In [14]:

def rmse(y_true,y_pred):

    y_pred=np.exp(y_pred)-1#轉換成真實的租金

    y_true=np.exp(y_true)-1

    return np.sqrt(mean_squared_error(y_true,y_pred))

構建子模型

構建嶺迴歸模型

In [15]:

# #1.參數搜索

# ridge=Ridge()

# params={

#     "alpha":[0.005,0.01,1,5,10,20,50]

# }

# model1=GridSearchCV(ridge,param_grid=params,cv=5,n_jobs=-1)

# model1.fit(new_x_train,train_y)

# model1.best_params_   

# #{'alpha': 10, 'fit_intercept': True}

In [16]:

#利用搜索出的最優參數構建模型

ridge=Ridge(alpha=0.005)

ridge.fit(new_x_train,train_y)

Out[16]:

Ridge(alpha=0.005, copy_X=True, fit_intercept=True, max_iter=None,
      normalize=False, random_state=None, solver='auto', tol=0.001)

In [17]:

y_pred_test=ridge.predict(new_x_test)

y_pred_train=ridge.predict(new_x_train)

print("訓練集rmse:",rmse(train_y,y_pred_train))

print("測試集rmse:",rmse(test_y,y_pred_test))

訓練集rmse: 3.162947362147576
測試集rmse: 3.1450837952700987

構建lasso迴歸

In [18]:

# #1.參數搜索

# lasso=Lasso()

# params={

#     "alpha":[0.001,0.01,0.05,0.1,0.5,1,5,10],

#     "fit_intercept":[True,False] 

# }

# model2=GridSearchCV(lasso,param_grid=params,cv=5,n_jobs=-1)

# model2.fit(new_x_train,train_y)

# model2.best_params_

# #{'alpha': 0.001, 'fit_intercept': True}

In [19]:

#利用搜索出的最優參數構建模型

lasso=Lasso(alpha=0.001)

lasso.fit(new_x_train,train_y)

Out[19]:

Lasso(alpha=0.001, copy_X=True, fit_intercept=True, max_iter=1000,
      normalize=False, positive=False, precompute=False, random_state=None,
      selection='cyclic', tol=0.0001, warm_start=False)

In [20]:

y_pred_test=lasso.predict(new_x_test)

y_pred_train=lasso.predict(new_x_train)

print("訓練集rmse:",rmse(train_y,y_pred_train))

print("測試集rmse:",rmse(test_y,y_pred_test))

訓練集rmse: 3.17469838175572
測試集rmse: 3.1600537035148

構建隨機森林

In [55]:

# #1.參數搜索 

# rf=RandomForestRegressor(max_features='sqrt')#設置max_features='sqrt',不然太耗時間

# params={

#     "n_estimators":[200],#[200,500,700],

#     "max_depth":[40,50,60],

#     "min_samples_split":[20,50,100],

#     "min_samples_leaf":[10,20,30]

# }

# model3=GridSearchCV(rf,param_grid=params,cv=5,n_jobs=-1,verbose=2)

# model3.fit(x_train,train_y)

# model3.best_params_

# # {'max_depth': 50,

# #  'min_samples_leaf': 10,

# #  'min_samples_split': 20,

# #  'n_estimators': 200}

Fitting 5 folds for each of 27 candidates, totalling 135 fits

[Parallel(n_jobs=-1)]: Using backend LokyBackend with 20 concurrent workers.
[Parallel(n_jobs=-1)]: Done   1 tasks      | elapsed:  5.1min
[Parallel(n_jobs=-1)]: Done 135 out of 135 | elapsed: 35.5min finished

Out[55]:

{'max_depth': 50,
'min_samples_leaf': 10,
'min_samples_split': 20,
'n_estimators': 200}

In [ ]:

# import time

# print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 

In [21]:

#利用搜索出的最優參數構建模型

rf=RandomForestRegressor(n_estimators=200,

                         max_features=0.8,

                         max_depth=50,

                         min_samples_split=20,

                         min_samples_leaf=10,

                         n_jobs=-1)

rf.fit(x_train,train_y)

Out[21]:

RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=50,
                      max_features=0.8, max_leaf_nodes=None,
                      min_impurity_decrease=0.0, min_impurity_split=None,
                      min_samples_leaf=10, min_samples_split=20,
                      min_weight_fraction_leaf=0.0, n_estimators=200, n_jobs=-1,
                      oob_score=False, random_state=None, verbose=0,
                      warm_start=False)

In [22]:

y_pred_test=rf.predict(x_test)

y_pred_train=rf.predict(x_train)

print("訓練集rmse:",rmse(train_y,y_pred_train))

print("測試集rmse:",rmse(test_y,y_pred_test))

訓練集rmse: 1.8016406346453875
測試集rmse: 2.078690010364972

構建決策樹

In [93]:

# tree=DecisionTreeRegressor()

# params={

#     "max_depth":[40,50,60,70],

#     "min_samples_split":[5,10,20,30,40,50],

#     "min_samples_leaf":[2,3,5,7,9,11]

# }

# model4=GridSearchCV(tree,param_grid=params,cv=5,n_jobs=-1)

# model4.fit(x_train,train_y)

# model4.best_params_

# {'max_depth': 60, 'min_samples_leaf': 2, 'min_samples_split': 5}

Out[93]:

{'max_depth': 60, 'min_samples_leaf': 2, 'min_samples_split': 5}

In [94]:

from sklearn.tree import DecisionTreeRegressor

#利用搜索出的最優參數構建模型

tree=DecisionTreeRegressor(max_depth=60,min_samples_leaf=2,min_samples_split=5)

tree.fit(x_train,train_y)

Out[94]:

DecisionTreeRegressor(criterion='mse', max_depth=60, max_features=None,
                      max_leaf_nodes=None, min_impurity_decrease=0.0,
                      min_impurity_split=None, min_samples_leaf=2,
                      min_samples_split=5, min_weight_fraction_leaf=0.0,
                      presort=False, random_state=None, splitter='best')

In [95]:

y_pred_test=tree.predict(x_test)

y_pred_train=tree.predict(x_train)

print("訓練集rmse:",rmse(train_y,y_pred_train))

print("測試集rmse:",rmse(test_y,y_pred_test))

訓練集rmse: 0.7147616009940363
測試集rmse: 1.5876633153093507

In [96]:

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif']=['SimHei']

plt.rcParams['axes.unicode_minus']=False

plt.figure(figsize=(20,20),dpi=100)

plt.scatter(test_y,y_pred_test)

plt.xlabel("真實值")

plt.ylabel("預測值")

plt.show()

構建支持向量機

In [1]:

# #1.參數搜索----數據量大 svm太耗時,調參幾乎不可能

# svr=SVR()

# params={

#     "gamma":[0.001,0.01,0.1,0.5,1,5],

#     "C":[0.001,0.1,0.5,1,5] 

# }

# model5=GridSearchCV(svr,param_grid=params,cv=5,n_jobs=-1,verbose=10)

# model5.fit(new_x_train,train_y)

# model5.best_params_

In [ ]:

# #隨意選一組參數   --- 耗時太長 放棄該模型

# svr=SVR(gamma=0.1,C=0.5)

# svr.fit(new_x_train,train_y)

# y_pred=svr.predict(new_x_test)

# rmse(test_y,y_pred)

構建xgboost模型

In [25]:

import xgboost as xgb

params={

    "objective":'reg:linear',

    'eta':0.1,

    'gamma': 0.05,

    'silent': 1,

    'max_depth':45, 

    'min_child_weight':0.5,

    'sub_sample':0.6,

    'reg_alpha':0.5,

    'reg_lambda':0.8,

    'colsample_bytree':0.5

}

dtrain = xgb.DMatrix(x_train,train_y)

dtest = xgb.DMatrix(x_test,test_y)

bst = xgb.train(params, dtrain, num_boost_round=2000)

/root/anaconda3/envs/ml/lib/python3.6/site-packages/xgboost/core.py:587: FutureWarning: Series.base is deprecated and will be removed in a future version
  if getattr(data, 'base', None) is not None and \

In [66]:

y_pred_test=bst.predict(dtest)

y_pred_train=bst.predict(dtrain)

print("訓練集rmse:",rmse(train_y,y_pred_train))

print("測試集rmse:",rmse(test_y,y_pred_test))

訓練集rmse: 0.8318620679177371
測試集rmse: 1.3412344636800162

In [68]:

import matplotlib.pyplot as plt

plt.figure(figsize=(20,20),dpi=100)

plt.scatter(test_y,y_pred_test)

plt.xlabel("真實值")

plt.ylabel("預測值")

plt.show()

Stacking融合

In [97]:

#獲取每個子模型的預測結果作爲特徵

train_features=[]

train_features.append(ridge.predict(new_x_train))#將每個模型預測值保存起來

train_features.append(lasso.predict(new_x_train))

# train_features.append(svr.predict(new_x_train))#這個太慢了  不要了

train_features.append(rf.predict(x_train))

train_features.append(tree.predict(x_train))

train_features.append(bst.predict(dtrain))

test_features=[]

test_features.append(ridge.predict(new_x_test))

test_features.append(lasso.predict(new_x_test))

# test_features.append(svr.predict(new_x_test))

test_features.append(rf.predict(x_test))

test_features.append(tree.predict(x_test))

test_features.append(bst.predict(dtest))

 

In [98]:

mx_train=np.vstack(train_features).T

mx_test=np.vstack(test_features).T

mx_train.shape

Out[98]:

(137549, 5)

In [110]:

stack_model=Ridge(fit_intercept=False)

params={

    "alpha":np.logspace(-2,3,20)

}

model=GridSearchCV(stack_model,param_grid=params,cv=5,n_jobs=-1)

model.fit(mx_train,train_y)

model.best_params_

Out[110]:

{'alpha': 0.20691380811147891}

In [120]:

stack_model=Ridge(alpha=0.206,fit_intercept=False)

stack_model.fit(mx_train,train_y)

y_pred=stack_model.predict(mx_test)

y_pred_train=stack_model.predict(mx_train)

print("訓練集rmse:",rmse(train_y,y_pred_train))

print("測試集rmse:",rmse(test_y,y_pred))

訓練集rmse: 0.6824409675644203
測試集rmse: 1.3588850206739824

In [121]:

stack_model.coef_

Out[121]:

array([-0.01476048, -0.01601146,  0.04143987,  0.55925897,  0.43009737])

模型保存

In [ ]:

import pickle

with open("data/model.pkl","wb") as f:

    pickle.dump({

        "vector":vector,

        "pca":pca,

        "sc":trans,

        "ridge":ridge,

        "lasso":lasso,

        "rf":rf,

        "tree":tree,

        "bst":bst,

        "stack":stack_model

    },f)


數據處理

In [1]:

import pandas as pd

In [2]:

train = pd.read_csv("./data/train.csv")

In [3]:

test = pd.read_csv("./data/test.csv")

In [4]:

train.head()

Out[4]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金
0 1 3072 0.128906 2 0.236364 0.008628 東南 NaN 1 1 1 NaN 11.0 118.0 2.0 40.0 0.764167 NaN 5.602716
1 1 3152 0.132812 1 0.381818 0.017046 NaN 1 0 0 NaN 10.0 100.0 4.0 58.0 0.709167 NaN 16.977929
2 1 5575 0.042969 0 0.290909 0.010593 東南 NaN 2 1 2 NaN 12.0 130.0 5.0 37.0 0.572500 NaN 8.998302
3 1 3103 0.085938 2 0.581818 0.019199 NaN 3 2 2 NaN 7.0 90.0 2.0 63.0 0.658333 NaN 5.602716
4 1 5182 0.214844 0 0.545455 0.010427 東北 NaN 2 1 1 NaN 3.0 31.0 NaN NaN NaN NaN 7.300509

In [5]:

test.head()

Out[5]:

  id 時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況
0 1 4 6011 0.382812 1 0.600000 0.007117 3.0 2 1 1 1.0 10.0 5.0 NaN NaN NaN 6.0
1 2 4 1697 0.152344 1 0.472727 0.007448 NaN 2 1 1 NaN 3.0 0.0 NaN NaN NaN NaN
2 3 4 754 0.207031 2 0.709091 0.014068 東南 NaN 3 2 2 NaN 10.0 9.0 4.0 74.0 0.400833 NaN
3 4 4 1285 0.011719 0 0.090909 0.008937 NaN 2 1 1 NaN 6.0 96.0 5.0 17.0 0.384167 NaN
4 5 4 4984 0.035156 1 0.218182 0.008606 東南 NaN 2 1 1 NaN 6.0 61.0 3.0 114.0 0.598333 NaN

In [7]:

train.shape

Out[7]:

(196539, 19)

In [8]:

import seaborn as sns

In [11]:

# 圖形可視化,查看數據分佈

import seaborn as sns

import matplotlib.pyplot as plt

sns.countplot(train.時間)

plt.show()

In [14]:

train1 = train[train.時間 == 1]

train1.shape

Out[14]:

(50843, 19)

In [15]:

train2 = train[train.時間 == 2]

train2.shape

Out[15]:

(72206, 19)

In [16]:

train3 = train[train.時間 == 3]

train3.shape

Out[16]:

(73490, 19)

In [21]:

train2.index

Out[21]:

Int64Index([ 50843,  50844,  50845,  50846,  50847,  50848,  50849,  50850,
             50851,  50852,
            ...
            123039, 123040, 123041, 123042, 123043, 123044, 123045, 123046,
            123047, 123048],
           dtype='int64', length=72206)

In [22]:

train3.index

Out[22]:

Int64Index([123049, 123050, 123051, 123052, 123053, 123054, 123055, 123056,
            123057, 123058,
            ...
            196529, 196530, 196531, 196532, 196533, 196534, 196535, 196536,
            196537, 196538],
           dtype='int64', length=73490)

In [31]:

train2.月租金.values

Out[31]:

array([7.64006791, 4.24448217, 6.62139219, ..., 5.60271647, 7.30050934,
       6.96095076])

In [32]:

plt.figure()

plt.plot(train2.index.values, train2.月租金.values)

plt.show()

In [33]:

plt.figure()

plt.plot(train3.index.values, train3.月租金.values)

plt.show()

In [37]:

train_ = train[:150539]

In [38]:

# 圖形可視化,查看數據分佈

import seaborn as sns

import matplotlib.pyplot as plt

sns.countplot(train_.時間)

plt.show()

In [39]:

plt.figure()

plt.plot(train_.index.values, train_.月租金.values)

plt.show()

In [42]:

train_.index.values

Out[42]:

array([     0,      1,      2, ..., 150536, 150537, 150538])

In [43]:

test_ = train[150539:]

In [44]:

test_.index.values

Out[44]:

array([150539, 150540, 150541, ..., 196536, 196537, 196538])

In [45]:

test_.shape

Out[45]:

(46000, 19)

In [46]:

test_.head()

Out[46]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金
150539 3 3882 0.035156 1 0.436364 0.013075 東南 NaN 3 1 1 NaN 8.0 94.0 4.0 76.0 0.383333 NaN 6.281834
150540 3 6353 0.078125 1 0.436364 0.012248 東南 NaN 3 1 1 NaN 3.0 33.0 3.0 23.0 1.000000 NaN 6.281834
150541 3 1493 0.203125 1 0.381818 0.023006 NaN 4 2 2 NaN 12.0 60.0 5.0 115.0 0.945000 NaN 23.259762
150542 3 1532 0.414062 1 0.600000 0.019695 東南 NaN 3 2 2 NaN 1.0 40.0 NaN NaN NaN NaN 2.886248
150543 3 1251 0.226562 1 0.381818 0.014730 NaN 3 1 1 NaN 12.0 52.0 NaN NaN NaN NaN 10.696095

In [50]:

id = [i for i in range(1, 46001)]

id

test_["id"] = id

In [52]:

test_.head()

Out[52]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金 id
150539 3 3882 0.035156 1 0.436364 0.013075 東南 NaN 3 1 1 NaN 8.0 94.0 4.0 76.0 0.383333 NaN 6.281834 1
150540 3 6353 0.078125 1 0.436364 0.012248 東南 NaN 3 1 1 NaN 3.0 33.0 3.0 23.0 1.000000 NaN 6.281834 2
150541 3 1493 0.203125 1 0.381818 0.023006 NaN 4 2 2 NaN 12.0 60.0 5.0 115.0 0.945000 NaN 23.259762 3
150542 3 1532 0.414062 1 0.600000 0.019695 東南 NaN 3 2 2 NaN 1.0 40.0 NaN NaN NaN NaN 2.886248 4
150543 3 1251 0.226562 1 0.381818 0.014730 NaN 3 1 1 NaN 12.0 52.0 NaN NaN NaN NaN 10.696095 5

In [74]:

train_.to_csv("./train.csv", index=False)

In [54]:

test_.to_csv("./test_result.csv")

In [57]:

test_1 = test_.drop(["月租金"], axis=1)

In [59]:

test_1.head()

Out[59]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 id
150539 3 3882 0.035156 1 0.436364 0.013075 東南 NaN 3 1 1 NaN 8.0 94.0 4.0 76.0 0.383333 NaN 1
150540 3 6353 0.078125 1 0.436364 0.012248 東南 NaN 3 1 1 NaN 3.0 33.0 3.0 23.0 1.000000 NaN 2
150541 3 1493 0.203125 1 0.381818 0.023006 NaN 4 2 2 NaN 12.0 60.0 5.0 115.0 0.945000 NaN 3
150542 3 1532 0.414062 1 0.600000 0.019695 東南 NaN 3 2 2 NaN 1.0 40.0 NaN NaN NaN NaN 4
150543 3 1251 0.226562 1 0.381818 0.014730 NaN 3 1 1 NaN 12.0 52.0 NaN NaN NaN NaN 5

In [60]:

test_1.to_csv("./test.csv")

In [62]:

test = pd.read_csv("./test.csv")

In [63]:

test.head()

Out[63]:

  Unnamed: 0 id 時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況
0 1 1 3 3882 0.035156 1 0.436364 0.013075 東南 NaN 3 1 1 NaN 8.0 94.0 4.0 76.0 0.383333 NaN
1 2 2 3 6353 0.078125 1 0.436364 0.012248 東南 NaN 3 1 1 NaN 3.0 33.0 3.0 23.0 1.000000 NaN
2 3 3 3 1493 0.203125 1 0.381818 0.023006 NaN 4 2 2 NaN 12.0 60.0 5.0 115.0 0.945000 NaN
3 150542 4 3 1532 0.414062 1 0.600000 0.019695 東南 NaN 3 2 2 NaN 1.0 40.0 NaN NaN NaN NaN
4 150543 5 3 1251 0.226562 1 0.381818 0.014730 NaN 3 1 1 NaN 12.0 52.0 NaN NaN NaN NaN

In [65]:

test = test.drop(["Unnamed: 0"], axis=1)

In [68]:

test.to_csv("./test.csv", index=False)

In [72]:

test = pd.read_csv("./test.csv")

test.head()

Out[72]:

  id 時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況
0 1 3 3882 0.035156 1 0.436364 0.013075 東南 NaN 3 1 1 NaN 8.0 94.0 4.0 76.0 0.383333 NaN
1 2 3 6353 0.078125 1 0.436364 0.012248 東南 NaN 3 1 1 NaN 3.0 33.0 3.0 23.0 1.000000 NaN
2 3 3 1493 0.203125 1 0.381818 0.023006 NaN 4 2 2 NaN 12.0 60.0 5.0 115.0 0.945000 NaN
3 4 3 1532 0.414062 1 0.600000 0.019695 東南 NaN 3 2 2 NaN 1.0 40.0 NaN NaN NaN NaN
4 5 3 1251 0.226562 1 0.381818 0.014730 NaN 3 1 1 NaN 12.0 52.0 NaN NaN NaN NaN

In [73]:

test.shape

Out[73]:

(46000, 19)

In [79]:

train = pd.read_csv("./train.csv")

train.head()

Out[79]:

  時間 小區名 小區房屋出租數量 樓層 總樓層 房屋面積 房屋朝向 居住狀態 臥室數量 廳的數量 衛的數量 出租方式 位置 地鐵線路 地鐵站點 距離 裝修情況 月租金
0 1 3072 0.128906 2 0.236364 0.008628 東南 NaN 1 1 1 NaN 11.0 118.0 2.0 40.0 0.764167 NaN 5.602716
1 1 3152 0.132812 1 0.381818 0.017046 NaN 1 0 0 NaN 10.0 100.0 4.0 58.0 0.709167 NaN 16.977929
2 1 5575 0.042969 0 0.290909 0.010593 東南 NaN 2 1 2 NaN 12.0 130.0 5.0 37.0 0.572500 NaN 8.998302
3 1 3103 0.085938 2 0.581818 0.019199 NaN 3 2 2 NaN 7.0 90.0 2.0 63.0 0.658333 NaN 5.602716
4 1 5182 0.214844 0 0.545455 0.010427 東北 NaN 2 1 1 NaN 3.0 31.0 NaN NaN NaN NaN 7.300509

In [80]:

train.shape

Out[80]:

(150539, 19)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章