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]:

时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金
0130720.12890620.2363640.008628东南NaN111NaN11.0118.02.040.00.764167NaN5.602716
1131520.13281210.3818180.017046NaN100NaN10.0100.04.058.00.709167NaN16.977929
2155750.04296900.2909090.010593东南NaN212NaN12.0130.05.037.00.572500NaN8.998302
3131030.08593820.5818180.019199NaN322NaN7.090.02.063.00.658333NaN5.602716
4151820.21484400.5454550.010427东北NaN211NaN3.031.0NaNNaNNaNNaN7.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]:

时间小区名小区房屋出租数量楼层总楼层房屋面积居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金
count196539.000000196539.000000195538.000000196539.000000196539.000000196539.00000020138.000000196539.000000196539.000000196539.00000024230.000000196508.000000196508.00000091778.00000091778.00000091778.00000018492.000000196539.000000
mean2.1152293224.1165620.1241510.9554490.4087110.0131392.7251962.2366351.2996251.2238180.9002897.90513967.9459823.28485057.4937350.5512023.5892287.949313
std0.7869802023.0737260.1332990.8515110.1831000.0081040.6677630.8969610.6131690.4872340.2996214.02569643.5223941.47714735.1914140.2472681.9969126.310609
min1.0000000.0000000.0078120.0000000.0000000.0000001.0000000.0000000.0000000.0000000.0000000.0000000.0000001.0000001.0000000.0016671.0000000.000000
25%1.0000001388.0000000.0390620.0000000.2909090.0092683.0000002.0000001.0000001.0000001.0000004.00000033.0000002.00000023.0000000.3566672.0000004.923599
50%2.0000003086.0000000.0820311.0000000.4181820.0129103.0000002.0000001.0000001.0000001.0000009.00000061.0000004.00000059.0000000.5541672.0000006.621392
75%3.0000005199.0000000.1601562.0000000.5636360.0148963.0000003.0000002.0000001.0000001.00000011.000000103.0000005.00000087.0000000.7458336.0000008.998302
max3.0000006627.0000001.0000002.0000001.0000001.0000003.00000011.0000008.0000008.0000001.00000014.000000152.0000005.000000119.0000001.0000006.000000100.000000

数据探索

基本信息

In [6]:

train.head()

Out[6]:

时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金
0130720.12890620.2363640.008628东南NaN111NaN11.0118.02.040.00.764167NaN5.602716
1131520.13281210.3818180.017046NaN100NaN10.0100.04.058.00.709167NaN16.977929
2155750.04296900.2909090.010593东南NaN212NaN12.0130.05.037.00.572500NaN8.998302
3131030.08593820.5818180.019199NaN322NaN7.090.02.063.00.658333NaN5.602716
4151820.21484400.5454550.010427东北NaN211NaN3.031.0NaNNaNNaNNaN7.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]:

小区名位置
105800284102.0
105988284102.0
105228284102.0
105076284102.0
105074284102.0
.........
131530662786.0
1586216627136.0
56569662786.0
39956662786.0
1611626627136.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.01
1.02
2.01
3.02
4.01
......
146.02
147.02
148.01
150.01
151.01

120 rows × 1 columns

In [45]:

#每个位置的站点数   也可以作为新特征加入

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

b

Out[45]:

地铁站点
位置
0.01
1.03
2.01
3.04
4.01
......
146.03
147.02
148.01
150.04
151.01

120 rows × 1 columns

In [46]:

#两者的相关性

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

al.corr()

Out[46]:

地铁线路地铁站点
地铁线路1.0000000.685211
地铁站点0.6852111.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.04
2.01
3.05
4.01
5.05
......
115.03
116.02
117.01
118.02
119.04

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
1513166260.05078100.5818180.009070NaN11...1.010.00.965000NaN5.942275NaNNaNNaNNaN
6622166260.05078120.5454550.022840NaN33...5.016.00.974167NaN4.244482NaNNaNNaNNaN
10951166260.05078100.5818180.009103西NaN11...1.010.00.965000NaN5.602716西NaNNaNNaNNaN
12327166260.05078110.5454550.014234东南NaN31...5.016.00.974167NaN6.960951东南NaNNaNNaNNaN
14738166260.05078110.5454550.008039NaN11...5.016.00.974167NaN5.602716NaNNaNNaNNaN
..................................................................
177641366260.08593800.5454550.014068东南1.021...5.016.00.9741672.07.300509东南NaNNaNNaNNaN
177725366260.08593810.5454550.014234东南NaN31...5.016.00.974167NaN6.960951东南NaNNaNNaNNaN
191611366260.08593810.5454550.0147303.032...5.016.00.9741676.08.998302NaNNaNNaNNaN
194534366260.08593820.5818180.013846东南3.021...1.010.00.9650002.08.319185东南NaNNaNNaNNaN
195236366260.08593800.5818180.012744东南NaN21...1.010.00.965000NaN5.602716东南NaNNaNNaNNaN

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]:

地铁站点
小区名
6024
17284
326914

看一下小区名过多的问题

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]:

时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金
0130720.12890620.2363640.008628东南NaN111NaN11.0118.02.040.00.764167NaN5.602716
1131520.13281210.3818180.017046NaN100NaN10.0100.04.058.00.709167NaN16.977929
2155750.04296900.2909090.010593东南NaN212NaN12.0130.05.037.00.572500NaN8.998302
3131030.08593820.5818180.019199NaN322NaN7.090.02.063.00.658333NaN5.602716
4151820.21484400.5454550.010427东北NaN211NaN3.031.0NaNNaNNaNNaN7.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]:

小区名地铁线路
10733703.0
362013.0
4128625.0
82114NaN
559625NaN
.........
453476625NaN
662266265.0
151366261.0
17276627NaN
254266271.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]:

地铁站点距离
小区名位置
059.057.00.478333
159.057.00.563333
240.033.00.971667
1124.0103.00.914167
1228.069.00.633333
............
662541.088.00.931667
662686.016.00.974167
136.016.00.974167
662786.010.00.985000
136.010.00.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]:

地铁站点距离
小区名
057.00.478333
157.00.563333
233.00.971667
11103.00.914167
1269.00.633333
.........
662225.00.245000
6623119.00.410000
662588.00.931667
662616.00.974167
662710.00.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
0130720.12890620.2363640.008628东南0.0111-1.011.0118.02.040.00.764167-1.05.6027161.887481
1131520.13281210.3818180.0170460.0100-1.010.0100.04.058.00.709167-1.016.9779292.889145
2155750.04296900.2909090.010593东南0.0212-1.012.0130.05.037.00.572500-1.08.9983022.302415
3131030.08593820.5818180.0191990.0322-1.07.090.02.063.00.658333-1.05.6027161.887481
4151820.21484400.5454550.010427东北0.0211-1.03.031.00.00.02.000000-1.07.3005092.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新朝向
0130720.12890620.2363640.008628东南0.011...-1.011.0118.02.040.00.764167-1.05.6027161.887481东南
1131520.13281210.3818180.0170460.010...-1.010.0100.04.058.00.709167-1.016.9779292.889145
2155750.04296900.2909090.010593东南0.021...-1.012.0130.05.037.00.572500-1.08.9983022.302415东南
3131030.08593820.5818180.0191990.032...-1.07.090.02.063.00.658333-1.05.6027161.887481
4151820.21484400.5454550.010427东北0.021...-1.03.031.00.00.02.000000-1.07.3005092.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时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量...新朝向房+卫+厅房/总卫/总厅/总卧室面积楼层比户型有地铁聚类特征
01460110.38281210.6000000.0071173.02...40.5000000.2500000.2500000.0035580.62500021112
12416970.15234410.4727270.0074480.02...40.5000000.2500000.2500000.0037240.67901221112
2347540.20703120.7090910.014068东南0.03...东南70.4285710.2857140.2857140.0046891.17021332212
34412850.01171900.0909090.0089370.02...40.5000000.2500000.2500000.0044690.00000021112
45449840.03515610.2181820.008606东南0.02...东南40.5000000.2500000.2500000.0043030.82089621112
..................................................................
9596452390.43359400.5454550.0062020.01...20.5000000.5000000.0000000.0062020.00000010112
9697410270.04687500.7272730.0077790.02...40.5000000.2500000.2500000.0038890.00000021112
979843000.14062520.4545450.013744西0.02...西50.4000000.2000000.4000000.0068721.37500022112
9899410210.26953100.5818180.013860东南0.03...东南70.4285710.2857140.2857140.0046200.00000032212
99100426440.30078100.3090910.014896东南0.03...东南60.5000000.1666670.3333330.0049650.00000032112

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]:

时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金
0130720.12890620.2363640.008628东南NaN111NaN11.0118.02.040.00.764167NaN5.602716
1131520.13281210.3818180.017046NaN100NaN10.0100.04.058.00.709167NaN16.977929
2155750.04296900.2909090.010593东南NaN212NaN12.0130.05.037.00.572500NaN8.998302
3131030.08593820.5818180.019199NaN322NaN7.090.02.063.00.658333NaN5.602716
4151820.21484400.5454550.010427东北NaN211NaN3.031.0NaNNaNNaNNaN7.300509

In [5]:

test.head()

Out[5]:

id时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况
01460110.38281210.6000000.0071173.02111.010.05.0NaNNaNNaN6.0
12416970.15234410.4727270.007448NaN211NaN3.00.0NaNNaNNaNNaN
2347540.20703120.7090910.014068东南NaN322NaN10.09.04.074.00.400833NaN
34412850.01171900.0909090.008937NaN211NaN6.096.05.017.00.384167NaN
45449840.03515610.2181820.008606东南NaN211NaN6.061.03.0114.00.598333NaN

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]:

时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金
150539338820.03515610.4363640.013075东南NaN311NaN8.094.04.076.00.383333NaN6.281834
150540363530.07812510.4363640.012248东南NaN311NaN3.033.03.023.01.000000NaN6.281834
150541314930.20312510.3818180.023006NaN422NaN12.060.05.0115.00.945000NaN23.259762
150542315320.41406210.6000000.019695东南NaN322NaN1.040.0NaNNaNNaNNaN2.886248
150543312510.22656210.3818180.014730NaN311NaN12.052.0NaNNaNNaNNaN10.696095

In [50]:

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

id

test_["id"] = id

In [52]:

test_.head()

Out[52]:

时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金id
150539338820.03515610.4363640.013075东南NaN311NaN8.094.04.076.00.383333NaN6.2818341
150540363530.07812510.4363640.012248东南NaN311NaN3.033.03.023.01.000000NaN6.2818342
150541314930.20312510.3818180.023006NaN422NaN12.060.05.0115.00.945000NaN23.2597623
150542315320.41406210.6000000.019695东南NaN322NaN1.040.0NaNNaNNaNNaN2.8862484
150543312510.22656210.3818180.014730NaN311NaN12.052.0NaNNaNNaNNaN10.6960955

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
150539338820.03515610.4363640.013075东南NaN311NaN8.094.04.076.00.383333NaN1
150540363530.07812510.4363640.012248东南NaN311NaN3.033.03.023.01.000000NaN2
150541314930.20312510.3818180.023006NaN422NaN12.060.05.0115.00.945000NaN3
150542315320.41406210.6000000.019695东南NaN322NaN1.040.0NaNNaNNaNNaN4
150543312510.22656210.3818180.014730NaN311NaN12.052.0NaNNaNNaNNaN5

In [60]:

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

In [62]:

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

In [63]:

test.head()

Out[63]:

Unnamed: 0id时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况
011338820.03515610.4363640.013075东南NaN311NaN8.094.04.076.00.383333NaN
122363530.07812510.4363640.012248东南NaN311NaN3.033.03.023.01.000000NaN
233314930.20312510.3818180.023006NaN422NaN12.060.05.0115.00.945000NaN
31505424315320.41406210.6000000.019695东南NaN322NaN1.040.0NaNNaNNaNNaN
41505435312510.22656210.3818180.014730NaN311NaN12.052.0NaNNaNNaNNaN

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时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况
01338820.03515610.4363640.013075东南NaN311NaN8.094.04.076.00.383333NaN
12363530.07812510.4363640.012248东南NaN311NaN3.033.03.023.01.000000NaN
23314930.20312510.3818180.023006NaN422NaN12.060.05.0115.00.945000NaN
34315320.41406210.6000000.019695东南NaN322NaN1.040.0NaNNaNNaNNaN
45312510.22656210.3818180.014730NaN311NaN12.052.0NaNNaNNaNNaN

In [73]:

test.shape

Out[73]:

(46000, 19)

In [79]:

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

train.head()

Out[79]:

时间小区名小区房屋出租数量楼层总楼层房屋面积房屋朝向居住状态卧室数量厅的数量卫的数量出租方式位置地铁线路地铁站点距离装修情况月租金
0130720.12890620.2363640.008628东南NaN111NaN11.0118.02.040.00.764167NaN5.602716
1131520.13281210.3818180.017046NaN100NaN10.0100.04.058.00.709167NaN16.977929
2155750.04296900.2909090.010593东南NaN212NaN12.0130.05.037.00.572500NaN8.998302
3131030.08593820.5818180.019199NaN322NaN7.090.02.063.00.658333NaN5.602716
4151820.21484400.5454550.010427东北NaN211NaN3.031.0NaNNaNNaNNaN7.300509

In [80]:

train.shape

Out[80]:

(150539, 19)

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

あずにゃん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值