利用线性回归模型进行kaggle房价预测

 

最近刚学线性回归的一些基础知识,就想利用kaggle中的一个入门级比赛 House Prices: Advanced Regression Techniques进行一下巩固,发现建模之前的数据清洗与特征选择非常重要。

1. 数据清洗

1.1 导入数据   

将train.csv与test.csv文件导入,放到一起直接预处理,处理完毕后再分开。

def load_file(path):    #导入数据
    f = open(path)
    train_set = pd.read_csv(f, index_col=0)
    return train_set

train_path = "G:\practice.pycharm\house_price_predict\\train.csv"
train_set = load_file(train_path)
test_path = "G:\practice.pycharm\house_price_predict\\all\\test.csv"
all_set = pd.concat([train_set,load_file(train_path)])

可以利用shape函数得到train与all的大小,便于处理后分割

print(train_set.shape)
(1460, 80)
print(all_set.shape)
(2919, 80)

1.2 数据预处理

1.2.1 数据去重

使用drop_duplicates函数去掉重复值:

DataFrame.drop_duplicates(subset=None, keep='first', inplace=False)

这里因为我们需要对所有列进行重复行删除,保留第一个值即可,这里直接使用默认参数。

all_set.drop_duplicates(keep='first',inplace=True)

shape查看发现没有重复值:

(2919, 80)

1.2.2 缺失值处理

这里主要参考Comprehensive data exploration with Python预处理数据的方法。首先拿到各列的缺失值:

na_count = all_set.shape[0]-all_set.count().sort_values()
na_rate = na_count/all_set.shape[0]
na_det = pd.concat([na_count,na_rate],axis=1,keys=['nan count','nan ratio'])
print(na_det.head(36))
              nan count  nan ratio
PoolQC             2909   0.996574
MiscFeature        2814   0.964029
Alley              2721   0.932169
Fence              2348   0.804385
SalePrice          1459   0.499829
FireplaceQu        1420   0.486468
LotFrontage         486   0.166495
GarageYrBlt         159   0.054471
GarageFinish        159   0.054471
GarageCond          159   0.054471
GarageQual          159   0.054471
GarageType          157   0.053786
BsmtCond             82   0.028092
BsmtExposure         82   0.028092
BsmtQual             81   0.027749
BsmtFinType2         80   0.027407
BsmtFinType1         79   0.027064
MasVnrType           24   0.008222
MasVnrArea           23   0.007879
MSZoning              4   0.001370
Utilities             2   0.000685
BsmtFullBath          2   0.000685
BsmtHalfBath          2   0.000685
Functional            2   0.000685
SaleType              1   0.000343
KitchenQual           1   0.000343
TotalBsmtSF           1   0.000343
BsmtFinSF1            1   0.000343
Electrical            1   0.000343
GarageCars            1   0.000343
GarageArea            1   0.000343
BsmtFinSF2            1   0.000343
Exterior2nd           1   0.000343
Exterior1st           1   0.000343
BsmtUnfSF             1   0.000343
RoofMatl              0   0.000000

一共发现有35个包含缺失值的列,一般的,当一列数据缺失值超过15%时,就应该删除该列,注意到SalePrice列为我们要预测的列,所有除SalePice外其余6列全部予以删除。

all_set.drop('PoolQC',axis = 1,inplace = True)
all_set.drop('MiscFeature', axis=1, inplace=True)
all_set.drop('Alley', axis=1, inplace=True)
all_set.drop('Fence', axis=1, inplace=True)
all_set.drop('FireplaceQu', axis=1, inplace=True)
all_set.drop('LotFrontage', axis=1, inplace=True)

而后面GarageX的项,应该是一些列强相关的项,因为有GarageCars这个特征表征,也可以删去。

all_set.drop('GarageYrBlt', axis=1, inplace=True)
all_set.drop('GarageFinish', axis=1, inplace=True)
all_set.drop('GarageCond', axis=1, inplace=True)
all_set.drop('GarageQual', axis=1, inplace=True)
all_set.drop('GarageType', axis=1, inplace=True)

对于BsmtX同样删除。

all_set.drop('BsmtCond', axis=1, inplace=True)
all_set.drop('BsmtExposure', axis=1, inplace=True)
all_set.drop('BsmtQual', axis=1, inplace=True)
all_set.drop('BsmtFinType2', axis=1, inplace=True)
all_set.drop('BsmtFinType1', axis=1, inplace=True)

对于MasVnr也同样删除。

all_set.drop('MasVnrType', axis=1, inplace=True)
all_set.drop('MasVnrArea', axis=1, inplace=True)

查看另外18列含有缺失值的属性。

              nan count  nan ratio    dtype
SalePrice          1459   0.499829  float64
MSZoning              4   0.001370   object
Utilities             2   0.000685   object
BsmtFullBath          2   0.000685  float64
BsmtHalfBath          2   0.000685  float64
Functional            2   0.000685   object
Exterior1st           1   0.000343   object
GarageCars            1   0.000343  float64
Exterior2nd           1   0.000343   object
SaleType              1   0.000343   object
Electrical            1   0.000343   object
GarageArea            1   0.000343  float64
BsmtUnfSF             1   0.000343  float64
BsmtFinSF2            1   0.000343  float64
BsmtFinSF1            1   0.000343  float64
TotalBsmtSF           1   0.000343  float64
KitchenQual           1   0.000343   object
Neighborhood          0   0.000000   object

发现这些列中有的是object属性,有的是float属性,分别进行处理,对于object属性的列,使用出现频率最高的值进行代替,对于float属性的列,一般为“无”,所以不填,故使用0填充。

all_set['MSZoning'].fillna('C (all)',inplace=True)
all_set['Utilities'].fillna('AllPub',inplace=True)
all_set['Functional'].fillna('Typ',inplace=True)
all_set['Exterior1st'].fillna('VinylSd',inplace=True)
all_set['Exterior2nd'].fillna('VinylSd',inplace=True)
all_set['SaleType'].fillna('WD',inplace=True)
all_set['Electrical'].fillna('SBrkr',inplace=True)
all_set['KitchenQual'].fillna('TA',inplace=True)
all_set['BsmtFullBath'].fillna(0., inplace=True)
all_set['BsmtHalfBath'].fillna(0., inplace=True)
all_set['BsmtUnfSF'].fillna(0., inplace=True)
all_set['GarageArea'].fillna(0., inplace=True)
all_set['GarageCars'].fillna(0., inplace=True)
all_set['TotalBsmtSF'].fillna(0., inplace=True)
all_set['BsmtFinSF1'].fillna(0., inplace=True)
all_set['BsmtFinSF2'].fillna(0., inplace=True)

再次对缺失值进行检查,发现除我们要预测的SalePrice列外没有缺失值,缺失值处理完毕。

              nan count  nan ratio    dtype
SalePrice          1459   0.499829  float64
1stFlrSF              0   0.000000    int64
LandSlope             0   0.000000   object
LotArea               0   0.000000    int64
LotConfig             0   0.000000   object
LotShape              0   0.000000   object
LowQualFinSF          0   0.000000    int64
MSSubClass            0   0.000000    int64
MSZoning              0   0.000000   object
MiscVal               0   0.000000    int64

1.2.3 定性量哑编码

对数据集进行onehot哑编码,将定性量转化为哑编码方式,便于后续训练模型,将原数据集中的SalePrice列删除。

data_set.drop('SalePrice',axis = 1,inplace = True)
data_set_num = pd.DataFrame()
data_set_ob = pd.DataFrame()
for i in data_set.columns.values:
    if data_set[i].dtypes == 'object':
        data_set_ob = pd.concat([data_set_ob,data_set[i]],axis=1)
    else:
        data_set_num = pd.concat([data_set_num,data_set[i]],axis=1)
data_set_ob = pd.get_dummies(data_set)

得到哑编码后的数据集,查看shape:

(2918, 221)

1.2.4 连续值标准化

为提高收敛速度,对数据集标准化,对价格取对数。选择sklearn中的StandardScaler进行标准化,价格采用log1p函数。

num_col = data_set_num.columns
data_set_num = pd.DataFrame(preprocessing.StandardScaler().fit_transform(data_set_num),columns=num_col)
data_y = np.log1p(data_y)

查看对数化之前与之后的分布:

对数化后更加符合正态分布。

 

1.2.5 离群值删除

首先拿到所有单列对于价格的散点图:

发现GrLivArea明显有两个偏离点,找到删除。

data_x.drop(data_x.index[[1298,523]],inplace = True)
data_y.drop(data_y.index[[1298,523]],inplace = True)

离群点删除完毕。

2. 数据建模

2.1 数据分割

将数据集按7:3切割为训练集和测试集。

x_train,x_test,y_train,y_test = cross_validation.train_test_split(data_x,data_y,test_size=0.3)

2.2 线性回归模型

利用sklearn中的线性模型对训练集进行建模。

model = linear_model.LinearRegression()
model.fit(x_train,y_train)

使用多元线性回归拟合数据,查看截距与系数:

系数: [-1.85543669e+07 -8.04763021e+06  8.74505546e-02 -8.41983585e-02
  2.60674291e+10  7.04799731e+09  8.07989649e-02 -2.37079067e-02
  1.07890706e+10  9.29348469e-02  1.55423164e-01  8.64651203e-02
  1.88232660e-01  1.80189371e-01  2.06861132e+07  3.56459618e-02
 -8.52451324e-02  7.75563359e-01 -4.14657567e+06 -7.68175125e-02
 -5.87408125e-01  1.83105469e-03  1.02868974e-02  4.62743044e-01
  6.69234022e-01  1.10272944e-01  1.84955835e-01  1.72290325e-01
 -2.82197009e+10  3.00650597e-02  4.03986931e-01  7.40909576e-02
 -2.11348534e-02 -2.70690585e+10 -2.70690585e+10 -2.70690585e+10
 -2.70690585e+10 -2.70690585e+10  1.53694722e+10  1.53694722e+10
  5.55073126e+08  5.55073126e+08  5.55073126e+08  5.55073126e+08
  5.55073126e+08  5.55073126e+08  5.55073126e+08  5.55073126e+08
  5.55073126e+08 -1.71070683e+10 -1.71070683e+10 -1.71070683e+10
 -2.20707567e+10 -1.71070683e+10 -1.71070683e+10 -1.71070683e+10
 -1.71070683e+10  3.77141831e+10  3.77141831e+10  3.77141831e+10
 -3.58089763e+10  3.77141831e+10  6.11169150e+09  6.11169150e+09
  6.11169150e+09  6.11169150e+09  6.11169150e+09 -6.32708343e+08
 -6.32708343e+08 -6.32708343e+08 -6.32708343e+08 -9.89338552e+09
 -9.89338552e+09 -9.89338552e+09 -9.89338552e+09 -1.68585564e+10
 -9.89338552e+09 -9.89338552e+09 -9.89338552e+09 -9.89338552e+09
 -9.89338552e+09 -9.89338552e+09 -9.89338552e+09 -9.89338552e+09
 -9.89338552e+09 -9.89338552e+09  1.43397977e+10  1.43397977e+10
  1.43397977e+10  1.43397977e+10  2.13049686e+10  1.43397977e+10
  1.43397977e+10  1.43397977e+10  1.43397977e+10  3.21889821e+10
  1.43397977e+10  1.43397977e+10  1.43397977e+10  1.43397977e+10
  1.43397977e+10  1.43397977e+10 -3.28284039e+09 -3.28284039e+09
 -3.28284039e+09 -3.28284039e+09 -3.28284039e+09 -3.28284039e+09
  1.02802487e+09  1.02802487e+09  1.02802487e+09  1.02802487e+09
  1.02802487e+09 -1.73231695e+09  1.02802487e+09  1.65177921e+09
  1.65177921e+09  1.65177921e+09  1.65177921e+09  1.65177921e+09
  1.65177921e+09 -5.89256168e+10 -5.89256168e+10 -5.89256168e+10
  2.93173824e+09 -5.89256168e+10 -2.05874740e+10 -2.05874740e+10
 -2.05874740e+10 -2.05874740e+10 -2.05874740e+10 -2.05874740e+10
 -2.05874740e+10 -2.05874740e+10 -1.88074328e+10 -1.88074328e+10
 -1.88074328e+10 -1.88074328e+10 -8.77449366e+09 -8.77449366e+09
 -8.77449366e+09 -8.77449366e+09  3.12362451e+10  3.12362451e+10
  3.12362451e+10 -6.76533101e+09 -6.76533101e+09 -6.76533101e+09
 -6.76533101e+09 -6.76533101e+09  1.74194848e+10  1.74194848e+10
  1.74194848e+10  1.74194848e+10 -2.32040189e+10 -2.32040189e+10
 -2.32040189e+10 -2.32040189e+10 -2.32040189e+10 -9.22089572e+09
 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09
 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09
 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09
 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09
 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09
 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09 -9.22089572e+09
  1.05481999e+10  1.05481999e+10  1.05481999e+10  2.45233811e+08
  2.45233811e+08  2.45233811e+08  2.45233811e+08  2.45233811e+08
  2.45233811e+08  2.45233811e+08  2.45233811e+08 -1.65389315e+08
 -1.65389315e+08 -1.65389315e+08 -1.65389315e+08 -1.65389315e+08
 -1.65389315e+08 -4.98004278e+08 -4.98004278e+08 -4.98004278e+08
 -4.98004278e+08 -4.98004278e+08 -4.98004278e+08 -1.40919590e+10
 -1.40919590e+10 -1.40919590e+10 -1.40919590e+10 -1.40919590e+10
 -1.40919590e+10 -1.40919590e+10 -1.40919590e+10 -1.40919590e+10
 -2.06193399e+09 -2.06193399e+09 -8.50851018e+08 -8.50851018e+08]
截距: 85719276156.30911

3. 模型评估

3.1 可视化

将预测值与目标值放入一张图进行比较。

y_pre = model.predict(x_test)
plt.scatter(y_pre,y_test,marker='o')
plt.scatter(y_test,y_test)
plt.show()

拟合度看起来还行, 看一下方差的大小。

print(metrics.mean_squared_error(y_test,y_pre))
0.015132547556096164

3.2  模型调整

3.2.1 正则化参数

在线性回归模型中加入正则化项,使用sklearn中的Ridge建立具有正则化项的线性回归模型。

model = linear_model.Ridge(alpha=i)
model.fit(x_train,y_train)

画出正则化项随偏差的变化趋势。

可见aplha取1是比较合理的,此时Jcv(红色曲线)接近最低值,Jtrain值也比较低。

  3.2.2 样本分割比例

将误差根据训练样本大小画出曲线。

样本分割比例的修改对误差的影响不大(一般取6:2:2)。

3.2.3 迭代次数

迭代次数无需调整。

3.2.4 可视化

将预测值与目标值重新作图,得到:

可见效果还不错,可以输出提交了。

4. 总结

这是我第一次做kaggle比赛,也是从0开始,从数据清洗到建模到调整,全部按照自己的主观想法来做,所以会比较随意,后续也会逐渐再改进。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值