KaggleのHouse Pricesに挑戦 その1
今回kaggleの初心者向き課題の一つであるHousingPriceに挑戦しました。とはいいつつも項目数が70以上もあり、参加している人もレベルがかなり高いので前回挑戦したタイタニックに比べればはるかに難しいです。
HousingPriceとは
米国アイオワ州のエイムズという都市の物件価格を予測する問題となります。データは、”築年数”、”設備”、”広さ”、”エリア”、”ガレージに入る車の数”など79個の項目数および1460戸の学習データが与えられます。そのデータをもとに、残りの1459戸の家の価格を予測します。
はじめに
今回課題を取り組むにあたって以下のkernel、ブログを参考にしました。
Stacked Regressions : Top 4% on LeaderBoard | Kaggle
こちらのリンクでは欠損値の埋め方等を参考にしました。
KaggleのHousePrices問題を決定木系のアンサンブルで解く - mirandora.commirandora.com
機械学習3ヶ月の初心者がKaggleHousingPriceに挑戦した(Top29%) 前半 - Qiita
Kaggleの練習問題(Regression)を解いてKagglerになる - Qiita
こちらのサイトではどのアルゴリズムを採用するか、また特徴量の考え方、抽出について非常に参考になりました。
価格の分析
まずそもそもアイオワのエイムズに関して知識もないし、価格も全く分からないので、まずは価格帯についてどうなのか調べました。
train = pd.read_csv('train.csv') test = pd.read_csv('test.csv') train['SalePrice'].describe() count 1460.000000 mean 180921.195890 std 79442.502883 min 34900.000000 25% 129975.000000 50% 163000.000000 75% 214000.000000 max 755000.000000 Name: SalePrice, dtype: float64
sns.distplot(train['SalePrice']);
正規分布になってないので、logを使用して一時的に正規分布になるように変換します。
train_ID = train['Id'] test_ID = test['Id'] y_train = train['SalePrice'] X_train = train.drop(['Id','SalePrice'], axis=1) X_test = test.drop('Id', axis=1) ntrain = X_train.shape[0] ntest = X_test.shape[0] Xmat = pd.concat((X_train,X_test)) y_train = np.log(y_train) sns.distplot(y_train);
これで正規分布になりました。もちろん最後には戻す必要があります。
欠損値について
次にデータの中に欠損値があるかどうか調べます。
Xmat_na = (Xmat.isnull().sum() / len(Xmat)) * 100 Xmat_na = Xmat_na.drop(Xmat_na[Xmat_na == 0].index).sort_values(ascending=False)[:30] Xmat_na_missing_data = pd.DataFrame({'Missing Ratio' :Xmat_na}) Xmat_na_missing_data
Missing Ratio | |
---|---|
PoolQC | 99.657417 |
MiscFeature | 96.402878 |
Alley | 93.216855 |
Fence | 80.438506 |
FireplaceQu | 48.646797 |
LotFrontage | 16.649538 |
GarageFinish | 5.447071 |
GarageYrBlt | 5.447071 |
GarageQual | 5.447071 |
GarageCond | 5.447071 |
GarageType | 5.378554 |
BsmtExposure | 2.809181 |
BsmtCond | 2.809181 |
BsmtQual | 2.774923 |
BsmtFinType2 | 2.740665 |
BsmtFinType1 | 2.706406 |
MasVnrType | 0.822199 |
MasVnrArea | 0.787941 |
MSZoning | 0.137033 |
BsmtFullBath | 0.068517 |
BsmtHalfBath | 0.068517 |
Utilities | 0.068517 |
Functional | 0.068517 |
Exterior2nd | 0.034258 |
Exterior1st | 0.034258 |
SaleType | 0.034258 |
BsmtFinSF1 | 0.034258 |
BsmtFinSF2 | 0.034258 |
BsmtUnfSF | 0.034258 |
Electrical | 0.034258 |
ここから欠損値がある項目から数値0、文字の場合はNONEを入れます。一部のみ処理を記載します。
for col in ('BsmtFinSF1', 'BsmtFinSF2', 'BsmtUnfSF','TotalBsmtSF', 'BsmtFullBath', 'BsmtHalfBath'): Xmat[col] = Xmat[col].fillna(0) for col in ('BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2'): Xmat[col] = Xmat[col].fillna('None')
また、Utilitiesの項目はほぼAllPubであり特徴量の解析に寄与しないため削除します。
Xmat = Xmat.drop(['Utilities'], axis=1)
そしてラベルコンバーターよりすべての値を実数にします。
from sklearn.preprocessing import LabelEncoder cols = ('FireplaceQu', 'BsmtQual', 'BsmtCond', 'GarageQual', 'GarageCond', 'ExterQual', 'ExterCond','HeatingQC', 'PoolQC', 'KitchenQual', 'BsmtFinType1', 'BsmtFinType2', 'Functional', 'Fence', 'BsmtExposure', 'GarageFinish', 'LandSlope', 'LotShape', 'PavedDrive', 'Street', 'Alley', 'CentralAir', 'MSSubClass', 'OverallCond', 'YrSold', 'MoSold', 'MSZoning', 'LandContour', 'LotConfig', 'Neighborhood', 'Condition1', 'Condition2', 'BldgType', 'HouseStyle', 'RoofStyle', 'RoofMatl', 'Exterior1st', 'Exterior2nd', 'MasVnrType', 'Foundation', 'Heating', 'Electrical', 'GarageType', 'MiscFeature', 'SaleType', 'SaleCondition') for c in cols: lbl = LabelEncoder() lbl.fit(list(Xmat[c].values)) Xmat[c] = lbl.transform(list(Xmat[c].values))
データはトレーニングデータ、テストデータ含めて加工しましたが、ここでトレーニングデータ、テストデータそれぞれに戻します。
X_train_1 = Xmat[:ntrain] X_test_1 = Xmat[ntrain:]