-
[ML] [Kaggle] House Prices - Advanced Regression Techniques__Data Analysis/__Kaggle 2021. 4. 21. 00:40
수업 중 개별 프로젝트(과제)
- url : www.kaggle.com/c/house-prices-advanced-regression-techniques/data?select=data_description.txt
- 제공 데이터 :
- data_description.txt
- sample_submission.csv
- test.csv
- train.csv
- 요약 :
- 데이터 : 1460 row X 81 columns
- Goal : predict the sales price for each house.(the value of the SalePrice variable.)
- Metric : Submissions are evaluated on Root-Mean-Squared-Error (RMSE) between the logarithm of the predicted value and the logarithm of the observed sales price.
라이브러리 불러오기
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import warnings warnings.filterwarnings(action='ignore') from sklearn.model_selection import train_test_split, GridSearchCV, KFold, StratifiedKFold from sklearn.model_selection import cross_val_score, cross_validate from sklearn.svm import SVC from xgboost import XGBClassifier from lightgbm import LGBMClassifier from sklearn.linear_model import Ridge, Lasso, ElasticNet, LinearRegression, LogisticRegression from sklearn.metrics import mean_squared_error pd.set_option('display.max_columns',None) pd.set_option('display.max_row',None)
1. DATA LOAD
dataset = pd.read_csv('train.csv')
2. EDA
print(dataset.head()) print(dataset.describe())
- Alley 결측치 보임. 전체 데이터 결측치 확인 필요
- MSSubClass, OverallQual 등 카테고리성 피쳐 확인 필요
- LotArea, BsmtFinSF1 등 스케일링 필요한 피쳐 확인 필요
- 불필요한 피쳐 삭제 & 데이터 변환 필요
상관분석 - 무슨 피쳐가 중요할까
df.corrwith(df["SalePrice"]).sort_values(ascending=False)
SalePrice 1.000000 집 가격
OverallQual 0.790982 집 재료 및 마감 평가
GrLivArea 0.708624 지상 거실 면적(평방 피트)
GarageArea 0.623431 차고 크기(평방 피트)
TotalBsmtSF 0.613581 지하 총 면적(평방 피트)
1stFlrSF 0.605852 1층 면적(평방 피트)
FullBath 0.560664 등급? 이상의 전체 욕실
TotRmsAbvGrd 0.533723 등급 이상의 총 방 (욕실 미포함)
YearBuilt 0.522897 연식
YearRemodAdd 0.507101 리모델링 날짜 (개조 또는 추가가없는 경우 시공 날짜와 동일)
Fireplaces 0.466929 벽난로 수
BsmtFinSF1 0.386420 완성 된 평방 피트
LotFrontage 0.351799 부동산에 연결된 거리의 선형 피트
2ndFlrSF 0.319334 2 층 평방 피트
HalfBath 0.284108 등급? 이상의 절반 욕실
LotArea 0.263843 로트 크기 (평방 피트)
BsmtFullBath 0.227122 지하 전체 욕실
BedroomAbvGr 0.168213
BsmtFinSF2 -0.011378 유형 2 완성 된 면적 (평방 피트)
BsmtHalfBath -0.016844 지하 절반 욕실
Id -0.021917 -------------------------------------------------id가 왜 높지?
LowQualFinSF -0.025606 저품질 마감 (모든 층) (평방 피트)
OverallCond -0.077856 집의 전반적인 상태를 평가
MSSubClass -0.084284 판매와 관련된 주거 유형
KitchenAbvGr -0.135907- 모든 피쳐가 필요해보이진 않으며, 우선 SalesPrice와 상관관계가 큰 피쳐가 중요도 높은 것으로 생각됨.
- 따라서 우선 상관계수 높은 것만 데이터프레임 생성하고 점수가 안 좋으면 추가해가기
high_corr = ['SalePrice', 'OverallQual', 'GrLivArea', 'GarageArea', 'TotalBsmtSF', '1stFlrSF', 'FullBath', 'TotRmsAbvGrd', 'YearBuilt', 'YearRemodAdd', 'Fireplaces', 'BsmtFinSF1', 'LotFrontage', '2ndFlrSF', 'HalfBath', 'LotArea', 'BsmtFullBath', 'BedroomAbvGr', 'BsmtFinSF2', 'BsmtHalfBath', 'Id', 'LowQualFinSF', 'OverallCond', 'MSSubClass', 'KitchenAbvGr' ] df = dataset.copy()[high_corr]
피쳐 축소( -> 25개)
print(df.head()) print(df.describe())
상관도 확인
plt.figure(figsize=(15,12)) sns.heatmap(df.corr(),annot=True, fmt='.2g')
결측치 확인
df.isnull().sum()
- 새로 생성한 데이터는 결측치 가진 피쳐가 1개. LotFrontage
- LotFrontage :부동산에 연결된 거리의 선형 피트 -> 우선 중요하지 않아 보여 drop
df = df.drop(['LotFrontage'],axis=1) # print(df.isnull().sum()) # 결측 피처 없음
0 데이터 확인
nan_dict = {"CNT":df.isin([0]).sum(), "RATE": df.isin([0]).sum()/df.shape[0] *100 } nan_df = pd.DataFrame(nan_dict) print(nan_df[nan_df["RATE"]>0].sort_values("CNT", ascending=False))
카테고리성 피쳐 확인
cate_feature = [] no_cate = [] for col in df.columns: if df[col].nunique() <= 40: print(col, df[col].unique()) cate_feature.append(col) else: no_cate.append(col) print() print('개수: ',len(cate_feature)) print('- 카테고리 피쳐 -', cate_feature, sep='\n') print('- 수치 피쳐 -',no_cate,sep='\n')
분포도 확인 - histogram
df.hist(figsize=(12,12)) plt.show()
결측치 없으니 일단 점수 내보기
X_df = df.iloc[:,:-1] y_df = df.iloc[:,-1] X_train, X_val, y_train,y_val = train_test_split(X_df,y_df,test_size=0.3,shuffle=True, random_state=121) print(X_train.shape,X_val.shape,y_train.shape,y_val.shape)
model1 = LinearRegression() model1.fit(X_train,y_train) pred = model1.predict(X_val) mse = mean_squared_error(y_val, pred, squared=True) rmse = mean_squared_error(y_val, pred, squared=False) print(f'MSE:{mse:.5f} , RMSE:{rmse:.5f}') # MSE:0.03584 , RMSE:0.18932
아무런 전처리도 하지 않았고, 스케일링도 되지 않은 상태로 낸 점수 - RMSE 점수가 0.189로 좋게 나왔다. Overfitting이 의심된다.
- 스케일링 후 다시 점수 내보자.
- - - - - - 21.04.20 - - - - - -
위 코드에선 아주 큰 실수가 있었다! 습관의 무서움
이후 전처리와 가공을 더 하고 모델도 추가해 0.8이라는 점수를 봐서 캐글에 제출했다.
- - 결과는 처참한 등수. 쓰기도 싫은 결과물
왜 그럴까 싶어 주피터에서 pred 출력해보니, log 스케일 한것을 원래 스케일로 돌려놨음에도 1.0이라는 값들로 채워져있었다.
구글에도 그런 질문글이 보이지 않아서 강사님께 도움을 청했다. 내 노트북을 보시더니 target이 X_val에 포함 되어있다는걸 발견해주셨다! ㅠㅠ 임의로 컬럼을 선택해 데이터프레임 생성할 때 target을 맨 앞에 뒀다는 걸 잊고 습관처럼 마지막 피쳐를 target으로 분리한 것이었다.
다행히, 그걸 고쳤더니 캐글에서 정상 점수 획득.
새로운 공모전 시작하지만, 시간날 때 틈틈이 피쳐 추가하고 가공 다시해서 30% 까지 올려봅시다
house_price_0421 house_price_0421 - - - - - - 21.04.21 - - - - - -
728x90