这个比赛是通过所给的有关房屋的一些特征数据对房价进行预测。特征包括房子面积、卧室数量、街道情况等等共计79个特征
导入数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
traininitial=pd.read_csv("../input/home-data-for-ml-course/train.csv")
testinitial=pd.read_csv("../input/home-data-for-ml-course/test.csv")
train=traininitial.copy()
test=testinitial.copy()
full=[train,test]
先处理数据的异常值,根据数值型特征与标签的散点图来判断异常值,代码如下:
#取出数据中除了oj类型的数据
train_int=train.select_dtypes(exclude=['object'])
fig=plt.figure(figsize=(20,20))
for i in range(len(train_int.columns)):
fig.add_subplot(10,4,i+1)
sns.scatterplot(x=train_int.iloc[:,i],y=train.SalePrice)
plt.xlabel(train_int.columns[i])
plt.tight_layout()
结果如下图
根据上图删除离群程度较高的值
#删除异常值
train.drop(train[train['BsmtFinSF1']>5000].index,inplace=True)
train.drop(train[train['1stFlrSF']>4000].index,inplace=True)
train.drop(train[train['LotFrontage']>300].index,inplace=True)
train.drop(train[train['TotalBsmtSF']>5000].index,inplace=True)
train.drop(train[(train['GrLivArea']>4000)&
(train['SalePrice']<400000)].index,inplace=True)
train.drop(train[train['LowQualFinSF']>550].index,inplace=True)
train.drop(train[(train['GarageArea']>1200)&(train['SalePrice']<30000)].index,inplace=True)
train.drop(train[train['LotArea']>100000].index,inplace=True)
train.drop(train[train['OpenPorchSF']>400].index,inplace=True)
在来看看缺失值情况
#训练集数值型特征缺失情况
train_int.isnull().sum().sort_values(ascending=False).head()
#测试集数值型特征缺失情况
test_int.isnull().sum().sort_values(ascending=False).head(12)
相关性分析后可以发现GarageYrBlt与YearBuilt有很高的相关性而且又有大量的缺失值,所以可以删掉,代码如下
train.corr()['GarageYrBlt'].sort_values(ascending=False).head()
#这个特征与YearBuilt有很高的相关性而且又有缺失值,所以可以删掉
for dataset in full:
dataset.drop('GarageYrBlt',axis=1,inplace=True)
到这里回头在看看缺失值,会发现有很多都缺一个,像庭院面积,地下室面积等,可以判断这是因为房子没有庭院、地下室而导致数值的缺失。所以我们用0去填充、而对于非数值型数据的缺失我们用NONE去填充
#用none去填充的列表,因为没有那个东西……
ojcoltofill=['PoolQC','MiscFeature','Fence','Alley','FireplaceQu',
'GarageCond','GarageQual','GarageFinish','GarageType',
'BsmtCond','BsmtQual','BsmtExposure','BsmtFinType2',
'BsmtFinType1','MasVnrType']
for col in ojcoltofill:
for dataset in full:
dataset[col].fillna("none",inplace=True)
采用独热编码后填充数据
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
testid=test.Id
y=train.SalePrice
train1=train.drop(["SalePrice","Id"],axis=1)
test1=test.drop("Id",axis=1)
all=pd.concat([train1,test1],axis=0,ignore_index=True)
all_dummies=pd.get_dummies(all)
all_dummies.isnull().sum().sort_values(ascending=False).head(13)
b=all_dummies.MasVnrArea.median()
all_dummies.LotFrontage.fillna(a,inplace=True)
all_dummies.MasVnrArea.fillna(b,inplace=True)
cols=['BsmtFullBath','BsmtHalfBath','GarageArea','GarageCars','BsmtFinSF1',
'BsmtFinSF2','BsmtUnfSF','TotalBsmtSF']
for col in cols:
all_dummies[col].fillna(0,inplace=True)
到这里数据已经全部处理完毕,开始建模。
X=all_dummies.iloc[:1448,:]
TTT=all_dummies.iloc[1448:,:]
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import Lasso
from sklearn.linear_model import LinearRegression
from xgboost import XGBRegressor
xtrain,xtest,ytrain,ytest=train_test_split(X,y,random_state=666)
#lass
las=Lasso(alpha=0.0005)
las.fit(xtrain,ytrain)
lassyp=las.predict(xtest)
print("las_score:\n",las.score(xtest,ytest))
print("las_mae:\n",mean_absolute_error(ytest,lassyp))
print("-"*10)
#线性回归
lr=LinearRegression()
lr.fit(xtrain,ytrain)
lryp=lr.predict(xtest)
print("lr_score:\n",lr.score(xtest,ytest))
print("lr_mae:\n",mean_absolute_error(ytest,lryp))
print("-"*10)
#XGBre
XGBR=XGBRegressor()
XGBR.fit(xtrain,ytrain)
XGBRyp=XGBR.predict(xtest)
print("XGBR_score:\n",XGBR.score(xtest,ytest))
print("XGBR_mae:\n",mean_absolute_error(ytest,XGBRyp))
选用分数最高的lasso回归进行网格搜索优化参数
parama={"alpha":[0.005,0.0003,0.007,0.001,0.0001]}
gridlas=Lasso()
lasgrid=GridSearchCV(gridlas,cv=5,param_grid=parama,n_jobs=-1,verbose=1)
lasgrid.fit(xtrain,ytrain)
print(lasgrid.best_score_)
lasgb=lasgrid.best_estimator_
lasgbyp=lasgb.predict(xtest)
print("lasgbmae:\n",mean_absolute_error(ytest,lasgbyp))
SSS=np.exp(lasgb.predict(TTT))
sumi=pd.DataFrame({"Id":testid,"SalePrice":SSS})
sumi.to_csv('submition.csv',index=False)
这个模型最终交上去排名在1000开外,可是如果把标签对数化后在用这个模型最终结果会在500名左右。因为该标签是呈对数正太分布的。对比如下图所示。
sns.distplot(train.SalePrice)
sns.distplot(np.log(train.SalePrice))
可见数据的正太分布对模型的重要性十分重要。