회귀모델 실습으로 캘리포니아 집값 예측 프로젝트를 하였다.
https://scikit-learn.org/stable/datasets/real_world.html#california-housing-dataset
7.2. Real world datasets
scikit-learn provides tools to load larger datasets, downloading them if necessary. They can be loaded using the following functions: The Olivetti faces dataset: This dataset contains a set of face...
scikit-learn.org
1. 데이터 불러오기
- 데이터는 scikit-learn에서 제공하기 때문에, 손쉽게 가져올 수 있다.
# 라이브러리 불러오기
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 캘리포니아 집값 데이터 불러오기
from sklearn.datasets import fetch_california_housing
# data = fetch_california_housing()
# data # 그냥 출력하면 dictionary 형태로 나온다.
X = fetch_california_housing(as_frame = True)['data']
y = fetch_california_housing(as_frame = True)['target']
display(X)
display(y)
# EDA를 하기 위해 X, y를 결합한다
data = pd.concat([X, y], axis = 1)
- 집값 데이터를 data 변수에 담아 출력해보면, dictionary 형태로 되어있다.
- as_frame을 True로 하고, data와 target을 구분하면 보기좋게 바꿀 수 있다.
2. Data Preprocessing(전처리)
2-1. 결측치 처리
data.info()
- 결측치가 없다.
- 추가로, 특정 값이 ' ' 이런식으로 빈칸이 입력되어 있어서 갯수는 맞지만 결측치인 경우가 있다.
- Dtype이 object가 아닌지도 같이 확인한다.
2-2. Feature Selection
- 이번 실습에서는 다 사용하기로 한다.
3. EDA
- 일반적으로 EDA는 train, test 데이터가 분리된 상태에서, train 데이터에 대해서만 한다.
- 하지만 이번 실습에서는 편의상 전체 데이터에 해대 EDA를 한다.
3-1. Feature Distribution
data.head()
- 정답인 label(=target) 데이터는 MedHouseVal 컬럼, 나머지 8개는 주어진 데이터이다.
- 8개 컬럼의 연속적인 값들이 어떤 특성을 갖는지 파악하기 위해 분포를 확인한다.
(각 컬럼의 구체적인 설명은 scikit-learn 사이트에 나와있음으로 생략한다.)
sns.histplot(data = data, x = "MedInc")
- MedInc 컬럼은, 2 ~ 5 사이에 많이 분포한다.
- MedInc 값이 커질수록 점점 줄어들다가 마지막에 그래프가 튀어나오는데,
- 이는 일반적으로 상한선을 두고 상한선 이후로는 값을 똑같이 수정하는 방법(Clipping)을 써서 그렇다고 한다.
sns.histplot(data = data, x = "AveBedrms")
- AveBedrms는 데이터 분포가 매우 불균형한 것을 볼 수 있다.
- 이러한 데이터의 경우는, histplot 보다는 boxplot으로 확인하는 것이 더 좋다.
plt.figure(figsize=(10, 6))
sns.boxplot(data = data.loc[:, ["AveRooms", "AveBedrms"]])
- 이렇게 평균을 크게 벗어나는 데이터의 경우는 Outlier로 볼 수 있기 때문에 학습성능 향상을 위해 제거하는 편이 좋다.
3-2. Target Distribution
sns.histplot(data = data, x = "MedHouseVal")
- 50만 달러 이상은 다 같은값으로 처리되어 있다. 경향성을 보기 위해서는 제거하는 것이 좋다.
(분류에서는 크게 상관없지만, 회귀에서는 특정 값을 찾아야 하기 때문에 데이터가 일관되지 않으면 학습에 방해가 된다.)
3-3. Correlation analysis
sns.heatmap(data.corr(), annot = True)
- MedHouseVal과의 관계를 살펴보면, MedInc가 0.69로 강한 상관관계를 갖는다.
- AveRooms와 AveBedrms는 0.85로 변수간 상관관계가 강하게 나타난다.
- 이 경우는 다중공선성(multi-collinearity) 문제가 있을 수 있기 때문에 하나만 사용한다.
- Latitude & Longitude(-0.92)와 HouseAge & Population(-0.3)도 확인해 볼 필요가 있다.
4. Feature Engineering
4-1. Remove Outlier
data = data[~np.logical_or(data.AveRooms > 100, data.AveOccup > 200)]
- 앞서 확인한 바와 같이, AveRooms, AveOccup 컬럼은 데이터가 넓게 분포되어 있기 때문에 Outlier 제거를 한다.
- AveRooms 값이 100 이상이거나, AveOccup 값이 200 이상인 경우는 삭제했다.
- 기준은 25, 50, 100.. 이런식으로 임계값(Threshold)을 기준으로 나눠 관련성, 특징 등을 파악해서 정할 수 있다.
- 기준을 찾기 애매한 경우는, 학습을 시켜보며 결과가 잘 나오는 기준을 정할 수도 있다.
4-2. Remove Columns(multi-collinearity problems)
data = data.drop(columns = ["AveBedrms", "Longitude"])
- AveBedrms는 AveRooms와 상관관계가 높기 때문에 삭제한다.
- Longitude는 Latitude와 상관관계가 높기 때문에 삭제한다.
5. Training
5-1. Train-Test Split
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=42)
print(X_train.shape, X_val.shape, y_train.shape, y_val.shape) # 6 : 2 : 2로 분할
- train, validation, test(6 : 2 : 2) 데이터로 분할한다.
5-2. Standardization
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.fit_transform(X_val)
X_test = scaler.fit_transform(X_test)
- sklearn의 StandardScaler를 이용하여 표준화 한다. 평균이 0, 분산이 1이 되도록 표준정규분포 형태로 만든다.
(여기서 모든 데이터를 다 표준화 하지만, 일반적으로는, train, test 데이터를 분리하고 train 전처리 모듈을 만들어 test에 그대로 적용한다.)
5-3. Model Training
# 학습을 위한 라이브러리 세팅
from sklearn.linear_model import LinearRegression # 1. Linear Regression
from sklearn.linear_model import Lasso # 2. Lasso
from sklearn.linear_model import Ridge # 3. Ridge
from xgboost.sklearn import XGBRegressor # 4. XGBoost. XGBoost는 라이브러리가 따로 있는데 이렇게 하면 sklearn 버전으로 사용 가능
from lightgbm.sklearn import LGBMRegressor # 5. LightGBM
# 평가지표
from sklearn.metrics import mean_squared_error
## training
reg1 = LinearRegression()
reg2 = Lasso()
reg3 = Ridge()
reg4 = XGBRegressor()
reg5 = LGBMRegressor()
reg1.fit(X_train, y_train)
reg2.fit(X_train, y_train)
reg3.fit(X_train, y_train)
reg4.fit(X_train, y_train)
reg5.fit(X_train, y_train)
- 회귀모델은 이론에서 배웠던 Linear Regression, Lasso, Ridge, XGBoost, LightGBM 4가지를 가져온다.
- X_train 데이터로 각 회귀모델들을 학습시킨다.
# 예측코드를 모델별로 다 작성하기 번거로워 함수화 하였다.
def pred(model, X_train, y_train, X_val="test", y_val="test"):
pred_train = model.predict(X_train)
mse_train = mean_squared_error(y_train, pred_train)
if X_val != "test":
pred_validation = model.predict(X_val)
mse_validation = mean_squared_error(y_val, pred_validation)
print(str(model).split('(')[0] + " model\t\t, train = %.4f, validation = %.4f" % (mse_train, mse_validation))
else:
print(str(model).split('(')[0] + " model\t\t, test = %.4f" % (mse_train))
pred(reg1, X_train, y_train, X_val, y_val)
pred(reg2, X_train, y_train, X_val, y_val)
pred(reg3, X_train, y_train, X_val, y_val)
pred(reg4, X_train, y_train, X_val, y_val)
pred(reg5, X_train, y_train, X_val, y_val)
- train에서는 XGBoost가 0.0645로 오차가 가장 작게 나왔다.
- validation에서는 LightGBM이 0.2951로 오차가 가장 작게 나왔다.
5-4. Hyper-Parameter Tuning
- LightGBM을 사용하려고 하는데, 이 회귀모델은 hyper-parameter에 민감하다.
- GridSearch 방법으로 hyper-parameter를 튜닝한다.
# GridSearchCV
from sklearn.model_selection import GridSearchCV
# hyper-paramete의 조합을 dictionary 형태로 만든다.
# 총 조합은 12개
param_grid = {
"max_depth" : [3, 5, -1],
"learning_rate" : [0.1, 0.01],
"n_estimators" : [50, 100]
}
gcv = GridSearchCV(reg5, param_grid, scoring="neg_mean_squared_error", verbose=2)
gcv.fit(X_train, y_train)
- hyper-parameter를 튜닝하는 방법은 총 3가지가 있다.
- 1. 사람이 직접 하나씩 해보는 것, 2. hyper-parameter의 조합을 모두 돌려보는 것(GridSearch), 3. Baysian 최적화
- Boosting 계열의 tree방식은, 이전 tree의 loss를 줄여주는 방향으로 늘어난다.
- 따라서 tree 갯수가 많으면 overfitting 될 가능성이 있기 때문에 무조건 많다고 좋은게 아님을 염두해 두어야 한다.
- 일반적으로 많이 사용하는 max_depth, learning_rate, n_estimators에 대해서 조합을 만든다.
- 조합 수가 많아질 수록 메모리와 시간 소요가 크게 증가한다.
# print(gcv.cv_results_) # 전체 내용을 다 출력한다.
print(gcv.best_estimator_)
print(gcv.best_params_)
final_model = gcv.best_estimator_ # 가장 좋은 모델을 변수로 지정한다.
- best 조합은 defult 옵션과 동일하게 나왔다.
6. TEST(Prediction)
pred(reg1, X_test, y_test)
pred(reg2, X_test, y_test)
pred(reg3, X_test, y_test)
pred(reg4, X_test, y_test)
pred(reg5, X_test, y_test)
- LightGBM 모델의 오차가 가작 작게 나왔다.
실습 끝!
'클래스 리뷰 > 22.12 K-Digital 기초역량훈련 딥러닝 강의' 카테고리의 다른 글
[패스트캠퍼스] 딥러닝 강의 - 분류모델 실습 (0) | 2023.04.01 |
---|---|
[패스트캠퍼스] 딥러닝 강의 - 6주차 학습일지 - 파이널 프로젝트 및 후기 (0) | 2023.02.08 |
[패스트캠퍼스] 딥러닝 강의 - 5주차 학습일지 - 클러스터링 모델 정리 (0) | 2023.02.08 |
[패스트캠퍼스] 딥러닝 강의 - 4주차 학습일지 - 회귀 모델 정리 (0) | 2023.02.03 |
[패스트캠퍼스] 딥러닝 강의 - 3주차 학습일지 - 분류 모델 정리 (0) | 2023.02.01 |
댓글