https://lsjsj92.tistory.com/429
지난 3주차 포스팅 글입니다.
3주차에 이은 4주차입니다. (말이 n주차지.. 글이 밀려서 한 번에 올리네욯ㅎㅎㅎㅎ).
4주차에서도 저는 porto 데이터 셋을 가지고 다른 커널을 필사했습니다. 솔직히 타이타닉 다음으로 porto를 하는데 있어 너무 어려웠습니다. 그래서 이 데이터는 몇 번 더 해봐야겠네요 ㅠ
지난 커널에서는 모르는 내용이 너무 많았습니다. 왜 데이터를 그렇게 복잡하게 조합하고 그러는지 이해도 안되고요.
하지만 이 커널은 정말 명확하더라구요! 시작하겠습니다.
맨 위에 커널 주소가 나와있습니다. 저 주소로 진행했습니다.
먼저 필요한 라이브러리를 import 합니다. Numpy, pandas는 기본이고, sklearn에서 model_selection, StratifiedKFold, cross_val_score를 가져옵니다. 그리고 xgboost의 XGBClassifier와 lightgbm을 사용합니다. Stacking을 위해서 logisticregression을 이용할 것이구요.
그리고 데이터를 가져옵니다.
바로 전처리를 들어갑니다. 기본적인 데이터 구성은 지난 3주차에서 살펴봤기 때문에 바로 진행하겠습니다.
먼저 id_test값을 뽑아냅니다. Test[‘id’].values로 가져옵니다. 그리고 train의 target값을 가져옵니다. 이 값은 y값이 됩니다. 이후 필요 없는 컬럼을 바로 뽑아 내줍니다! train.drop([‘target’, ‘id’], axis=1)을 통해서 지워줍니다.
그리고 3주차에서 얘기를 잠깐 드렸었는데요. calc 변수들은 뭔가 target값과 연관성이 적어 보였습니다. 그래서 이 커널은
train.columns.str.startswith(‘ps_calc_’)을 통해서 ps_calc로 시작되는 컬럼을 지워줍니다.
여기서 startswith이라는 것은 처음 보네요! 그리고 endswith도 있습니다. 아무튼 이 컬럼들을 제거합니다.
그러면 ps_calc_로 시작되는 컬럼은 제거된 것을 볼 수 있습니다.
또한, 해당 데이터의 -1 값은 nan 값을 의미하기 때문에 train.replace(-1, np.nan)을 통해서 -1를 nan 값으로 바꿔줍니다.
자! 여기서 바로 entswith이 나오죠! Endswith를 통해서 cat으로 끝나는 컬럼을 찾아줍니다. 이렇게 배열을 간단하게 선언하면 편하죠. Cat_features = [a for a in train.columns if a.endswith(‘cat’)]식으로 하면 알아서 배열이 만들어집니다.
그리고 이 카테고리 데이터를 마치 one-hot-encoding 처럼 만들어줍니다. Pandas의 get_dummies를 이용해서 그렇게 할 수 있습니다.
만약 카테고리가 2개면 2개의 새로운 feature가 만들어집니다. 그리고 그 값을 temp에 저장했다가 pandas의 concat을 이용해서
pd.concat([train, temp], axis=1)식으로 합쳐줍니다. 그리고 기존의 colums은 삭제합니다. train.drop([column], axis=1)을 이용하면 되죠.
그리고 train과 test의 shape를 보면 똑같이 198개의 컬럼이 남습니다.
자 다음은 ensemble 클래스입니다. 뭔가 클래스가 나와서 겁나실 필요가 없습니다. 먼저 __init__부분입니다. 일종의 생성자입니다. n_splits는 StratifiedKFold에서 split 계수로 사용합니다. Stacker는 스태킹을 할 모델이구요. Base_model은 훈련을 진행할 base_model입니다.
다음으로 fit_predict 함수가 있습니다. 이 함수는 말 그래도 fit을 하고 predict하는 함수입니다. X, y, T는 각각 훈련 데이터와 T는 테스트 데이터입니다. 다음으로 folds를 통해 StratifiedKFold의 값을 받습니다. 여기 인자로는 아까 선언한 n_splits가 들어가구요 마지막에 .split을 통해 X, y를 나눠 줍니다.
S_train과 S_test가 나오는데요. 이 것들은 0값이 들어간 numpy array입니다. 하지만 안의 모양은 X.shape와 len(base_model)로 되어 있죠. 언제 쓰이냐면 X의 shape만큼 행 개수가 생성되고 model 계수만큼 열 개수가 생깁니다. 즉, model 마다 결과값을 넣을 것이지요. S_train에는 validation으로 측정한 예측 값이 들어갑니다. S_test에는 실제 테스트한 결과가 들어가죠.
이제 enumerate를 통해 model 만큼 반복문을 진행합니다. 그리고 S_test_i라는 것이 나오죠. 이거는 매 split마다 test의 결과를 임시로 저장할 공간입니다. 아래에서 어떻게 쓰이는지 알 수 있어요! 그 다음 folds만큼 enumerate를 도는데요. 이렇게 하면 train_idx와 test_idx가 나옵니다. 3번에 걸쳐서 모든 index가 출력되죠. 그리고 겹치지도 않게요! X_train 에는 train_idx, x_holdout은 test_idx를 넣어줍니다.
그리고 3주차에서 increase를 배웠는데요. 만약 increase를 삽입하고 싶으시면 여기 쯤에 넣으시면 됩니다. 다만 로직 부분이 조금 바뀌어야겠죠? ㅎㅎ 저는 이 커널에선 증가시키지는 않았습니다. (증가 시킨 것을 해봤는데요. 정확도는 크게 달라지는 것은 없었어요..... ㅠ)
그리고 fit을 통해서 모델을 훈련시켜줍니다. 훈련 다음에 y_pred에다가 clf.predict_proba값을 넣어줍니다. 이 값을 S_train[test_idx, i] = y_pred로 넣어주죠. S_train은 validation으로 생성된 예측 값이 들어가니까요. 그걸 i 번째 컬럼에 넣어줍니다. 그러면 test_idx에 각 값이 들어가겠죠?
S_test_i에다가는 [:, j] 즉 j 번째 컬럼에 clf.predict_proba(T)[:, 1] 값을 넣어줍니다. 왜 이렇게 하냐구요? 바로 밑에 나와있죠!
S_test에다가 모델에 대해서 fold만큼 진행한 S_test_i의 값들을 평균을 내서 S_test에다가 넣어줍니다!. 그러면 1번째 모델은 첫 번째 컬럼에 그 평균 값이 들어가게 되겠죠.
만약 모델이 3개면 각 모델에 대한 값이 평균으로 들어가 있을 겁니다.
그리고 아래를 보면 cross_val_score를 stacker를 이용해서 S_train,과 y를 넣어주고 그 result 값을 평균을 내서 보여줍니다. (cross_val_score 이니까요)
그리고 stacker에다가 S_train값과 y 값을 훈련시켜주고 그 stacker에 S_test를 predict_proba를 통해 예측을 한 뒤 res 값을 리턴 시켜주는 것으로 이 클래스는 끝이 납니다. 도대체 왜 이렇게 하는지는 뒤에서 값을 불러오는 것을 보면 아시게 될 것입니다.
자 이제 LGBMClassifier에다가 넣은 다양한 파라미터를 가진 3개의 변수를 선언해줍니다.
그리고 이 값들을 이용해서 각 LGBMClassifier model 변수를 만들어주죠!
그리고 아까 사용한 self.stacker는 바로 logisticregression이었습니다!
Stack = Ensembel(n_split=3, stacker = mog_model, base_model = (lgb_model, lgb_model2)) 이런 식으로 stack의 객체를 생성하고 stack.fit_predict(train, target_train, test)를 넣어줍니다!
그러면 각 모델을 돌고 ( i loop ), 각 split마다 돌고( j loop) 진행합니다.
S_train에다가는 각 모델 의 split 때마다 i index에 예측한 값을 넣어줍니다.
S_test_i는 split loop 마다 모델의 predict_proba를 j 열에다가 넣어주고 이 j 루프가 끝나면 S_test의 i 인덱스에 j 인덱스의 평균 값을
넣어주는 것이죠! 이 과정이 끝나게 되면 stacker(LogisticRegression)에 S_train을 훈련시킨 뒤 predict를 S_test로 해주고
그 예측한 값을 이제 y_pred 값에 돌려받는 것입니다. 꽤나 복잡하죠?
하지만 매우 강력합니다. 이렇게 하고 데이터 뽑아내고 제출 하니까
public은 위와 같이 0.28448이 나오지만 private score가 0.29가 나옵니다. 상위 5% 때에 속하는 점수입니다.
저도 이 부분이 아직 완벽하게 이해가 되지 않습니다. 지니 계수를 쓰지 않고도 어떻게 이렇게 나올 까.. 이런 것부터 시작해서 stacking하는 방법 등이 전체적으로 말이죠. 그래서 꾸준히 복습하고 있습니다. 한 번으로 되지 않기 때문이죠.
이것으로 4주차를 마칩니다.
5주차는 무엇으로 할 지 고민중입니다. 지금 quora competition에 참여하고 있고 점수 스코어가 50%인데 흠 이걸 진행할지 아니면 대회는 대회이고, 필사는 다른 것으로 진행할 지 고민이 많네요!
아무튼 다음 차에 뵙겠습니다.
'kaggle(캐글)' 카테고리의 다른 글
[6주차] 새벽 5시 캐글(kaggle) 필사하기 - home credit 데이터 편 - 2 (4) | 2019.02.10 |
---|---|
[5주차] 새벽 5시 캐글(kaggle) 필사하기 - home credit 데이터 편 - 1 (2) | 2019.02.03 |
[3주차] 새벽 5시 캐글(kaggle) 필사하기 - porto 데이터 편 - 1 (0) | 2019.01.26 |
캐글을 하면서 겪은 이슈들(kernel stopping, timeout error) (0) | 2019.01.24 |
[2주차] 새벽 5시 캐글(kaggle) 필사하기 - 타이타닉 편_2 (0) | 2019.01.16 |