✅MAE(평균절대오차)
오차값의 describe 값 중 mean 값
mae = abs(y_train - y_predict).mean()
-> 음수 값을 정확히 하기 위해 오차에 절대값을 적용해주어야 함 (abs)
✅MAPE
(실제값 - 예측값/ 실제값)의 절대값에 대한 평균
실제값에 대비해서 오차값의 비율
mape = abs(y_train - y_predict)/y_train.mean()
-> MAPE 값은 작을수록 잘 예측한 것.
✒️r2 score = 사용했던 측정 공식 중에 1에 가까울 수록 좋은 모델이고, 0에 가까울수록 잘못 예측한 측정 공식
✅MSE(Mean Squared Error)
실제값 - 예측값의 차이의 제곱의 평균
-> 오차에 제곱을 하는 이유:
절대값을 씌워주는 것과 마찬가지로 부호 무시 가능
mse = ((y_train - y_predict)**2).mean() mse
✒️pow()도 제곱이랑 같은 역할
✅RMSE(root mean squared error)
mae에 루트 씌우기
np.sqrt(mse) ((np.square(y_train-y_predict)).mean())**0.5
🔷1)
100억을 110억으로 예측
100억을 105억으로 예측
-> MAE, MSE 모두 2번이 잘 예측
🔷2)
5분 걸린다고 예측했는데 10분 걸림
25분 걸린다고 예측했는데 50분 걸림
-> MAE, MSE 모두 2번이 잘 예측
=> MSE, MAE 등은 회귀모델이 잘 예측했는지 파악하기 위한 지표
🔷1. 분류
분류의 경우에는 잘 정답값과 비교해서 많이 맞으면 잘 예측했다라고 말할 수 O -> accuracy
🔷2. 회귀
회귀는 잘 예측했다라고 말하기에는 정답값에 딱 맞출 X
오차가 적을수록 모델이 잘 예측했다 라는 가정을 하고 그 오차를 MAE, MSE, RMSE와 같은 지표들로 검증
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12,2))
sns.countplot(x=y_train, ax=axes[0]).set_title("train")
sns.countplot(x=y_test, ax=axes[1]).set_title("test")
✅1. GridSearch CV
: 모델의 하이퍼 파라미터 후보군들을 완전 탐색하여 하이퍼 파라미터를 검색
-> 정해진 구간에서만 값을 탐색
장점: 검증하고 싶은 하이퍼 파라미터의 수치를 지정하면 수치별 조합을 모두 검증하여 최적의 파라미터 검색의 정확도 향상
단점: 후보군의 개수가 많으면 많을수록 기하급수적으로 찾는 시간은 오래 걸리며 후보군들을 정확히 설정 필요
✅2. RandomizedSearchCV
: 정해진 횟수 안에서 정의된 하이퍼 파라미터의 후보군들로부터의 조합을 잰덤하게 샘플링하여 최소의 오차를 갖는 모델의 하이퍼 파라미터를 검색
-> 지정된 구간 외에 최적값이 있을 때 그리드 서치로 찾지 못하는 단점을 보완하여 랜덤한 값들을 지정해 그 중 가장 좋은 성능을 찾아내는 파라미터 찾음
정점: 무작위로 값을 선정하고 그 조합을 검증하므로 빠른 속도로 최적의 파라미터 조합을 검색
단점: 후보군을 신중히 결정해야하며, 랜덤한 조합들 중 최적의 하이퍼 파라미터를 찾는다는 보장X, 횟수를 늘려주면 시간도 비례하게 증가
-> gridsearchCV: 조합의 수 만큼 실행
-> randomizedsearchCV: k-fold 수(n_iter 수)만큼 실행
X_train = train[feature_names].fillna(0)
print(X_train.shape)
print("결측치 합계 : ", X_train.isnull().sum().sum())
X_test = test[feature_names].fillna(0)
print(X_test.shape)
print("결측치 합계 : ", X_test.isnull().sum().sum())
로그(log)는 지수 함수의 역함수
어떤 수를 나타내기 위해 고정된 밑을 몇 번 곱하여야 하는지 나타냄
0/2) * np.log2(1/2))
(2/2) * np.log2(2/2) + (0/2) * np.log2(1/2))
✅ 지니불순도와 엔트로피를 사용하는 목적
: 분류를 했을 때 True, False 로 완전히 나뉘지 않는데 이 때 값이 얼마나 섞여있는지 수치로 확인하기 위해서이고, 0에 가까울 수록 다른 값이 섞여있지 않은 상태
분류의 분할에 대한 품질을 평가하고 싶을 때 사용
✅ 이퍼 파라미터
criterion: 가지의 분할의 품질을 측정하는 기능
max_depth: 트리의 최대 깊이
min_samples_split:내부 노드를 분할하는 데 필요한 최소 샘플 수
min_samples_leaf: 리프 노드에 있어야 하는 최소 샘플 수
max_leaf_nodes: 리프 노드 숫자의 제한치
random_state: 추정기의 무작위성을 제어,실행했을 때 같은 결과가 나오도록 함
✅ 마무리
set(train["Title"].unique()) - set(test["Title"].unique())
set(test["Title"].unique()) - set(train["Title"].unique())
❓한쪽에만 있는 호칭은 어떻게 정리해야할까? -> 기타로 묶어서 처리
(결측치 처리도 가능하다❗
기타 호칭에 의미 부여를 하고 싶지 않을 때->범주형 데이터의 경우에는 결측치 처리를 하면 원핫인코딩을 했을 때 해당 값이 만들아지지 않음
❗하지만 특이한 값도 고려를 하기 원한다면 예외값이라고 만들어주면 예외값이라는 힌트를 머신러닝 알고리즘에 알려주는 효과가 있음)
=> 빈도수가 작은 값들은 머신러닝이 예측하는데 어려움. 따라서 빈도수가 적은 값에 의미를 살리고 싶으면 '기타'로 묶어줌
title_count = train["Title"].value_counts() title_not_etc = title_count[title_count >2].index title_not_etc
train["TitleEtc"] = train["Title"] train.loc[~train["Title"].isin(title_not_etc), "TitleEtc"] = "Etc"
train["TitleEtc"].value_counts()
=> 앞으로 어떤 값이 들어올지 모르기 때문에 기타의 정의를 빈도수 기준으로 설정함
✒️ 데이터 전처리를 할 때는 train을 기준으로
-> 현실 세계에서 test는 아직 모르기 때문에 train을 기준으로 전처리 해야함
✒️ train에만 등장하는 호칭은 학습을 해도 test에 없기 때문에 예측에 큰 도움이 되지 않음
train에만 등장하는 호칭을 피처로 만들어주게되면 피처의 개수가 늘어나는데, 불필요한 피처가 생기기도 하고
데이터의 크기도 커지기 때문에 학습 시간도 더 오래 걸림
너무 적게 등장하는 값을 피처로 만들었을 때 해당 값에 대한 오버피팅 문제도 있을 수 있음
train과 test의 피처 개수가 다르면 오류 발생
원핫 인코딩을 할 때 train, test 피처의 개수와 종류가 같은지 확인 필요
-> 예를 들어 train 피처는 수학인데 test 피처는 국어다 라고 하면 피처의 개수가 같더라도 다른 종류 값이기 때문에 제대로 학습할 수 없음.
#피처를 컬럼명으로 만들 때도 제대로 만들어지지 않음
✒️ esc + f: find & 코드 replace
train["Cabin_initial"] = train["Cabin"].astype(str).map(lambda x:x[:1].upper().strip()) test["Cabin_initial"] = test["Cabin"].astype(str).map(lambda x:x[:1].upper().strip()) print(train["Cabin_initial"].head(2)) print(test["Cabin_initial"].head(2))
train["Cabin_initial"] = train["Cabin"].fillna("N").str[0] train["Cabin_initial"].unique()
test["Cabin_initial"] = test["Cabin"].str[0] test["Cabin_initial"].fillna("N")
-> T객실은 한개만 있음 ▶️ 요금이 비슷한 객실로 묶어줌
sklearn 을 사용하게 되면 일단 학습을 해서 전처리를 하게 됨(어떤 피처가 있는지를 확인)
test에 없는 값이라도 test에 해당 피처를 생성
그런데 pandas 의 get_dummies 를 사용하면 각각 전처리를 하기 때문에 다른 값이 있다면 다른 컬럼으로 생성 됨
이 부분도 피처가 만들어지고 나서 다른 컬럼은 제외해 주는 방법도 있음
✒️ ordianl-Encoding: S,C,Q를 0,1,2로 만들 수 있음.
🔷 순서가 있는 데이터라면 ordianl-Encoding을 사용하는데 순서가 없는 데이터인데 이 방식을 사용하면 의도치 않은 연산이 될 수 있음
🔷 순서가 없는 데이터라면 One-Hot-Encoding 사용
🔷 pandas를 사용하는 이유는 수치데이터와 범주형 데이터를 함께 넣어주어도 알아서 인코딩을 구분해서 해줌
(수치형 데이터는 그대로 두고 범주형 데이터 대해서만 인코딩 함)
수치데이터는 그대로 두고 범주형(object, category) 타입에 대해서만 인코딩
ex) pd.get_dummies(train[["Fare", "Age", "Embarked", "Cabin_initial"]])
결측치가 있으면 머신러닝 알고리즘 내부에서 연산을 할 수 없기 때문에 오류가 발생
결측치가 있는 피러를 사용하려면 사이킷런에서는 꼭 결측치를 대체해줘야함
✒️현실세계에서 분석하는 데이터 함부로 결측치 채우는 건 꼭 주의
method : {'backfill', 'bfill', 'pad', 'ffill', None}
Method to use for filling holes in reindexed Series
pad / ffill: propagate last valid observation forward to next valid
backfill / bfill: use next valid observation to fill gap.
limit_direction : {{'forward', 'backward', 'both'}}
ex)
train["Age_ffill"] = train["Age"].fillna(method="ffill") train["Age_bfill"] = train["Age"].fillna(method="bfill") train["Age_interpolate"] = train["Age"].interpolate(method='linear', limit_direction='both') train[["Age", "Age_ffill", "Age_bfill", "Age_interpolate"]].tail()
✒️결측치를 대체하는 방법에는 정답이 없다!!!!!!
1. 결측치 행을 그냥 제거하는 방법
2. 결측치를 중앙값으로 대체하는 방법
3. 보간법으로 결측치를 대체하는 방법(보간법도 종류가 다양)
: 랜덤 포레스트를 사용해도 되지만 cross validation을 하게 되면 여러번 학습하기 때문에 빠르게 학습시켜 결과를 보기 위해 DecisionTree를 사용
: bootstrap aggregating