房价一直是人们热议的话题。毕竟,很多人一辈子都在为之奋斗。房地产泡沫有多大?今天我们抛开泡沫,回归到房子最本质的内容,分析影响房价的因素有哪些?1、导入数据importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltimportseabornassnimportmissingnoasmsno%matplotlibinlinetrain=pd.read_csv('train.csv',index_col=0)#导入训练集test=pd.read_csv('test.csv',index_col=0)#导入测试集train。head(3)print('train训练集中缺失数据分布')msno.matrix(train)print('test测试集中缺失数据分布')msno.matrix(test)可以看到缺失数据可视化上面可以看出部分特征的数据缺失非常严重。接下来,我们将计算缺失特征的数量。2.目标Y值分析##拆分Y和X数据y=train['SalePrice']#看y的值分布prices=pd.DataFrame({'price':y,'log(price+1)':np.log1p(y)})prices.hist()观察目标变量y的分布和取对数后的分布。取对数后趋于符合正态分布,所以我们对y进行对数变换。y=np.log1p(y)#+1的目的是防止对数变换后的值没有意义3.合并数据缺失处理#合并训练特征和测试集all_df=pd.concat((X,test),axis=0)print('all_df缺失数据图')msno.matrix(all_df)#定义缺失统计函数defshow_missing(feature):missing=feature.columns[feature.isnull().any()].tolist()returnmissingprint('Missingdatastatisticsformissingfeatures:')all_df[show_missing(all_df)].isnull().sum()#先处理数值型数据#一一看分布fig,axs=plt.subplots(3,2,figsize=(16,9))all_df['BsmtFinSF1'].hist(ax=axs[0,0])#populationall_df['BsmtFinSF2'].hist(ax=axs[0,1])#publicNumberall_df['BsmtUnfSF'].hist(ax=axs[1,0])#中位数all_df['TotalBsmtSF'].hist(ax=axs[1,1])#均值填充all_df['BsmtFullBath'].hist(ax=axs[2,0])#modenumberall_df['BsmtHalfBath'].hist(ax=axs[2,1])#moderatenumber#lotfrontagefillwithmean_lotfrontage=all_df.LotFrontage.mean()all_df.LotFrontage.hist()print('用均值填充:')cat_input(all_df,'LotFrontage',mean_lotfrontage)cat_input(all_df,'BsmtFinSF1',0.0)cat_input(all_df,'BsmtFinSF2',0.0)cat_input(all_df,'BsmtFullBath',0.0)cat_input(all_df,'BsmtHalfBath',0.0)cat_input(all_df,'BsmtUnfSF',467.00)cat_input(all_df,'TotalBsmtSF',1051.78)#在处理字符类型的时候,也一一看分布fig,axs=plt.subplots(4,2,figsize=(16,9))all_df['MSZoning'].hist(ax=axs[0,0])#多次填充all_df['Utilities'].hist(ax=axs[0,1])#多次all_df['Exterior1st'].hist(ax=axs[1,0])#MultipleNumberall_df['Exterior2nd'].hist(ax=axs[1,1])#模型填充all_df['KitchenQual'].hist(ax=axs[2,0])#Modelall_df['Functional'].hist(ax=axs[2,1])#moderateall_df['SaleType'].hist(ax=axs[3,0])#moderatecat_input(all_df,'MSZoning','RL')cat_input(all_df,'Utilities','AllPub')cat_input(all_df,'Exterior1st','VinylSd')cat_input(all_df,'Exterior2nd','VinylSd')cat_input(all_df,'KitchenQual','TA')cat_input(all_df,'Functional','Typ')cat_input(all_df,'SaleType','WD')#再看看缺失的分布msno.matrix(all_df)binggo,数据干净!让我们开始处理特征。经过上面稍微复杂的处理,数据集中所有缺失的数据都处理完了,接下来的工作就可以开始了!缺失处理小结:本文使用的数据集中存在大量缺失数据。缺失的数据包括数字和字符类型。主要有两个处理原则:1.根据数据分布直方图的绘制,观察数据分布的状态,以适当的方式填充缺失的数据;2.很重要的特征描述,仔细阅读,根据特征描述填写即可解决大部分问题4.特征处理让我们重新仔细审视数据。有什么问题吗?仔细观察发现MSSubClass特征其实是分类特征,只是数据显示是int类型,需要改成str。#观察特征属性,发现MSSubClass是分类特征,但是给的数据是数值类型,需要转换all_df['MSSubClass']=all_df['MSSubClass'].astype(str)#转换分类变量转化为数值型变量all_df=pd.get_dummies(all_df)print('分类变量转换完成后有{}行{}列'.format(*all_df.shape))分类变量转换完成后,有2919行316列#标准化处理numeric_cols=all_df。columns[all_df.dtypes!='uint8']#x-mean(x)/std(x)numeric_mean=all_df.loc[:,numeric_cols].mean()numeric_std=all_df.loc[:,numeric_cols].std()all_df.loc[:,numeric_cols]=(all_df.loc[:,numeric_cols]-numeric_mean)/numeric_std并将数据拆分为训练集和测试集train_df=all_df.ix[0:1460]#trainingsettest_df=all_df.ix[1461:]#测试集5、构建基准模型fromsklearnimportcross_validationfromsklearnimportlinear_modelfromsklearn.learning_curveimportlearning_curvefromsklearn.metricsimportexplained_variance_scorefromsklearn.grid_searchimportGridSearchCVfromsklearn.model_selectionimportcross_val_scorefromsklearn.ensembleimportRandomForestRegressory=y.values#转换成array数组X=train_df.values#转换成array数组cv=cross_validation.ShuffleSplit(len(X),n_iter=3,test_size=0.2)print('岭回归交叉验证结果:')fortrain_index,test_indexincv:ridge=linear_model.Ridge(alpha=1).fit(X,y)print('train_score:{0:.3f},test_score:{1:.3f}\n'.format(ridge.score(X[train_index],y[train_index]),ridge.score(X[test_index],y[test_index])))print('随机森林交叉验证结果:')fortrain_index,test_indexincv:rf=RandomForestRegressor()。fit(X,y)print('train_score:{0:.3f},test_score:{1:.3f}\n'.format(rf.score(X[train_index],y[train_index]),rf.score(X[test_index],y[test_index])))哇!好意外,这两个模型的结果都不错,但是随机森林的结果好像更好,我们来看看学习曲线。我们使用没有调参的默认参数,得到的两个benchmark模型都存在过拟合现象。接下来我们开始调整参数,希望能改善模型的过拟合现象。6.参数调优岭回归正则项比例因子alpha调整alphas=[0.01,0.1,1,10,20,50,100,300]test_scores=[]foralpinalphas:clf=linear_model.Ridge(alp)test_score=-cross_val_score(clf,X,y,cv=10,scoring='neg_mean_squared_error')test_scores.append(np.mean(test_score))importmatplotlib.pyplotasplt%matplotlibinlineplt.plot(alphas,test_scores)plt.title('alphavstest_score')alpha10-20左右随机具有最小均方误差的森林参数用于优化随机森林算法。本文主要调整三个参数:maxfeatures,maxdepth,n_estimators#随机森林的深度参数max_depth=[2,4,6,8,10]test_scores_depth=[]fordepthinmax_depth:clf=RandomForestRegressor(max_depth=depth)test_score_depth=-cross_val_score(clf,X,y,cv=10,scoring='neg_mean_squared_error')test_scores_depth.append(np.mean(test_score_depth))#随机森林的特征数参数max_features=[.1,.3,.5,.7,.9,.99]test_scores_feature=[]forfeatureinmax_features:clf=RandomForestRegressor(max_features=feature)test_score_feature=-cross_val_score(clf,X,y,cv=10,scoring='neg_mean_squared_error')test_scores_feature.append(np.mean(test_score_feature))#随机森林估计器个位数参数n_estimators=[10,50,100,200,500]test_scores_n=[]forninn_estimators:clf=RandomForestRegressor(n_estimators=n)test_score_n=-cross_val_score(clf,X,y,cv=10,scoring='neg_mean_squared_error')test_scores_n.append(npsc_mean())寻找在随机森林的各个参数下,深度为8,选择特征个数的比例为0.5,估计器个数为500,效果最好。接下来用上面得到的参数分别重新训练,看一下学习曲线,过拟合的现象有没有缓解?再回想一下,我们原来的基线模型学习曲线的形状是不是有些缓和了?OK,我们使用模型融合技术来预测数据。#预测ridge=linear_model.Ridge(alpha=10).fit(X,y)rf=RandomForestRegressor(n_estimators=500,max_depth=8,max_features=.5).fit(X,y)y_ridge=np.expm1(ridge.predict(test_df.values))y_rf=np.expm1(rf.predict(test_df.values))y_final=(y_ridge+y_rf)/2本文的房价预测模型已经搭建完成。同样,我们再梳理一下思路:1、本文使用的房价数据集,缺失数据较多,分类变量较多。在预处理阶段,需要结合训练集和测试集,进行缺失填充和one-hotone-hot变量处理,保证数据处理过程的一致性。在数据缺失填充过程中,需要综合考虑特征和数据的实际描述。分布,选择合适的填充方式进行填充;2.为防止数据变量不一致导致模型精度下降,对数值特征进行了标准化处理。数据处理完成后,恢复到训练集和测试集;3.首先建立岭回归和随机森林基准模型,进行三折交叉验证,绘制学习曲线。存在明显的过拟合现象;4.接下来分别调优两个基准模型的参数,得到均方误差最小的参数返回到训练集进行训练;5、采用并行模型融合的方法,计算两个模型预测结果的均值作为测试集的预测结果。
