DS School 3~4주차: "같은 데이터, 다른 결과물"을 향해서
첫 2주동안 파이썬과 판다스의 기초와 데이터를 분석한다는 것이 어떤 식으로 이루어지는지에 대해 개괄적으로 알아봤다면, 3주차부터 4주차까지의 3회의 수업동안은 주어진 데이터로 좀 더 의미있는 데이터정보를 추출해내고, 좀 더 효과적으로 방대한 양의 데이터를 분석하는 방법들에 대해 알아보았다. 이 수업들을 통해 내가 변화한 부분이 있다면, 데이터과학을 배움에 있어서 수동적이었던 마인드가 보다 적극적으로 변한 데에 있을 것 같다. 5주간의 수업들을 수용하는 데에도 그 마인드가 큰 도움이 되었을 뿐더러, 앞으로 데이터과학을 스스로 더 공부해 나가는 데에 있어서도 이 마인드 자체가 질 좋은 자양분이 될 것이라고 믿고 있다.
엑셀을 통해서 1~2주차에 타이타닉을 통한 해상사고 생존율 분석에 도전해보았다. 그리고 파이썬의 기초, 주요 문법들과 판다스의 작동원리와 기초에 대해서 배웠다. 이제는 2주간 배운 지식들을 활용하여 파이썬의 판다스 패키지를 이용해 해상사고 생존율 분석을 하는 과정의 마무리 단계로, 같은 분석이라도 어떻게 하면 더욱 성과(즉 캐글 상에서는 평가점수)를 높일 수 있는지에 대해서 3주차와 4주차에 알아보았다. 더 나아가 수동작업 대신 머신러닝의 근본이되는 Decision Tree를 사용하여 같은 사례를 학습해 보았다.
먼저 참고용으로 타이타닉 데이터를 다시한번 첨부하고 시작하겠다.
데이터 분석을 할 때는 Column(열)에 대해서 친숙하지 않을 수가 없다. 주어진 train 데이터에서 어떤 열을 골라서 가설을 세워서 분석을 하냐에 따라서 점수 차이가 확연히 났다. 이 뿐만이 아니라 열과 열을 합쳐서 새로운 열을 만들거나 다른 방식으로 조합한 새로운 열로 분석하기도 하였다. 하지만 이것은 엑셀 단계에서도 충분히 할 수 있는 것. 보다 좋은 결과, 정확한 예측을 위해 몇 가지 고려해볼만한 방법들을 논해보고자 한다. 단순히 열을 추가하거나 수정하고, Raw한 데이터 자체를 놓고 고민하기보다, 빈 데이터를 채우는 방법에 대해 생각해본다거나 인코딩을 고려해보는 방법이 있다. 보다 유의적인 결과를 창출해 낼 수 있는 두가지에 대해서 지금부터 논의해보고자 한다.
먼저 빈 데이터를 채우는 것이다. 타이타닉 데이터의 경우 Train 데이터를 잘 살펴보면 가격이나 나이에 NaN이라고 표시되어 있거나 아예 비어있는 경우를 확인할 수 있다. 사람의 나이가 없어서? 가격이 없어서? 말이 안되는 소리다. 이런 경우는 실제 사용되는 데이터들에는 굉장히 흔한 케이스인데, 집계가 잘못 되었거나, 오류가 났거나, 그런 비일반적인 상황들로 인해 발생하는 경우이다. 그럼 이런 경우 어떻게 대처를 해야 유의적인 결과를 향해갈 수 있을까? 일단은 임의의 값을 넣어야만 하는데, 그 임의의 값이 설득력을 가질 수 있어야 할 것이다. 나이 자료를 예로 들자면, 빈 자료들은 평균나이값을 mean함수로 계산하여 입력하는 것이 무난하지만 보다 정확할 것이다. 이 때 유의해야할 사항은 Column을설정함에 있어 기존의 나이 Column을 사용하는 대신 항상 사본을 만들어 사용하는 것이 좋다는 것이다. 원본 Column을 수정하지 않고 사본을 사용하다보면 언젠가는 원본을 사용할 때 고쳐지지 않은 그대로를 사용함으로써 더 나은 결과를 도출할 수도 있을 것이다.
두번째로 인코딩을 사용하는 것도 항상 고려해야 할 중요한 방법 중 하나이다. 남녀 성별을 Male/Female로 표시하는 대신 Sex_Encode라는 새로운 Column을 만들고 0과 1값으로 표현하여 인코딩한다면, 컴퓨터 입장에서 훨씬 알아듣기 쉬울 것이다. 늘 말했듯이 이 또한 언어임을 항상 기억해야 한다. 사람 대 사람 간 가독성도 중요하지만, 보다 좋은 결과를 위해서는 코딩을 하는 우리들과 컴퓨터 간의 가독성도 중요한 법. 출발지를 인코딩할 때는 어떡해야 할까? 이 데이터에는 출발지가 세 곳으로 분류되어 있다. 그렇다고 이를 성별 인코딩 때처럼 한다면 C==0, S==1, Q==2 이렇게 넣을 수도 있는데, 이 경우 디씨젼 트리를 가동함에 있어 문제를 초래한다. 이렇게 하면 컴퓨터가 2*S==Q? 또는 S+S==Q? 이런식으로 이해할 수 있는 것이다. 즉, 전혀 산술적이지 않은 데이터를 산술적으로 이해하게 되어버리는 것이다. 이 경우에는 One-hot Encoding을 사용한다.
#C==[1,0,0]
#S==[0,1,0]
#Q==[0,0,1]
이런 식으로 세팅을 해 둔다. True==1, False==0으로 간주하는 점에 비추어 보았을 때 One-hot Encoding은 여러 가지 항목들 중 하나만 1(True)로 만드는것이다. 그래서 각각을 컴퓨터가 이해하기에도 쉬운 다른 변수들로 만들어 버리는 것이다. 컴퓨터는 이렇게 세팅한 경우,
#C==[True,False,False]
#S==[False,True,False]
#Q==[False,False,True] 로 받아들인다.
원핫인코딩까지 마친 후의 Column들이다. 좀전에 언급했듯이 모든 Column들을 수정할 때 새로운 사본 Column을 만들어서 진행하였고 이에 따라 보다 유의적인 Column들로 바뀌어 있음을 확인할 수 있다.
앞서서 Decision Tree에 대해서 설명 없이 언급만 계속 했었는데, 판다스의 세계에서는 Decision Tree를 활용하기 때문에 기초적인 머신러닝에 대한 이해만 수반된다면, 그 이후에 번잡한 가설-실험-확인의 과정을 Decision Tree로 간소화시킬 수 있다. 물론 나중에 데이터의 양이 많아지면 Decision Tree를 구동하는 데에 상당한 시간이 소요되지만, 지금 단계에서 사용하는 데이터는 기초적인 소량의 데이터이므로 그런 걱정은 일단 나중에 하는걸로..!
기초적인 머신러닝인 디씨젼 트리는 간단하게 얘기하면 Fit과 Predict의 단계로 구성된다. Fit단계는 가설-실험-확인의 단계를 학습시키는 과정이다. 이 때 알아두어야 할 개념이 2가지 있는데, feature와 label이다. Feature는 데이터 분석에 사용되는 Column들이고, 그를 이용해서 최종적으로 우리가 알고 싶어하는 목표값을 Label이라고 부른다. 즉 타이타닉 데이터에서는 성별, 출발지, 나이 등의 자료들이 feature가 되겠고, 생존여부가 label이 되는 것이다. Feature를 feature_names라는 임의의 리스트로 설정하여 이를 이용해 train 데이터와 test 데이터의 feature들을 각각 설정한 후 label_name="Survived"로 Label까지 설정을 해준다.
그 후 fit 기능을구동하기 위해서는 싸이킷 런(Scikit learn)이라는 기능을 활용해 pandas를 처음에 불러왔듯이 Decision Tree를 불러와야 한다. 이 때 Classifier의 성격으로 불러올수도 있고, Regressor의 성격으로 불러올수도 있는데 이는 통계적 지식과 관련된다. 저번 글과 이번 글에서 알아본 Titanic 데이터의 경우, 생존여부를 알아보기 위한 데이터이므로 Classification의 머신러닝에 속한다. 즉, 둘 중 하나(True or False)의 문제이거나 특정 카테고리에 속하는지 여부를 고르는 문제에 대해서는 Classification을 적용한다. 이 타이타닉 캐글 대회 외에도 Classification의 예로는 암환자예측(생존했는지/사망했는지), 스팸 필터링(Spam인지/Ham인지; 나는 스팸의 반대를 햄이라고 하는 것을 이를 통해 처음 알았다..! 나만 몰랐던 상식인 것일까..?), 상품 카테고리를 나누는 등이 있다. Classification의 범위 y는 0or1/ 의류or가전제품, 이런 식으로 표현할 수 있는데, 이를 Discrete(이산적)하다고 이야기한다.
반대로 Regression은 숫자의 높고 낮음을 판단하는 Label을 사용할 때 쓰인다. Regression 문제의 y값을 continuous(연속적)하다고 얘기하는데, 따라서 regression의 범위 y는 (-)무한대~무한대라고 보면 된다. 이의 예로는 비트코인 가격예측이나 부동산 가격 예측이 되겠다. 타이타닉 문제로 Classification 머신러닝에 대해서 알아보았으니 그 이후에는 Regression 머신러닝을 적용할 수 있는 Bike Sharing Demand 사례를 이용해서 학습하게 되었다.
혹여나 이 글을 통해 Titanic 사례이든 Bike Demand 사례이든 캐글 사례들을 통해 파이썬을 학습을 하고자 하는 이들을 위해 이 둘의 특성에 대해서 간단히 언급하고자 한다. Titanic data는 python을 배우기에는 굉장히 좋다. 특정 데이터 중에 NaN(실제 데이터를 받아보면 에러가 났거나, 집계가 안되었거나, 기타 등등의 이유들로 데이터가 비어있는 자료들을 받는 경우들이 대부분이다.)이 있어 빈 데이터를 어떻게 채울지에 대해서 고민해볼 수 있고, 성별이나 출발지 등을 인코딩하는 것이 더 좋아 인코딩 공부를 할 수도 있기 때문이다. 그러나 단점이 있다면 통계, 머신러닝에 활용하기에는 부적절하다. 애초에 Train data 수 자체가 많지 않기 때문이다.
이에 반해 Bike Sharing Demand 사례는 NaN도 없고 encoding 할 필요도 없고 해서 파이썬을 배우기에는 적합하지 않을 수 있겠지만, 다루기가 편하고 데이터가 상대적으로 넉넉해서 타이타닉보다는 통계적 유의성이 더 높으므로 머신러닝을 학습하기에도 상당한 도움이 된다.
https://www.kaggle.com/c/bike-sharing-demand
Bike Sharing Demand는 연월일시분초의 날짜/시간 정보와 기온, 체감온도, 습도, 풍속, 휴일여부 등의 데이터를 활용하여 자전거 대여수를 예측하는 사례이다. 마찬가지로 참고용으로 Train 데이터와 Test 데이터를 첨부한다.
이 또한 스스로 생각하기에 어떤 요소들이 자전거 대여수에 반영될지를 고민해보는 것이 첫번째 단계이지만, 판다스에서 디씨젼트리를 활용하여 예측모델을 만들 때, 보다 좋은 결과를 단 1%라도 낼 수 있을 방법에 대해서 타이타닉 사례처럼 이 Bike Sharing Demand 사례를 통해서도 학습하였다. 따라해볼 분들을 위해 몇 가지 팁(?), 생각해볼 점들을 제시하자면
1. 일단 Datetime에 주목할 필요가 있다. Raw한 데이터 그자체에서는 Datetime이 연-월-일-시-분-초 단위로 나와 있는데, 이를 각각의 단위로 쪼개 본다면, 그 중 어떤 시간 데이터가 유의적이고 어떤 시간 데이터가 무의미한지, 심지어 결과에 방해가 될지까지 알 수 있을 것이다.
2. windspeed에도 주목할 필요가 있다. 풍속이 0으로 나타나는 것이 정말 그 시간에 바람이 1도 안 불었던 상황인 것인지, 혹은 Titanic Data에서 빈 데이터에 임의의 값을 넣었던 것처럼, 측정상의 오류 등의 이유들로 임의의 값을 넣어야 하는 상황인지를 판단할 필요가 있다. 더 나아가 0으로 나타난 값들에 임의의 값을 넣을 때, 그 값을 어떻게 설정할 지 또한 고민해 보는 것이 좋다. 단순히 전체 평균으로 하기보다는 구간별 평균값을 제시하는 것이 좋을 것이고, 0값으로 나타나기 직전값과 직후값을 비교하여 설정하는 것도 좋은 방법이라고 보여진다. 다양하게 생각해보는 것이 좋다.
3. Temp 컬럼 또한 단순히 그 시점의 절대적인 기온을 놓고 분석하기보다 전후 기온과 비교하여 그 증감을 새로운 컬럼으로 제시하는 등의 방법을 사용해볼 수 있다.
4. Titanic에서 One-Hot-Encoding을 했던 것을 여기에서도 사용할 수 있다. 날짜 중에 제시되지 않은 요일 데이터를 새로운 컬럼으로 형성하여 one-hot-encoding까지 시도해 볼 수도 있고, Season이나 Weather가 1부터 4까지의 숫자로 표현되므로, 산술적인 오류를 방지하기 위해 one-hot-encoding 해볼 수도 있다.
위의 4가지 케이스들은 모두 내가 시도해본 방식들이다. 이 중에서는 결과값을 더 좋게 만들어주는 경우도 있고, 결과값을 안 좋게 만들어주는 경우도 있다. 변화를 반영하기 전과 비교하여 거의 달라지지 않는 경우도 있다. 중요한 것은 시도와 우선순위 설정이다. 일단 내가 생각하기에 효과적인 분석이 될 것 같다고 생각이 들면, 바로 시도하는 자세가 필요하다. 단, 실제로 다량의 데이터를 분석할 때 아무리 싸이킷런으로 디씨젼트리를 실행시키더라도, 워낙 데이터 양이 많다보니 구동되는 시간이 굉장히 오래 걸리는 경우가 허다하다. 이럴 때는 한번 디씨젼트리 결과값을 찾는데에 20~30분, 많게는 몇 시간이 걸리기도 한다. 퇴근길에 디씨젼트리를 돌려 놓고 다음날 출근해서 결과값을 확인해야 하는 상황도 다분히 많이 생기는 것이다. (사실 현업에서 활동할 때는 몇시간이 문제가 아니라 몇일이 걸리는 경우도 있다고 한다. 그것이 디씨젼트리를 이용한 머신러닝의 한계이기도 한다. 딥러닝이 주목받고 있는 이유이기도 하고 말이다.) 그러므로 여러가지 안들이 나왔을 때 우선순위를 스스로 정해두는 것이 굉장히 중요하다. 캐글의 Bike Sharing Demand 사례는 물론 Titanic 사례보다는 데이터의 양이 많지만 그래도 실제 사례들에 비하면 한참 적은 양이므로 시행착오법이 가능하다지만, '넣고 돌려보고 넣고 돌려보고'의 방식이 실제 사례들에는 적용하기 힘든 이상, 어떤 방식을 취했을 때 가장 결과값이 정확하게 나올지(캐글시스템으로 치면, 어떤 방식을 취했을 때 캐글 점수가 가장 높게 나올지)에 대해서 고민해보고 그 우선순위에 맞게 적용하여야 한다.
참고로 Kaggle은 한 ID당 한 competetion을 하루에 submit할 수 있는 횟수가 10회로 제한이 되어 있다. 아이디를 여러개 만드는 방식은 너무나도 무식한 방식일 것이다. 이를 위해, KAGGLE 시스템과 완벽하게 딱 들어맞지는 않지만, 내가 하고 있는 머신러닝이 지금 찾고자 하는 Lable에 근접하게 가고 있는지를 판다스 자체에서 확인할 수 있는 방식이 있다. 자체적인 정확도 점수 공식을 만들어서 시험해본다고 하면 좀 더 쉽게 다가올 것이다. 이에 대해서는 다음 글에서 데이터 시각화 툴과 함께 다루어보도록 하겠다.