데이터 : data_regression.zip (수업노트에서 다운로드)
- train.csv, test.csv만 사용
- y_test.csv파일은 최종 평가용임
머신러닝¶
- 문제정의, 라이브러리/데이터 불러오기
- 탐색적 데이터 분석 (EDA)
- 데이터 전처리
- 피처엔지니어링
- (Train/Validation 나누기)
- 모델 선택/훈련/평가/최적화
- 예측
- (csv 생성)
문제정의, 라이브러리/데이터 불러오기¶
- 보험료 예측
- 평가: rmse
- csv: id와 예측 값
In [132]:
# 라이브러리 및 데이터 불러오기
import pandas as pd
test = pd.read_csv(r'C:\Users\Master\Desktop\데이터자격증\빅분기_실기\퇴근후딴짓\insurance\test.csv')
train = pd.read_csv(r'C:\Users\Master\Desktop\데이터자격증\빅분기_실기\퇴근후딴짓\insurance\train.csv')
EDA¶
In [133]:
# 데이터 크기 확인
test.shape, train.shape
Out[133]:
((268, 7), (1070, 8))
In [134]:
# 데이터 샘플 확인 (train)
train.head()
# 시험에서는 타겟컬럼 표시될 것이다.
# test데이터와의 차이나는 charges가 타겟컬럼
Out[134]:
id | age | sex | bmi | children | smoker | region | charges | |
---|---|---|---|---|---|---|---|---|
0 | 330 | 61 | female | 36.385 | 1 | yes | northeast | 48517.56315 |
1 | 748 | 47 | female | 36.000 | 1 | no | southwest | 8556.90700 |
2 | 684 | 33 | female | 18.500 | 1 | no | southwest | 4766.02200 |
3 | 35 | 19 | male | 20.425 | 0 | no | northwest | 1625.43375 |
4 | 353 | 33 | male | 35.245 | 0 | no | northeast | 12404.87910 |
In [135]:
# 데이터 샘플 확인 (test)
test.head()
Out[135]:
id | age | sex | bmi | children | smoker | region | |
---|---|---|---|---|---|---|---|
0 | 508 | 24 | female | 25.270 | 0 | no | northeast |
1 | 1309 | 41 | male | 32.200 | 2 | no | southwest |
2 | 766 | 47 | male | 32.300 | 1 | no | southwest |
3 | 667 | 40 | female | 32.775 | 2 | yes | northwest |
4 | 1057 | 45 | female | 31.790 | 0 | no | southeast |
In [136]:
# 결측치 확인 (train)
train.isnull().sum()
Out[136]:
id 0 age 0 sex 0 bmi 0 children 0 smoker 0 region 0 charges 0 dtype: int64
In [137]:
# 결측치 확인 (test)
test.isnull().sum()
Out[137]:
id 0 age 0 sex 0 bmi 0 children 0 smoker 0 region 0 dtype: int64
In [138]:
# 통계값 확인
train.describe()
Out[138]:
id | age | bmi | children | charges | |
---|---|---|---|---|---|
count | 1070.000000 | 1070.000000 | 1070.000000 | 1070.000000 | 1070.000000 |
mean | 671.090654 | 39.024299 | 30.730495 | 1.090654 | 13193.634800 |
std | 380.666780 | 13.916945 | 6.053260 | 1.204997 | 12211.531632 |
min | 0.000000 | 18.000000 | 16.815000 | 0.000000 | 1121.873900 |
25% | 347.250000 | 27.000000 | 26.400000 | 0.000000 | 4695.398638 |
50% | 673.000000 | 39.000000 | 30.400000 | 1.000000 | 9273.638800 |
75% | 990.250000 | 51.000000 | 34.800000 | 2.000000 | 15826.112723 |
max | 1337.000000 | 64.000000 | 52.580000 | 5.000000 | 63770.428010 |
In [139]:
# 통계값 object (train)
train.describe(include='O')
Out[139]:
sex | smoker | region | |
---|---|---|---|
count | 1070 | 1070 | 1070 |
unique | 2 | 2 | 4 |
top | male | no | southeast |
freq | 544 | 856 | 287 |
In [140]:
# 통계값 object (test)
test.describe(include='O')
Out[140]:
sex | smoker | region | |
---|---|---|---|
count | 268 | 268 | 268 |
unique | 2 | 2 | 4 |
top | female | no | southeast |
freq | 136 | 208 | 77 |
데이터 전처리 및 피처 엔지니어링¶
In [141]:
# 데이터 샘플
train.head()
Out[141]:
id | age | sex | bmi | children | smoker | region | charges | |
---|---|---|---|---|---|---|---|---|
0 | 330 | 61 | female | 36.385 | 1 | yes | northeast | 48517.56315 |
1 | 748 | 47 | female | 36.000 | 1 | no | southwest | 8556.90700 |
2 | 684 | 33 | female | 18.500 | 1 | no | southwest | 4766.02200 |
3 | 35 | 19 | male | 20.425 | 0 | no | northwest | 1625.43375 |
4 | 353 | 33 | male | 35.245 | 0 | no | northeast | 12404.87910 |
In [142]:
# object 컬럼명 선택
cols = train.select_dtypes(include='object').columns
cols
Out[142]:
Index(['sex', 'smoker', 'region'], dtype='object')
In [143]:
# 원핫 인코딩
train = pd.get_dummies(train, columns=cols)
test = pd.get_dummies(test, columns=cols)
In [66]:
display(train.head(2), test.head(2))
# 데이터 분리로 넘어가기
id | age | bmi | children | charges | sex_female | sex_male | smoker_no | smoker_yes | region_northeast | region_northwest | region_southeast | region_southwest | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 330 | 61 | 36.385 | 1 | 48517.56315 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
1 | 748 | 47 | 36.000 | 1 | 8556.90700 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
id | age | bmi | children | sex_female | sex_male | smoker_no | smoker_yes | region_northeast | region_northwest | region_southeast | region_southwest | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 508 | 24 | 25.27 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
1 | 1309 | 41 | 32.20 | 2 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
In [78]:
# 스케일링
# 선형회귀모델로 한번 학습한 후 다시 올라옴
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
cols = ['age', 'bmi']
train[cols] = scaler.fit_transform(train[cols])
test[cols] = scaler.fit_transform(test[cols])
train.head()
# 데이터 분리로 넘어가기
Out[78]:
id | age | bmi | children | charges | sex_female | sex_male | smoker_no | smoker_yes | region_northeast | region_northwest | region_southeast | region_southwest | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 330 | 1.579799 | 0.934562 | 1 | 48517.56315 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
1 | 748 | 0.573361 | 0.870931 | 1 | 8556.90700 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
2 | 684 | -0.433078 | -2.021426 | 1 | 4766.02200 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
3 | 35 | -1.439516 | -1.703266 | 0 | 1625.43375 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
4 | 353 | -0.433078 | 0.746146 | 0 | 12404.87910 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
In [144]:
# 다른 스케일링으로 다시한번 스케일링
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
cols = ['age', 'bmi']
train[cols] = scaler.fit_transform(train[cols])
test[cols] = scaler.fit_transform(test[cols])
In [95]:
# 로그 스케일 전(시각화) (참고용)
train['charges'].hist()
Out[95]:
<Axes: >
In [124]:
# 로그 스케일
train['charges'] = np.log1p(train['charges'])
In [101]:
# 로그 스케일 후(시각화)
train['charges'].hist()
Out[101]:
<Axes: >
검증 데이터 분리¶
In [145]:
# 검증 데이터 분리
from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(train.drop('charges', axis=1),
train['charges'], test_size=0.1,
random_state=2022)
X_tr.shape, X_val.shape, y_tr.shape, y_val.shape
Out[145]:
((963, 12), (107, 12), (963,), (107,))
In [146]:
# X 데이터 확인
X_tr.head(1)
Out[146]:
id | age | bmi | children | sex_female | sex_male | smoker_no | smoker_yes | region_northeast | region_northwest | region_southeast | region_southwest | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
127 | 1154 | 0.652174 | 0.310779 | 4 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
In [147]:
# y 데이터 확인
y_tr.head(1)
Out[147]:
127 11015.1747 Name: charges, dtype: float64
In [148]:
# 평가 수식
from sklearn.metrics import mean_squared_error
# 평가방식인 rmse는 sklearn에서 지원해주지 않음
# 대신 mse 까지는 지원해줌 -> mse로 나온값에 루트를 씌워야함
import numpy as np
np.sqrt(9)
def rmse(y_test, pred):
return np.sqrt(mean_squared_error(y_test, pred))
In [149]:
# LinearRegression
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_tr, y_tr)
pred = lr.predict(X_val)
rmse(y_val, pred)
# 여기까지 한 후 다시 올라가서 데이터 전처리, 피처엔지니어링 더 할것 없는지 수행 후
# 동일한 모델로 다시 학습
# 이 과정을 반복하여 데이터를 다듬은 후 다른 모델에 적용
Out[149]:
5994.750205589361
In [107]:
# LinearRegression의 스케일링 후 모델에 학습시키기 전에 전 데이터 저장
# 5994.750205589531 : 베이스 라인
In [130]:
# 로그 스케일링 후 선형회귀
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_tr, y_tr)
pred = lr.predict(X_val)
rmse(np.exp(y_val), pred)
Out[130]:
18740.808722590868
In [150]:
# RandomForestRegressor
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor()
model.fit(X_tr, y_tr)
pred = model.predict(X_val)
rmse(y_val, pred)
Out[150]:
4735.313953691273
In [ ]:
# RandomForestRegressor의 스케일링 후 모델에 학습시키기 전에 전 데이터 저장
# 원핫인코딩만 상태 => 4716.528676602531 : 베이스 라인
# 원핫인코딩+표준화된 상태 => 4723.135160687038 - 값이 커짐(= 에러값이 커짐 ) -> 안좋아짐
# 원핫인코딩+민맥스케일링 => 4735.313953691273
# 두 스케일링까지 진행 후 결과를 비교했을때
# 강의에서처럼 베이스라인보다 안좋은 상태면
# 스케일링을 따로 하는 것이 좋을지 한 컬럼을 스케일링할때 제외 후 시도
# 그래도 안좋다면 스케일링안하는 것이 좋기에 실패 -> 기록
In [131]:
# RandomForestRegressor - 로그스케일 후
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor()
model.fit(X_tr, y_tr)
pred = model.predict(X_val)
rmse(np.exp(y_val), pred)
Out[131]:
18740.77476357595
In [152]:
# xgboost Regressor
from xgboost import XGBRegressor
xgb = XGBRegressor(objective='reg:squarederror')
# 파라미터를 지정해주지 않으면 에러가 뜰수 있음
# 시험에서는 랜덤포레스트가 적절할 것 같다
# xgboost를 사용하기 위해서는 지정 파라미터에 대해 공부해야함
model = RandomForestRegressor()
model.fit(X_tr, y_tr)
pred = model.predict(X_val)
rmse(y_val, pred)
Out[152]:
4617.391340886045
In [ ]:
# xgboost 기록
# 4617.391340886045 - 민맥스케일링
In [153]:
# test 데이터 예측
pred = model.predict(test)
In [156]:
# 제출용 데이터 프레임
submit = pd.DataFrame({
'id':test['id'],
'charges':pred
})
# 컬럼명 웬만하면 복사하기
In [157]:
# csv파일 생성
submit.to_csv('2222.csv',index=False)
평가¶
- 수험자는 알 수 없는 영역
In [158]:
y_test = pd.read_csv(r'C:\Users\Master\Desktop\데이터자격증\빅분기_실기\퇴근후딴짓\insurance\y_test.csv')
rmse(y_test['charges'], pred)
Out[158]:
4841.49901137069
In [ ]:
'빅데이터 분석 기사 공부' 카테고리의 다른 글
작업형1 모의문제2 (0) | 2023.11.06 |
---|---|
작업형1 모의문제1 (0) | 2023.11.06 |
머신러닝_분류모델(범주형 데이터) (0) | 2023.11.06 |
피처엔지니어링 (0) | 2023.11.06 |
데이터 전처리 (0) | 2023.11.06 |