// 퇴근후딴짓 님의 강의를 참고하였습니다. //
Dataset :
문제) 에어비엔비 가격을 다음과 같은 형식의 CSV 파일로 생성하시오.
- 평가: R-Squared, MAE, MSE, RMSE, RMSLE, MAPE
- target : price(가격)
- csv파일 생성 : 수험번호.csv (예시 아래 참조)
1. 데이터 불러오기
import pandas as pd
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
→ train과 test 2개의 파일로 나누어져있다.
2. EDA
train.shape, test.shape
실행 결과 :
(39116, 16) (9779, 15)
train.head(3)
→ train 데이터는 16개의 열로 이루어져있다.
test.head(3)
→ test 데이터는 15개의 열로 이루어져있다.
train.info()
실행 결과 :
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 39116 entries, 0 to 39115
Data columns (total 16 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 39116 non-null int64
1 name 39102 non-null object
2 host_id 39116 non-null int64
3 host_name 39100 non-null object
4 neighbourhood_group 39116 non-null object
5 neighbourhood 39116 non-null object
6 latitude 39116 non-null float64
7 longitude 39116 non-null float64
8 room_type 39116 non-null object
9 minimum_nights 39116 non-null int64
10 number_of_reviews 39116 non-null int64
11 last_review 31063 non-null object
12 reviews_per_month 31063 non-null float64
13 calculated_host_listings_count 39116 non-null int64
14 availability_365 39116 non-null int64
15 price 39116 non-null int64
dtypes: float64(3), int64(7), object(6)
→ 3개의 실수형, 7개의 정수형, 6개의 object형으로 이루어져있다.
train.isnull().sum()
실행 결과 :
id 0
name 14
host_id 0
host_name 16
neighbourhood_group 0
neighbourhood 0
latitude 0
longitude 0
room_type 0
minimum_nights 0
number_of_reviews 0
last_review 8053
reviews_per_month 8053
calculated_host_listings_count 0
availability_365 0
price 0
dtype: int64
test.isnull().sum()
실행 결과 :
id 0
name 2
host_id 0
host_name 5
neighbourhood_group 0
neighbourhood 0
latitude 0
longitude 0
room_type 0
minimum_nights 0
number_of_reviews 0
last_review 1999
reviews_per_month 1999
calculated_host_listings_count 0
availability_365 0
dtype: int64
→ train, test 데이터 모두 'name', 'host_name', 'last_review', 'review_per_month' 컬럼에 결측치가 있다.
3. 데이터 전처리 & 피처엔지니어링
train.nunique()
실행 결과 :
id 39116
name 38447
host_id 30821
host_name 9943
neighbourhood_group 5
neighbourhood 221
latitude 17378
longitude 13607
room_type 3
minimum_nights 94
number_of_reviews 377
last_review 1720
reviews_per_month 903
calculated_host_listings_count 47
availability_365 366
price 638
dtype: int64
→ 'name', 'host_name', 'last_review', 'host_id' 컬럼은 많은 행을 가지고 있어 제거할 예정이다.
→ 'review_per_month' 컬럼은 결측치에 0을 대입할 예정이다.
cols = ['name', 'host_name', 'last_review', 'host_id']
print(train.shape)
train = train.drop(cols, axis=1)
test = test.drop(cols, axis=1)
print(train.shape)
실행 결과 :
(39116, 16)
(39116, 12)
→ 'name', 'host_name', 'last_review', 'host_id' 컬럼을 제거 후 컬럼이 16개에서 12개로 줄어들었다.
train['reviews_per_month'] = train['reviews_per_month'].fillna(0)
test['reviews_per_month'] = test['reviews_per_month'].fillna(0)
train.isnull().sum()
실행 결과 :
id 0
neighbourhood_group 0
neighbourhood 0
latitude 0
longitude 0
room_type 0
minimum_nights 0
number_of_reviews 0
reviews_per_month 0
calculated_host_listings_count 0
availability_365 0
price 0
dtype: int64
→ 'review_per_month' 컬럼의 결측치를 0으로 대체 후 결측치 확인 시 결측치가 없는 것을 확인 할 수 있다.
train = train.drop('id', axis=1)
test_id = test.pop('id')
→ 제출파일에서 id로 사용될 'id' 컬럼을 제거 및 test_id 변수에 따로 담아둔다.
cols =['neighbourhood_group', 'neighbourhood', 'room_type']
from sklearn.preprocessing import LabelEncoder
for col in cols:
le = LabelEncoder()
train[col] = le.fit_transform(train[col])
test[col] = le.transform(test[col])
train[cols]
→ object형 컬럼 3개를 Label 작업한다.
4. 검증 데이터 분리
from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(train.drop('price', axis=1), train['price'],
test_size=0.15, random_state=2022)
→ target 컬럼인 'price' 를 train에서는 제거하고 test에서는 'price' 컬럼만 포함시켜 분리한다.
5. 모델 & 평가
# 평가
import numpy as np
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
def rmse(y_test, y_pred): #RMSE
return np.sqrt(mean_squared_error(y_test, y_pred))
def rmsle(y_test, y_pred): #RMSLE
return np.sqrt(np.mean(np.power(np.log1p(y_test) - np.log1p(y_pred), 2)))
def mape(y_test, y_pred): #MAPE
return np.mean(np.abs((y_test - y_pred) / y_test)) * 100
→ rmse, rmsle, mape 평가 방법은 sklearn에서 제공되지 않아 함수로 직접 만들어야한다.
# 선형회귀
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_tr,y_tr)
pred=model.predict(X_val)
print("r2: ",r2_score(y_val, pred))
print("mae: ",mean_absolute_error(y_val, pred))
print("mse: ",mean_squared_error(y_val, pred))
print("rmse: ",rmse(y_val, pred))
print("rmsle: ",rmsle(y_val, pred))
print("mape: ",mape(y_val, pred))
실행 결과 :
r2: 0.08452239774949566
mae: 73.98120907242394
mse: 44813.52112975366
rmse: 211.6920431422817
rmsle: 0.628466721627045
mape: 58.89870347351792
# 릿지
from sklearn.linear_model import Ridge
model = Ridge()
model.fit(X_tr,y_tr)
pred=model.predict(X_val)
print(r2_score(y_val, pred))
print("r2: ",r2_score(y_val, pred))
print("mae: ",mean_absolute_error(y_val, pred))
print("mse: ",mean_squared_error(y_val, pred))
print("rmse: ",rmse(y_val, pred))
print("rmsle: ",rmsle(y_val, pred))
print("mape: ",mape(y_val, pred))
실행 결과 :
r2: 0.08458002418498156
mae: 73.94214514943864
mse: 44810.70025955658
rmse: 211.68538036330375
rmsle: 0.6215134552794792
mape: 58.858160278049596
# 라쏘
from sklearn.linear_model import Lasso
model = Lasso()
model.fit(X_tr,y_tr)
pred=model.predict(X_val)
print("r2: ",r2_score(y_val, pred))
print("mae: ",mean_absolute_error(y_val, pred))
print("mse: ",mean_squared_error(y_val, pred))
print("rmse: ",rmse(y_val, pred))
print("rmsle: ",rmsle(y_val, pred))
print("mape: ",mape(y_val, pred))
실행 결과 :
r2: 0.07703411533588211
mae: 74.74494739225966
mse: 45180.07985423047
rmse: 212.55606284985257
rmsle: 0.6125581554187468
mape: 60.8858081365096
# 랜덤포레스트
from sklearn.ensemble import RandomForestRegressor
regressor = RandomForestRegressor()
model.fit(X_tr,y_tr)
pred=model.predict(X_val)
print("r2: ",r2_score(y_val, pred))
print("mae: ",mean_absolute_error(y_val, pred))
print("mse: ",mean_squared_error(y_val, pred))
print("rmse: ",rmse(y_val, pred))
print("rmsle: ",rmsle(y_val, pred))
print("mape: ",mape(y_val, pred))
실행 결과 :
r2: 0.07703411533588211
mae: 74.74494739225966
mse: 45180.07985423047
rmse: 212.55606284985257
rmsle: 0.6125581554187468
mape: 60.8858081365096
# xgb
from xgboost import XGBRegressor
model = XGBRegressor()
model.fit(X_tr,y_tr)
pred=model.predict(X_val)
print("r2: ",r2_score(y_val, pred))
print("mae: ",mean_absolute_error(y_val, pred))
print("mse: ",mean_squared_error(y_val, pred))
print("rmse: ",rmse(y_val, pred))
print("rmsle: ",rmsle(y_val, pred))
print("mape: ",mape(y_val, pred))
실행 결과 :
r2: 0.1870945928960972
mae: 66.26209479359112
mse: 39792.51217964102
rmse: 199.48060602384638
rmsle: 0.5132144368515108
mape: 48.07212870050863
→ 선형 회귀, 릿지, 라쏘, 랜덤포레스트, xgb 5개의 모델로 평가한 결과이다.
→ 오차에 기반한 평가방법으로 값이 작을수록 모델 성능이 뛰어난 것이다. xgb 모델이 가장 뛰어난 것으로 보인다.
6. 예측 및 csv 제출
pred = model.predict(test)
pred
실행 결과 :
array([261.76437, 137.69249, 173.10406, ..., 176.9876 , 170.21184,
211.4193 ], dtype=float32)
→ 검증용 데이터가 아닌 실제 제출용 test 데이터로 예측한 결과이다.
→ array 안의 숫자는 에어비엔비 가격을 예측한 것이다.
pd.DataFrame({'id':test_id, 'output':pred}).to_csv("00000.csv", index=False)
→ 문제 예시와 같이 'id' 컬럼에 test_id를 'output' 컬럼에 예측 가격을 넣어 데이터프레임을 만든다.
pd.read_csv("00000.csv")
→ 제출용 csv 파일을 만든 후 read_csv로 불러와 제출이 제대로 되었는지 재확인한다.
'빅데이터분석기사 > 작업형2' 카테고리의 다른 글
[작업형2] 유방암 예측 모델 만들기(분류) (0) | 2023.06.22 |
---|---|
[작업형2] 심장마비 확률 높은 사람 구하기(분류 / 튜닝) (0) | 2023.06.17 |
[작업형2] 신용카드 서비스를 떠나는 고객 확률 구하기(분류) (0) | 2023.06.17 |
[작업형2] 보험가입 확률 구하기(분류) (1) | 2023.06.17 |
[작업형2] 제품 배송 시간에 맞춰 배송되었는지 예측하기(분류) (0) | 2023.06.15 |