=> 지정된 조합만 보기 때문에 해당 그리드를 벗어나는 곳에 좋은 성능을 내는 하이퍼파라미터가 있다면 찾지 못하는 단점이 있습니다.
=> 랜덤한 값을 넣고 하이퍼파라미터를 찾습니다.
처음에는 범위를 넓게 지정하고 그 중에 좋은 성능을 내는 범위를 점점 좁혀가면서 찾습니다.
param_distributions = {"max_depth": np.random.randint(3, 100, 10),
"max_features": np.random.uniform(0, 1, 10)}
clf = RandomizedSearchCV(estimator=model,
param_distributions=param_distributions,
n_iter=5,
n_jobs=-1,
random_state=42
)
clf.fit(X_train, y_train)
n_iter: 반복횟수값
Fitting 5 folds for each of 5 candidates, totalling 25 fits => 5 fold 는 cv 조각 5개를 의미하며 5 candidates 는 n_iter를 의미
랜덤포레스트 안에 트리의 개수가 100개가 기본값이라면 그 내부에서도 트리를 100개를 만들기 때문에 디시전트리를 사용할 때보다 속도가 더 오래 걸린다
CV 기본값 = 5
cv는 cross validation의 약자로 어떤 조각이 어떤 성능을 냈는지를 알려줍니다.
cvresults
pd.DataFrame(clf.cvresults).sort_values(by="rank_test_score")
7:3 이나 8:2 로 나누는 과정은 hold-out-validation
hold-out-validation 은 중요한 데이터가 train:valid 가 7:3이라면 중요한 데이터가 3에만 있어서 제대로 학습되지 못하거나 모든 데이터가 학습에 사용되지도 않음. 그래서 모든 데이터가 학습과 검증에 사용하기 위해 cross validation을 진행
cross validation은 속도가 오래걸린다는 단점이 있기도 하지만 validation의 결과에 대한 신뢰가 중요할 때 사용.
ex) 사람의 생명을 다루는 암여부를 예측하는 모델을 만든다거나 하면 좀 더 신뢰가 있게 검증이 유리
hold-out-validation 은 한번만 나눠서 학습하고 검증하기 때문에 빠르지만 신뢰가 떨어지는 단점이 있음. hold-out-validation 은 당장 비즈니스에 적용해야 하는 문제에 빠르게 검증해보고 적용해 보기에 좋음
-> cross validation 이 너무 오래 걸린다면 조각의 수를 줄이면 좀 더 빠르게 결과를 볼 수 있고 신뢰가 중요하다면 조각의 수를 좀 더 여러 개 만들어 보면 된다
🔷점수를 올리고 내리는데 너무 집중하기 보다는 일단은 다양한 방법을 시도해 보는 것을 추천합니다!!
점수 평가 기준: RMSLE
-> RMSE와 비슷, 중간에 log L이 있음
회귀문제: 공유 자전거 수요예측(매시간 빌려진 자전거 수)
데이터 설명(도메인 지식 이해하기)
datetime - hourly date + timestamp
season - 1 = spring, 2 = summer, 3 = fall, 4 = winter
-> 계절로 1,2,3,4로 ordinal encoding(순서가 있는 값)으로 인코딩 됨
holiday - whether the day is considered a holiday
workingday - whether the day is neither a weekend nor holiday
weather - 1: Clear, Few clouds, Partly cloudy, Partly cloudy
2: Mist + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist
3: Light Snow, Light Rain + Thunderstorm + Scattered clouds, Light Rain + Scattered clouds
4: Heavy Rain + Ice Pallets + Thunderstorm + Mist, Snow + Fog
-> weather 는 1이면 맑은 날, 2는 흐린날, 3은 눈,비 오는 날, 4는 폭우, 폭설, 우박 내리는 날
temp - temperature in Celsius
atemp - "feels like" temperature in Celsius
-> 체감온도
humidity - relative humidity
windspeed - wind speed
casual - number of non-registered user rentals initiated
registered - number of registered user rentals initiated
count - number of total rentals
🔷답을 바로 찾기보다는 호기심을 갖자!!
🎈데이터 해석
-> 결측치가 없다, object도 없다
-> casual, registered, count의 평균값에 비해 max 값이 크다
-> 습도와 풍속이 0인 날이 있다
1. 풍속
: 결측치가 없는 줄 알았는데 windspeed에서 1313개나 0값을 가진다
2. 습도
:습도와 대여량에 연관성이 적어 습도에 결측치가 있는 것 같지만 굳이 전처리를 안 해줘도 됨(상관이 커 보인다면 결측치를 전처리 해주면 좋다)
3. 온도&체감온도
: 큰 상관관계를 가짐. 작은 예외가 존재하지만 온도가 높아지면 높아질수록 체감온도도 높아진다
-> 이상치보다는 오류 데이터가 존재한다고 볼 수 있음
n_estimators=100,
*,
criterion='squared_error',
max_depth=None,
min_samples_split=2,
min_samples_leaf=1,
min_weight_fraction_leaf=0.0,
max_features='auto',
max_leaf_nodes=None,
min_impurity_decrease=0.0,
bootstrap=True,
oob_score=False,
n_jobs=None,
random_state=None,
verbose=0,
warm_start=False,
ccp_alpha=0.0,
max_samples=None,
)
-> 분류 or 회귀일 때 criterion 값을 제외하고 나머지는 같다
-> criterion: {"squared_roor", "absolute_error", "poisson"}
✅MAE
✅MSE
✅RMSE
✅RMSLE(Root Mean Squared Logarithmic Error)
🔷로그 그래프의 기울기를 보면 작은 값에 기울기가 더 가파르고 값이 커질수록 기울기가 완만해 짐
-> 1을 더한후 로그값을 취한 이유: x 가 1보다 작으면 음수가 나오기 때문에 1을 더해서 1이하의 값이 나오지 않게 하기위해
(train은 나올 수 없지만 test는 0이 나올 수 있음)
=> 로그 값 씌우면 sacle값이 줄어듦,
skewed 값이 덜 skewed하게 됨(덜 찌그러지게 된다),
정규분포에 좀 더 가까워짐
np.log의 밑 = e
✒️Q. 로그를 취하기 전에 모든 값에 1을 더해서 가장 작은 값이 될 수 있는 0이 1이 되도록 더해주는 이유는 마이너스 값이 나왔는데 MSE를 계산한다면 어떻게 될까?
✒️A. 의도치 않은 큰 오차가 나올 수 있기 때문에 가장 작은 값이 될 수 있는 0에 1을 더해서 마이너스 값이 나오지 않게 해야 함
==> RMSLE는 RMSE 와 거의 비슷하지만 오차를 구하기 전에 예측값과 실제값에 로그를 취해주는 것만 다름
from sklearn.metrics import mean_squared_log_error
rmsle = np.sqrt(mean_squared_log_error(y_train, y_valid_pred))
ex) 부동산 가격
1) 2억원짜리 집을 4억으로 예측
2) 100억원짜리 집을 110억원으로 예측
Absolute Error 절대값의 차이로 보면
1) 2억 차이 2) 10억 차이
Squared Error 제곱의 차이로 보면
1) 4억차이 2) 100억차이
Squared Error 에 root 를 취하면 absolute error 하고 비슷해짐
-> 비율 오류로 봤을 때 1)은 2배 잘못 예측, 2)10% 잘못 예측
💥RMSE: 오차가 클수록 가중치를 주게 됨(오차 제곱의 효과)
💥RMSLE: 오차가 작을수록 가중치를 주게 됨(로그의 효과)
💥MAE: 가중치 없음(제곱, 로그 둘 다 없음)
피처 중요도가 높다고 높은 점수가 나오는 것은 아님
(피처 중요도란 어느 데이터 요소가 확률값 계산에 중요하게 작용을 했느냐 하는 정도를 나타내는 것)
점수가 높아야 좋은 측정 지표의 예시는 정확도를 기반으로 하는 분류의 측정지표인 Accuracy와 회귀 모델에서 독립변수가 종속변수를 얼마나 잘 설명했는지 보여주는 결정계수 (r2 score)등
점수가 낮아야 좋은 측정 지표는 에러 기반의 측정 지표인 MAE, MSE, RMSE 등
=> R square score 는 1에 가까울수록 더 좋은 성능을 의미. 예측값과 실제값이 같으면 1. 최대값이 1인데 클수록 좋고. 나머지 회귀의 측정공식은 오차를 측정하기 때문에 낮아야 좋다.
✅상대경로 VS 절대경로
상대경로는 현재 경로를 기준으로 하는 경로
ex) ./ 현재 경로 의미
절대경로는 전체 경로를 다 지정하는 경우
ex) 윈도우 C:부터 시작하는 경로
현재 경로에서 ./ 쓰는 것과 아무것도 안 쓰는것과 같은 위치를 나타냄
-> 절대경로를 사용하면 다른 사람의 컴퓨터에서 동작하지 않기 때문에 되도록이면 상대경로를 사용하는 것을 권장
🔷가장 추천하는 방법: .ipynb파일과 data 폴더를 같은 위치에 두는 것
log를 count 값에 적용하게 되면 한쪽에 너무 뾰족하게 있던 분포가 좀더 완만한 분포가 된다
데이터에 따라 치우치고(skewed) 뾰족한 분포가 정규분포에 가까워지기도 함
log를 취한 값을 사용하게 되면 이상치에도 덜 민감하게 됨
# count - kdeplot fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12,3)) sns.kdeplot(train["count"], ax=axes[0])
# count log1p - kdeplot sns.kdeplot(np.log1p(train['count']), ax=axes[1])
✒️ 왜 정규분포가 되면 머신러닝이나 딥러닝에서 좋은 성능을 낼까?
-> 값을 볼 때 한쪽에 너무 치우쳐져 있고 뾰족하다면 특성을 제대로 학습하기가 어렵기 때문에 정규분포로 되어 있다면 특성을 고르게 학습할 수 있음
지수함수
train['count_expm1'] = np.exp(train['count_log1p'])-1
train[['count', 'count_log1p', 'count_expm1']]```
-> expm1을 했더니 로그 계산이 제거되고 원래 값으로 되돌려줌
-> log를 취할 때는 1을 더하고 로그를 취했는데 지수함수를 적용할 때는 반대의 순서대로 복원해야 순서가 맞음
-> np.exp로 지수함수를 적용하고 -1을 해주어야 로그를 취했던 순서를 복원해줌
-> np.exmp1은 지수함수를 적용하고 -1을 해주는 순서로 되어있음
* count == np.expm1(np.log1p()) 같은 값
```fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(12,3))
# count - kdeplot
sns.kdeplot(train["count"], ax=axes[0])
# count log1p - kdeplot
sns.kdeplot(train["count_log1p"], ax=axes[1])
# count, log1p, expm1
sns.kdeplot(train["count_expm1"], ax=axes[2])
train[['count', 'count_log1p', 'count_expm1']].describe()
❓왜 count에 log를 취하고 다시 지수함수로 복원했을까❓
❗log값으로 예측하고 예측값을 복원하기 위해❗
✒️실무에서는 보통 비즈니스 평가지표를 더 많이 사용. 경진대회나 실습에서 사용하는 평가지표는 모델의 성능을 측정해서 객관화 해보기 위해 사용. 모델을 만드는 목적은 비즈니스 문제 해결을 위해서 이다. 그 모델의 목적이 DAU를 올리는 것이라면 DAU를 측정하고 매출을 늘리고 싶다면 매출액이 늘어났는지, 구매자수가 늘어났는지 등을 평가.
from sklearn.model_selection import RandomizedSearchCV
param_distributions= {'max_depth':np.random.randint(3,100,10),
'max_features':np.random.uniform(0,1,10)}
reg = RandomizedSearchCV(model,
param_distributions= param_distributions,
scoring="neg_root_mean_squared_error",
n_iter=10, cv=5, n_jobs=-1,
verbose=2, random_state=42)
reg.fit(X_train, y_train)
rmsle = abs(reg.best_score)
-> score : neg_root_mean_squared_error 설정
-> score가 음수로 나옴
(음수이기 때문에 절댓값이 작을수록 좋은 성능을 내는 모델)
🔷RMSE와 RMSLE 값이 동일
-> label인 count값에 로그를 취해주었기 때문
-> BUT best_modle로 다시 cross_val_predict를 하면서 cv를 다시 나눠 학습하고 예측해서 점수가 다르게 나올 수 있음
💥 모델 학습과정에서 log1p를 적용해줬기 때문에 답안을 제출할 때에는 expm1을 적용시키고 제출해야 함
df_submit['count']=np.expm1(y_predict)
✒️ 캐글 내 권장 튜토리얼을 따라해 보면 예습과 복습에 도움이 된다~!!!!
: 데이터에 대한 지식을 바탕으로 특성(feature)을 생성, 변경 삭제하는 등 조작하여 사용하기 더 유용한 형태로 바꾸는 것을 의미
feature engineering 분류
1. 특성 선택
: 도메인(해당분야) 전문가의 지식이나 특성의 중요도에 따라 일부 특성을 버리거나 선택
2. 특성 추출
: 특성을 버리거나 선택하는 것이 아니라 특성들의 조합으로 새로운 특성 생성
3. 범위 변환
: 변수의 분포가 편향되어 이상치가 많이 존재하는 등의 변수의 특성이 잘 드러나지 않아 활용하기 어려울 경우 변수의 범위 바꿔주기
-> 분포 편향: 왜도가 높거나 정규분포와 거리가 멀다, 데이터가 한 쪽으로 치우쳐 있다 를 의미
4. 변형
: 기존에 존재하는 변수의 성질을 이용해 새로운 변수 생성
5. 범주화
: 연속형 변수 -> 범주형 변수 변환
6. 숫자화
: 범주형 변수 -> 연속형 변수 변환
데이터 해석
-> 2000년대에 지어진 집이 많다
-> MiscVal 데이터가 0에 쏠려있다
-> 수치가 0인 항목이 많다
: Feature가 적절한 값을 가지지 못하고 무의미한 값을 갖는 경우
: 데이터 수집 과정에서 누락되거나 원래 존재할 수 없는 데이턴데 구조상 생겼을 수 있음
train_null = train.isnull().sum() train_null[train_null!=0]
train.isnull().sum().sort_values(ascending=False)[:20]
test_null = test.isnull().sum() test_null[test_null>0].sort_values(ascending=False)
train_na_mean = train.isnull().mean()
pd.concat([train_null, train_na_mean], axis=1).loc[train_sum.index]
: feature에서 일반적인 값 분포에서 벗어나는 경우
: 데이터 수집과정이나 조작 과정에서 잘못 생겼을 수도 있고 예회적으로 수치가 뛰어오를수도 있고
-> 데이터의 해석이나 학습을 방해함
(이상치로 인한 과대적합)
🔷이상치 찾는 방법
1. 값의 범위를 지정하여 범위에서 벗어나는 값을 찾기
2. 데이터를 시각화하여 그래프에서 눈에 띄는 값을 찾기
-> 대상 데이터의 "saleprice"(정답값)값을 산점도로 그려서 이상치 범위를 정할 수 있음
: numercie feature에서 대부분 값이 갖는 범위에서 벗어난 값 = 이상치
: categorical feature에서 빈도가 낮은 값 = 희소값
-> 데이터를 수집하다보면 자연스럽게 비율이 높고 낮은 값이 생김
-> 희소한 feature가 데이터 해석을 어렵게 하고 머신 러닝 성능을 낮출 수 있음
# object type nunique train.select_dtypes(include="object").nunique().nlargest(10)
# Neighborhood - value_counts train["Neighborhood"].value_counts()
# countplot plt.figure(figsize=(20,5)) sns.countplot(data=train, x="Neighborhood", order=train["Neighborhood"].value_counts().index)
ncount = train["Neighborhood"].value_counts() ncount sns.countplot(data=train, y="Neighborhood", order=ncount.index)
11/9
🔷변수 스케일링(=feature scaling)
1. feature의 범위를 조정하여 정규화하는 것
2. 일반적으로 feature의 분산과 표준표차를 조정하여 정규분포 형태를 띄게 하는 것이 목표
-> 붉은 선이 정규분포 형태
🔷feature scaling이 중요한 이유
1. feature의 범위가 다르면 feature끼리 비교하기 어렵고 일부 머신러닝 모델에서는 제대로 작동하지 않음
2. 스케일링이 잘 되어있으면 서로 다른 변수까지 비교하는 것이 편리
3. 더 빨리 작동
4. 성능 상승
5. 일부 feature scaling은 이상치에 대한 강점이 있음
ex) robust scaling
✒️IQR: interquartile Range로, 상위 75%와 하위 25% 사이의 범위 의미
: 평균을 제거하고 데이터를 단위 분산에 맞게 조정
-> 표준 편차가 1이고 0을 중심으로 하는 표준 정규 분포를 갖도록 조정
-> 변수가 왜곡되거나 이상치가 있으면 좁은 범위의 관측치를 압축하여 예측력을 손상시킴
🔷 공식: z=(X-X.mean)/std
: feature를 지정된 범위로 확장하여 기능을 변환.
: 기본값은 [0,1]
-> 변수가 왜곡되거나 이상치가 있으면 좁은 범위의 관측치를 압축하여 예측력을 손상시킴
🔷 공식: X_scaled = (X-X.min)/(X.max-X.min)
: 중앙값을 제거하고 분위수 범위(기본값은 IQR)에 따라 데이터 크기 조정
-> 편향된 변수에 대한 변환 후 변수의 분산을 더 잘 보존
-> 이상치 제거에 효과적
🔷 공식: x_scaled = (X-X.median)/IQR
🔷 스케일링 방법 중에서 이상치에 가장 덜 민감한 스케일링 방법: Robust scaling
💥 1. StandardScaler
💥 2. MinMaxScaler
💥 3. RobustScaler
✒️ 변수 스케일링은 라이브러리에 저장되어있어 불러오기만 하면 됨!
💥 스케일링을 했을 때 분포가 변하지 않는다. x 축 값을 보면 min-max x값이 0~1 사이에 있고, std => 평균을 빼주고 표준편차로 나눠주고, roubust => 중간값으로 빼고 IQR로 나눠준 결과
💥 트리 알고리즘에서는 절대적인 값보다 상대적인 값에 영향을 받기 때문에 스케일링에 영향을 크게 받지 않지만 다른 알고리즘에서는 스케일링 값을 조정해 주면 모델의 성능이 좋아짐
ss.fit(train["SalePrice"])
-> 오류가 남
ss.fit(train[["SalePrice"]])
->데이터 프레임 형태로 수정해야함
(train[["SalePrice_ss"]]) = ss.fit(train[["SalePrice"]]).transform(train[["SalePrice"]]) (train[["SalePrice_ss"]])
standardscaling
ss = StandardScaler() (train[["SalePrice_ss"]]) = ss.fit(train[["SalePrice"]]).transform(train[["SalePrice"]]) (train[["SalePrice_ss"]]) (train[["SalePrice", "SalePrice_ss"]]).head(2)
minmaxscaler
mm = MinMaxScaler() (train[["SalePrice_mm"]]) = mm.fit(train[["SalePrice"]]).transform(train[["SalePrice"]]) (train[["SalePrice","SalePrice_mm"]]).head(2)
robustscaler
rs = RobustScaler() (train[["SalePrice_rs"]]) = rs.fit(train[["SalePrice"]]).transform(train[["SalePrice"]]) (train[["SalePrice", "SalePrice_rs"]]).head(2)
1. log함수는 x값이 커질수록 기울기 완만
2. x값이 작을수록 y의 변화량이 크고, x값이 클수록 y의 변화량은 작다
3. 작은 숫자들 사이의 차이는 벌어지고, 큰 숫자들 사이의 차이는 줄어듬
-> 이미 잘 분포되어 있는 feature의 경우에는 transformation이 불필요할 수 있지만 편향된 feature의 경우 log가 적용된 값은 원래 값에 비해서 더 고르게 분포되어있고
고르게 분포되어있다는 것은 y 값을 예측하는데 더 유용하다는 것을 의미
💥 그래서 정규분포로 만드는게 중요
🔷 같은 컬럼을 fit하고 변환을 시켜준다면 fit과 transfrom을 한 번에 fit_transform으로 쓸 수 있음
train['SalePrice_ss'] = ss.fit(train[['SalePrice']]).transform(train[['SalePrice']])
==
train['SalePrice_ss'] = ss.fit_transform(train[['SalePrice']])
1. standardScaling 특징
: 평균=0, std(표준편차)=1
✒️ Z-score라고도 불림
2. Min-max 특징
: 최솟값 0, 최댓값 1
3. robust 특징
: 중간값(중앙값, 50%, 2사분위수)가 0
: 이상치의 영향을 덜 받음
✒️ robust = 강건하다
❓ 왜 정규분포로 되어있으면 모델이 더 좋은 성능을 내는걸까?
1. 1.4구간보다 2.3구간이 상대적으로 더 중요
-> 예측하려는 값이 비교적 매우 작거나 매우 큰 값보단 중간값에 가까운 값일 확률이 높다
-> 중간값을 잘 예측하는 모델이 일반적인 예측 성능이 높은 모델
2. 정규분포로 고르게 분포된 값이 예측에 더 유리
-> 예측하려는 값의 분포는 모르지만 정규분포로 고르게 분포시키는 것이 다양한 예측값에 대해 대응 가능케 함
❗ if label(예측하려는 feature)이 편향되어있다면?
✒️ 간격으로 나누기 => 절대평가, 개수로 나누기=> 상대평가 예. 학점
train["SalePrice_log1p"] = np.log1p(train["SalePrice"]) train["SalePrice_ss_log1p"] = np.log1p(train["SalePrice_ss"]) train["SalePrice_log1p_ss"] = ss.fit_transform(train[["SalePrice_log1p"]])
train[["SalePrice_ss", "SalePrice_ss_log1p", "SalePrice_log1p", "SalePrice_log1p_ss"]].hist(bins=50, figsize=(12,4));
🔷 트리계열 모델을 사용한다면 일반 정규분포를 사용해도 무관
그런데 스케일값이 영향을 미치는 모델에서는 표준정규분포로 만들어 주면 더 나은 성능을 낼 수도 있음.
표준정규분포로 만들 때 값이 왜곡될 수도 있기 때문에 주의가 필요
꼭 이런 변환작업을 많이 해준다고 해서 모델의 성능이 좋아진다고 보장할 수 없음
❗상황에 맞는 변환방법을 사용하는 것을 추천❗
: numerical feature를 일정 기준으로 나누어 그룹화 하는 것
🔷 왜 필요할까?
1. 더 직관적임
-> 나이를 개인별로 분석하기 어려울 때 20대 30대 40대로 분석하면 경향이 뚜렷해지고 이해하기 쉬워짐
2. 데이터 분석과 머신러닝 모델에 유리
-> 유사한 예측 강도를 가진 유사한 속성을 그룹화하여 모델 성능을 개선하는데 도움
-> 과대적합 방지
🔷 종류
: 가능한 값의 범위를 동일한 너비의 N개의 bins로 나눠줌
-> 편향된 분포에 민감
ex) 절대평가, 히스토그램, pd.cut()
: 변수의 가능한 값 범위를 N개의 bins로 나눠줌. 각 bins는 동일한 양의 관측값을 전달
-> 알고리즘의 성능을 높이는데 도움
-> 임의의 binning은 대상과의 관계를 방해할 수 있음
ex) 상대평가, pd.qcut()
💥 한 분할 안에 몇 개가 들어가는지와 무관하게 전체 수치 범위에 대해 n 분할하는 것이 Equal width binning, 개수를 기준으로 n 분할하는 것이 Equal frequency binning
pd.cut(train["SalePrice"], bins=4, labels=[1,2,3,4]) pd.qcut(train["SalePrice"], q=4, labels=[1,2,3,4])
-> pd.qcut은 상대평가와 유사한 개념이기 때문에 pd.qcut으로 데이터를 분할하게 되면 비슷한 비율로 나눠줌(딱 떨어지진 않음)
💥 머신러닝에서 데이터를 분할해서 연속된 수치데이터 -> 이산화 해주는 이유는 머신러닝 알고리즘에 힌트를 줄 수 있고, 너무 세분화된 조건으로 오버피팅(과대적합)되지 않도록 도움을 줄 수 있음
: categorical feature을 numerical feature로 변환하는 과정
✒️ 최근 부스팅3대장 알고리즘 중에는 범주형 데이터를 알아서 처리해 주는 알고리즘도 있지만 사이킷런에서는 범주형 데이터를 피처로 사용하기 위해서는 별도의 변환작업이 필요
-> 부스팅3대장 => Xgboost, LightGBM, catBoost
: categorical feature의 고유값들을 임의의 숫자로 바꿔줌
: categorical feature를 다른 bool변수(0또는 1)로 대체하여 해당 관찰에 대해 특정 레이블이 참인지 여부를 나타냄
MSZoning - .cat.codes => ordinal encoding, 결과가 벡터(1차원형태)
-> 순서가 있는 명목형 데이터에 사용
ex) 기간의 1분기,2분기,3분기,4분기
train['MSZoning'].astype("category").cat.codes
get_dummies => one-hot-encoding, 결과가 matrix(2차원 행렬) 형태
: 순서가 없는 명목형 데이터에 사용
: 순서가 없거나 크기를 비교할 수 없는 데이터-범주형 데이터에도 사용
ex) 좋아하는 음료, 주택의 종류, 수업의 종류 등으로
pd.get_dummies(train['MSZoning'])
from sklearn.preprocessing import OrdinalEncoder
oe = OrdinalEncoder()
onc = OneHotEncoder()
MSZoning_oe = oe.fit_transform(train[["MSZoning"]])
MSZoning_enc = enc.fit_transform(train[['MSZoning']]).toarray()
pandas 의 get_dummies 를 사용해서 인코딩 하면 train, test 따로 인코딩
train 학습한 것을 기반으로 test 와 동일하게 피처를 생성해 주어야 하는데 이게 조금 다를 수 있음
판다스로 train, test 각각 인코딩 했다면 피처의 수, 종류가 다를 수 있음
그런데 학습, 예측을 할 때는 동일한 피처와 개수를 입력해 주어야 함
pandas 로 인코딩 한다면 set(train.columns) - (test.columns) 이런식으로 비교해서 맞춰주어야 함
train 에만 등장하는 피처가 있다면 test 에도 동일하게 만들어 줘야함
가장 간단한 것은 concat 을 사용하는 방법입니다. 없는 값은 nan 으로 들어가게 되고 다시 train, test 를 나눠주면 됨
=> 처음부터 concat 을 사용하고 나중에 나눠주면 이런 문제를 해결할 수 있음
=> 그런데 test 에만 등장하는 데이터를 피처로 사용하지 말라는 정책이 있을 때 이 방법은 규칙위반일수 있음
pandas로 인코딩 했을 때 단점: 사이킷런의 원핫인코딩은 train 데이터로만 학습해서 진행하기에 test에만 존재하는 데이터를 인코딩하지 않지만 판다스는 이 기능이 없어서 test셋과 train셋의 고유값을 비교해줘야 하는데, 현실에서 test 데이터는 존재하지 않기 때문에 권장하지 않음
🔷 사이킷런을 사용했을 때 train을 기준으로 fit 을 해주기 때문에 test 는 transform 만 해주면 된다
🔷 train 에는 없지만 test 에만 있는 값은 ohe 되지 않는다
🔷 fit 하는 기준은 꼭 train
-> test 는 미래의 데이터이기 때문에 어떤 데이터가 들어올지 모르기 때문
🔷 경진대회 데이터는 test 가 무엇인지 알고 있지만 일부 경진대회는 test 값을 반영해서 인코딩 하는 것을 금지
: 이미 존재하는 변수로부터 여러가지 방법을 이용해 새로운 변수를 만들어 내는 것
1. 사칙연산, 최대값, 최소값, 비율 등을 통해서 변수 생성
2. 시간, 지역별 구분, 비율 등으로 생성
❗ 파생변수 생성으로 데이터 해석이 더 편리해지고 머신러닝 성능이 올라갈 수는 있지만 역효과가 생길수도 있음(마구잡이로 만들면 속도도 느려지고 성능도 낮아짐)