Patrick Riley의 Practical Advice for Analysis of Large, Complex Data Sets을 번역했습니다. 오역이 있다면 알려주세요.
나는 Google 검색 로그를 다루는 데이터 과학 팀을 몇 년 간 이끌었다. 우리 팀은 복잡한 결과에 대해 이유를 찾고, 행동 로그를 통해 새로운 현상을 관측하고, 다른 사람이 수행한 분석을 검증하고, 사용자 행동 지표를 해석해달라는 요청을 종종 받았다. 어떤 팀원들은 수준 높은 데이터 분석을 쉽고 능숙하게 해낸다. 이런 엔지니어와 분석가들을 흔히 “주의 깊고” “꼼꼼하다고” 이야기한다. 이 형용사는 실제로 무얼 의미할까? 이 수식어를 얻으려면 어떤 행동을 해야 할까?
이 질문에 대한 대답을 문서로 정리한 다음 ‘훌륭한 데이터 분석’이라는 낙천적이고 단순한 제목으로 Google 사내에 공유했다. 놀랍게도 이 문서는 내가 지난 11년 동안 Google에서 수행한 그 어떤 일보다 더 많은 사람들이 관심을 갖고 읽었다. 주요 내용을 업데이트한 지 4년이 지났음에도 확인할 때마다 문서를 열어 본 Google 직원 숫자가 상당수였다.
왜 많은 이들이 그 긴 시간 동안 이 문서를 공유해왔을까? 가장 큰 이유를 꼽자면, 문서가 추상적이고 이상적인 내용이 아니라 실천 가능하고 구체적인 내용으로 알차게 구성되어 있기 때문일 것이다. 나는 본 문서를 통해 많은 엔지니어와 분석가가 좋은 습관을 받아들여 수준 높은 작업을 수행하게 된 것을 목격하였다. 그래서 지금 이 블로그 게시물을 통해 해당 문서의 내용을 공유하고 싶다.
조언을 크게 세 가지 영역으로 나누었다.
분포를 이야기할 때 요약 지표(평균, 중앙값, 표준 편차 등)를 주로 사용하지만 분포의 모습을 더욱 자세히 확인해 봐야 한다. 히스토그램, CDF, Q-Q 플롯 등과 같은 방법을 사용하면 분포가 다봉(multi-modal) 형태인지, 요약 방법론을 결정할 때 특히 중요한 이상치 계층이 존재하는지, 중요하고 흥미로운 데이터 특성을 직접 확인할 수 있다.
데이터의 이상치를 살펴봐야 한다. 이상치는 분석에서 더 근본적인 문제에 관한 탄광 속 카나리아 역할을 하곤 한다. 데이터를 제외시키거나 “특이” 범주로 묶어버려도 괜찮지만 데이터가 해당 범주에 속해야 하는 이유는 알아봐야 한다. 예를 들어 클릭률이 가장 낮은 검색어를 살펴보면 사용자 인터페이스 특정 요소에 대해 클릭이 제대로 집계되지 못한 채 빠져 있음을 알게 될 수 있다. 클릭률이 가장 높은 검색어를 살펴보면 계산하지 말아야 할 클릭까지 포함하고 있음을 알게 될 수 있다. 반면 일부 이상치는 제대로 설명하기 어려우므로 시간을 너무 낭비하지 않게 주의하자.
무엇보다도 무작위성이 존재하며 이것이 우리를 속일 수 있음을 알아야 한다. 조심하지 않으면 잡음 안에서 패턴을 찾았다고 생각할 수 있다. 산출한 모든 추정량에 대해서 그에 맞는 신뢰도를 함께 제시해야 한다. 경우에 따라 이 절차를 공식적으로 엄격하게 적용할 수 있고(추정량의 신뢰 구간, 결론에 대한 p-값 또는 베이즈 요인 분석 같은 기법을 통해) 느슨하게 적용할 수도 있다. 예를 들어 팀 동료가 월요일마다 개구리에 대한 검색이 몇 건 있는지 묻는다면 과거 월요일 며칠 치로 빠르게 분석해보고 “단순 숫자가 아닌 1 천에서 1천2백만 사이”라고 이야기해줄 수 있다.
새로운 분석 코드를 만들 때마다 기존 데이터의 관측치들을 살펴보고 당신이 짠 코드가 그것들을 어떻게 해석하는지 확인해야 한다. 이러한 작업 없이 실제로 동작하는 분석 코드를 만드는 건 코드의 복잡도 문제를 떠나 거의 불가능하다. 분석 작업은 기존 데이터를 잘 요약하여 표현하기 위해 많은 특성들을 제거한다. 복잡도를 갖는 다양한 관측치들을 보다 보면 요약한 내용이 일리 있는지 확신할 수 있다.
빈도가 가장 높은 경우만 치우쳐서 보지 않도록 층화 추출 기법으로 값 분포에 대한 좋은 표본을 얻을 수 있다.
예를 들어 클릭 시간을 계산하는 경우 분포 전체, 특히 극단값의 관측치를 살펴보라. 데이터를 살펴볼 수 있는 도구/시각화 방법이 없다면 먼저 그것들부터 준비해야 한다.
데이터를 조각으로 나눈다는 건 데이터를 여러 하위 집단으로 나눈 다음 각 집단의 지표를 살펴보는 걸 의미한다. 보통 웹 트래픽을 분석할 때 모바일 대 데스크톱, 브라우저, 로케일 등 몇 가지 기준에 따라 데이터를 쪼갠다. 각 하위 집단마다 내재된 현상이 다르게 나타나는 경우 데이터를 조각으로 나눠서 따로 봐야 한다. 데이터를 쪼개는 작업이 꼭 필요하지 않아도 여러 조각들을 살펴보며 일관성을 확인하다 보면 올바르게 분석하고 있다는 확신이 든다. 경우에 따라 특정 조각에 잘못된 데이터가 있거나 지금까지의 경험과 맞지 않거나 근본적으로 다른 형태의 데이터가 존재할 수 있다.
두 집단을 비교하기 위해 데이터를 쪼갤 때(실험/대조군뿐만 아니라 A와 B 시간대 비교할 경우에도) 혼합 비율 변화에 신경 써야 한다. 혼합 비율의 변화란 비교하려는 집단에 따라 데이터 조각의 크기가 서로 다른 경우이다. 심슨의 역설을 포함해 여러 혼선이 발생할 수 있다. 일반적으로 두 집단의 데이터 조각 크기가 동일하면 안전하게 비교, 분석할 수 있다.
대량의 데이터를 다루다 보면 통계적 유의성에만 초점을 두거나 데이터의 모든 세부 사항을 파악하려는 마음이 생길 수 있다. 그럴 때 스스로 물어봐야 한다. “X값이 Y값보다 0.1% 높다는 게 사실이어도 이게 중요할까?” 데이터 일부를 이해/범주화할 수 없는 경우 이러한 질문은 매우 중요하다. Google 로그 중 일부 사용자 에이전트의 문자열을 이해할 수 없는 경우 그게 10% 인지 0.1% 인지에 따라 해당 사례를 조사하는 비용이 크게 달라진다.
반대로 종종 소량의 데이터만 가지고 있을 때가 있다. 상당한 지표 차이가 통계적으로 유의하지 않을 수 있지만 “차이가 없다”라고 주장하는 것과는 또 다르다. 스스로 물어보자. “지표가 실제로 상당히 차이가 날 가능성은 얼마나 될까?”
데이터를 조각으로 나눌 때 거의 항상 사용해보는 방식이 시간 단위 분할이다.(보통 일자 기준으로 나누지만 다른 시간 단위도 유용할 수 있다.) 이는 시간의 흐름에 따라 시스템을 운영해나갈 때 내재된 데이터에 여러 교란이 발생하기 때문이다. 기능 초기 버전 또는 데이터 초기 수집분을 보통 주의 깊게 검사하지만 시간이 흐르면서 문제가 발생하는 경우 또한 드물지 않다.
이상치로 보이는 특정 일자 데이터를 그냥 폐기하라는 뜻이 아니다. 폐기하기 전 해당 데이터를 매개로 하여 특정 일자가 다르게 나타난 이유를 찾아라.
일자 단위의 데이터를 보면서 얻을 수 있는 또 다른 장점은 데이터의 일별 움직임을 알게 되면서 신뢰 구간 혹은 통계적 유의성에 관한 이야기까지 해볼 수 있다는 거다. 이는 보통 엄격하게 계산한 신뢰 구간을 대체할 수 없지만 변동폭이 클 때 일별 추세 그래프를 통해 그것이 통계적으로 유의미한지 대략 알 수 있다.
탐색적 데이터 분석에는 서로 연관된 3 단계가 있다고 생각한다.
1. 검증 또는 데이터 초기 분석: 데이터가 균질하고 올바르게 수집됐으며 데이터가 내가 생각한 대로 형태를 갖추고 있는가? 이는 종종 “새너티 확인”라는 이름으로 불린다. 예를 들어 어떤 기능에 대해 수동 테스트를 수행한 경우 해당 테스트의 로그를 봐보자. 모바일을 위한 기능임에도 로그에는 데스크톱으로 기록되지 않았나?
2. 설명: 데이터에 대한 객관적인 해석은 무엇인가? 예를 들어 “사용자는 일곱 단어로 된 검색어를 더 적게 질의하는가?”, “(클릭 시) 클릭한 페이지를 불러오는 시간이 1% 더 길다”와 “적은 비중의 사용자만이 다음 페이지 결과로 이동한다.” 등이다.
3. 평가: 주어진 설명을 통해 사용자, Google 또는 세상이 더 나아질 거라고 데이터가 이야기하는가? 예를 들어 ‘사용자가 더 빨리 결과를 찾는다’ 또는 ‘클릭 품질이 향상된다’ 등이다.
단계를 이렇게 구분 지으면 타인의 동의를 보다 쉽게 구할 수 있다. 설명은 데이터를 통해 모든 사람이 동의할 수 있는 것이어야 한다. 평가는 데이터에 의미와 가치를 부여하기 때문에 훨씬 더 논쟁의 소지가 있다. 설명과 평가를 구분 짓지 않으면 데이터를 보고 싶은 대로 해석할 가능성이 크다. 일반적으로 평가의 경우 다른 기능과 지표 간의 엄격한 비교를 통해 지표 기준 값 설정에 상당한 시간을 소요하기 때문에 훨씬 더 까다롭다.
윗 단계들은 차례대로 진행될 수 없다. 데이터를 탐색하며 앞뒤 단계로 이동할 수 있지만 현재 어느 단계에 있는지는 분명히 해야 한다.
데이터를 살펴보기 전에 실험과 데이터 수집 설정을 이해해야 한다. 실험을 수행하는 사람과 분석하는 사람 간의 정확한 의사소통은 분석에서 어려운 점 중 하나이다. 실험 프로토콜 또는 구성을 직접 살펴볼 수 있다면 그렇게 해야 한다. 만약 그렇게 할 수 없다면 설정에 대해 본인이 이해한 바를 적어보고 데이터 생성을 담당하는 사람에게 그게 맞는지 확인해야 한다.
비정상적이거나 잘못된 구성 또는 모수에 대한 제한(예: 특정 브라우저에만 유효한 데이터)이 존재할 수 있다. 여기서 발견한 중요한 사실들은 나중에 생각을 정립하고 확인할 때 큰 도움이 될 수 있다. 다음은 고려해야 할 사항이다.
정말 궁금한 질문에 대답하기 전에(예: “새롭게 만든 우리 멋진 기능을 사용했는가?”) 관심 있는 내용과는 관련 없지만 나중에 분석에 유용하거나 데이터에 존재하는 문제를 알려줄 수 있는 여러 사항들을 먼저 확인해봐야 한다. 사용자 수가 변했는가? 영향을 받은 검색어가 각 하위 그룹마다 올바른 숫자로 나타났는가? 오류 비율이 변했는가? 검진할 때 의사가 항상 키, 몸무게와 혈압을 확인하는 것처럼 잠재적인 문제를 파악하기 위해 데이터의 생체 신호를 늘 확인하라.
이는 “검증” 단계에서 가장 중요한 부분이다.
이건 변경하지 말아야 할 사항을 재확인하라는 이야기와 다소 비슷하다. 신규 기능과 데이터를 살펴보다 보면 해당 기능에 대해 새로운 지표를 특별히 만들어, 바꿔서 측정하고 싶은 마음이 생긴다. 그러나 곧 변경할 것으로 예상되더라도 표준 지표를 항상 먼저 살펴봐야 한다. 예를 들어 신규 UI 기능을 검색 페이지에 추가할 때 해당 UI 기능에 대해 지표를 특별히 만들어 측정하기 전에 결괏값 클릭처럼 표준 지표에 미치는 영향을 먼저 이해해야 한다. 이렇게 하는 이유는 표준 지표가 훨씬 더 검증된 값이고 정확하기 때문이다. 새롭게 맞춤으로 만든 지표값이 표준 지표 값과 논리적으로 맞지 않는다면 새로운 맞춤 지표가 잘못 만들어진 것일 수 있다.
새로운 현상을 분석하는 경우 기본적으로 분석할 내용을 똑같이 설정하고 다양한 접근 방식으로 측정해봐라. 그렇게 구한 여러 개의 측정값이 일치하는지 확인해봐라. 한 개 이상의 측정 방식을 사용하면 측정 또는 코드 로깅 상의 버그, 기존 데이터의 예상하지 못한 특성 또는 필터링의 주요 단계를 알 수 있다. 측정에 다른 원천 데이터를 사용할 수 있다면 더욱 좋다.
데이터를 조각으로 나누거나, 시간에 따라 일관성을 확인하는 작업은 재현성 검증의 일환으로 볼 수 있다. 관측된 현상이 중요하고 의미 있다면 다른 모집단의 사용자에게도, 다른 시간대에서도 동일하게 관측되어야 한다. 그러나 재현성이란 그 이상을 의미한다. 데이터를 활용해 모형을 만들었다면 해당 모형은 데이터의 미세한 값 변동에도 안정적이어야 한다. 다른 시간대 혹은 일부 무작위 추출한 표본에 대해 살펴보면 얼마나 모형을 신뢰할 수 있는지, 또 그것이 재현 가능한 성질의 것인지 알 수 있다. 재현해낼 수 없다면 데이터를 만든 내재 활동에 관한 근원적인 정보를 모형이 제대로 담지 못해서 그런 것일 수 있다.
종종 과거에 측정했던 것과 유사한 지표를 계산하게 된다. 다른 모집단의 사용자를 측정한 값이더라도 해당 지표를 과거에 보고한 지표값과 맞춰 봐야 한다. 예를 들어 특정 모집단의 검색량을 측정했는데 보통 통용되는 수치보다 훨씬 큰 값이 나왔다면 자세히 들여다봐야 한다. 구한 숫자가 해당 모집단에 한해 맞는 값일 수 있다. 그러나 이를 검증하기 위해서는 더 많은 노력을 기울여야 한다. 측정한 값이 동일 지표 맞는가? 해당 모집단이 기존과 다르다고 믿을만한 합리적인 근거가 있는가? 완벽히 납득되어야 하는 건 아니지만 숫자가 대략의 셈법에는 맞아야 한다. 그렇지 않다면 완전히 확신할 수 있을 때까지는 잘못 계산한 거라고 가정해라. 보통의 경우 깜짝 놀랄만한 데이터 수치는 새롭고 멋진 인사이트로 이어지지 않고 단순 오류로 판명 난다.
완전히 새로운 데이터를 수집해서 새로운 지표를 측정하려 한다면 그게 올바르게 산출된 데이터 수치인지 알 길이 없다. 새로운 종류의 데이터를 수집할 때 먼저 해당 데이터를 알려진 기능에 적용해봐야 한다. 예를 들어 사용자 만족도에 대한 새로운 지표가 있는 경우 우선 최적화한 기존 기능이 해당 만족도를 향상했다고 나오는지 확인해 봐야 한다. 이렇게 하면 새로운 측정 지표를 검증할 수 있다.
복잡한 문제의 경우 탐색적 데이터 분석을 보통 반복 진행한다. 그 과정을 통해 데이터의 이상치, 추세 또는 여타 특징들을 발견할 수 있다. 자연스럽게 해당 데이터를 설명하는 가설을 세우게 된다. 수립한 가설이 진실이라고 손쉽게 여기지 않는 게 중요하다. 해당 논리를 동의/반박할 증거(데이터 내부 또는 외부에서)를 찾아라. 예를 들어 카트만두의 휴일 또는 출시한 다른 기능으로 인해 이상치가 발생했다고 여겨지는 경우 해당 기능을 출시한 모집단에서만 이상치가 발생하는지 확인하라. 또는 변동의 규모가 출시 당시 예상한 정도와 부합하는지 확인하라.
훌륭한 데이터 분석 내용에는 어떤 이야기가 존재한다. 그 이야기가 올바른 것인지 확인하기 위해 이야기를 스스로 되새기고 해당 가설이 사실이라면 데이터에서 무얼 보아야 하는지 가늠한 다음 그것이 틀리지 않았는지 증거를 찾아라. 이를 수행하는 한 가지 방법은 다음처럼 자문해보는 것이다. “내가 만든 이야기를 검증/무효화하기 위해 어떤 실험을 수행해야 하는가?” 이러한 질문은 실험을 수행하지 않거나 할 수 없어도, 보유 데이터만으로 유효성을 확인하는 방법에 대해 좋은 아이디어를 줄 수 있다.
바람직한 건 수립한 가설과 후속 실험을 통해 특정 기능 또는 데이터로 학습한 내용을 뛰어넘는 아주 새로운 질문을 해볼 수 있다는 점이다. 이 과정을 통해 데이터를 단순히 이해하는 정도가 아닌, 향후 모든 분석을 이끌 새로운 지표와 기술을 도출해낼 수 있다.
탐색적 분석을 수행할 때는 분석 과정 전체를 최대한 많이 반복하도록 노력해야 한다. 일반적으로 데이터 수집, 처리, 모델링 등 여러 단계를 수행한다. 데이터 관련 초기 단계를 완벽하게 수행하기 위해서 시간을 너무 많이 쓰면 같은 시간 동안 더 많이 반복해볼 수 있는 기회를 놓치게 된다. 데이터를 보는 마지막 단계에서 방향을 바꿀만한 사실을 발견하는 경우도 많다. 그러므로 처음부터 완벽함에 초점을 두지 말고 모든 과정을 통해 합리적인 사실을 얻는 것에 초점을 맞춰야 한다. 주요한 필터링 단계와 파싱이 안되거나 이해할 수 없는 데이터 레코드는 일단 놔둔 채로 메모해놔라. 이러한 것들을 제대로 제거하기 위해 힘들게 노력하는 건 탐색적 분석 시작 단계에서 분명 시간 낭비이다.
분석을 진행하는 데는 항상 이유가 있다. 당신이 원하는 바를 질문 또는 가설 형태로 공들여 정리해두면 수집해야 할 데이터를 제대로 수집하고 있는지, 데이터 상 괴리가 발생하는지 판단하는데 큰 도움이 될 것이다. 물론 질문은 데이터를 보면서 변할 수 있고 변해야만 한다. 그러나 질문이 없는 분석은 방향성 없이 끝난다.
또한 써보고 싶은 기법이 있어서 적용할만한 문제만 찾는 상황은 피해야 한다. 어떤 질문에서 분석이 시작됐는지 재차 확인하면 그런 상황을 피하는 데 도움이 된다.
대부분의 대용량 데이터 분석은 여러 단계마다 데이터를 필터링하며 시작한다. 예를 들어 미국 사용자, 웹을 이용한 검색, 결과 클릭을 통한 검색의 건만 살펴보고 싶을 수 있다. 어떤 경우이든
다수의 흥미로운 지표는 기본적인 측정값에 대한 비율이다. 불행히도 통용되는 비율이 뭘 의미하는지 모호한 경우가 종종 있다. 예를 들어 검색 결과에 대한 사이트 클릭률 이야기가 나왔을 때 아래 두 정의 중 어떤 것을 의미하는가?
데이터 전문가가 아닌 사람들에게 분석과 업무 결과를 설명해줘야 하는 경우가 종종 있다. 그들이 데이터를 해석하고 결론을 바르게 도출하게끔 교육시키는 것도 당신이 맡은 업무의 일부이다. 이것은 신뢰구간을 이해시키는 일부터 해당 도메인에서 특정 측정값을 신뢰할 수 없는 이유, 모집단 편향 효과를 이해시키기 위해 "좋고" "나쁜" 변화를 야기하는 효과가 보통 얼마나 커야 하는지 얘기해주는 일까지 광범위하다.
이러한 과정은 데이터가 잘못 해석되거나 선택적으로 인용될 가능성이 높은 경우 특히나 중요하다. 고객이 요청한 수치만 전달하는 게 아니라 데이터의 맥락과 전체적인 그림을 알려줄 의무가 있다.
당신은 데이터를 다루면서 얻은 인사이트를 자신 있게 주장하는 챔피언인 동시에 회의론자가 되어야 한다. 당신이 바라던 대로 데이터에서 흥미로운 현상을 발견하는 경우가 있다. 흥미로운 현상을 발견하면 “이걸 멋지게 보여주려면 다른 어떤 데이터를 수집해야 할까?”와 “무엇이 이걸 의미 없는 결과로 만들 수 있을까?”를 동시에 자문해봐야 한다. 특히 특정 대답을 원하는 사람(예: “내가 만든 기능은 훌륭하다”)을 위해 분석을 수행하는 경우 오류를 피하기 위해서 회의론자가 되어야만 한다.
보고 싶은 결과가 따로 있는 고객과는 달리 숙련된 동료 검토자는 질적으로 다른 피드백을 제공하거나 새너티를 확인해줄 수 있다. 보고 있는 데이터에 관해 잘 알고 있는 동료가 가장 좋을 테지만 데이터를 일반적으로 분석해본 경험만 있다면 그 동료의 피드백은 매우 유용할 것이다. 앞의 내용에서 새너티 확인과 검증을 올바르게 할 수 있는 몇 가지 방법을 제안했다. 그러나 동료와 공유하는 것만큼 그 모든 일을 스스로 하게 만드는 좋은 방법은 없다. 동료는 분석의 여러 지점에서 유용하다. 동료는 일찍이 알고 있었던 문제, 측정해야 할 항목에 대한 제안과 해당 분야의 과거 연구들에 대해 알려줄 수 있다. 즉 동료는 이상한 점, 불일치 또는 다소 혼란스러운 내용에 대해 매우 잘 지적해줄 수 있다.
우리가 데이터에서 배울 수 있는 것에는 한계가 있다. 네이트 실버는 그의 저서 신호와 소음에서 한계가 확실한 사례들을 제시한다. 확실성의 한계를 인정해야만 더 나은 예측을 할 수 있다. 무지를 인정하는 건 큰 장점이지만 보통 그 장점을 바로 인정받을 수 있는 건 아니다. 당시에는 기분이 나쁠 수 있지만 장기적으로 데이터에 능통한 동료와 리더의 존경을 얻을 수 있다. 실수를 하고 나중에(또는 너무 늦게) 그걸 발견하게 될 경우 기분이 몹시 나쁠 것이다. 그러니 해당 실수에 대한 대책을 마련해서 공유한다면 당신에 대한 신뢰도가 높아질 것이다. 신뢰도는 데이터 과학자에게 있어 가장 중요한 덕목 중 하나이다.
Top 10 스타일처럼 조언 목록을 짧게 쓸 수 없었다.(세보지 않았는지? 여기에는 24개 항목이 있다). 위에 적힌 아이디어를 현실 문제에 적용해보면 당신의 도메인에서 가장 중요한 문제 해결 방식과 기술을 습득할 수 있을 것이다. 분석을 빠르고 정확하게 수행하는데 도움이 되는 도구와 조언들이 윗 목록에 있다. 배운 내용을 공유하며 더욱 훌륭한 데이터 과학자가 되길 바란다.
이 문서에 대해 인사이트를 제공한 모든 사람들에게 감사드리고 싶다. 특히 Diane Tang, Rehan Khan, Elizabeth Tucker, Amir Najmi, Hilary Hutchinson, Joel Darnauer, Dale Neal 그리고 Aner Ben-Artzi에게 말이다.