사실 비율 보다는 샘플의 크기가 중요하지만 어쨌든 95%대 5%로는 A/B테스트는 문제를 만듭니다.
A/B테스트 흔히 온라인서비스에서는 버킷테스트라고 하는데 이 테스트에서 A와 B 두개의 샘플의 수가 서로 불균등하다고 하면 대부분의 통계학자들은 표정이 안좋아지며 심각하게 생각하지만 개발자들은 별것 아니라고 생각합니다.
이게 논란의 여지가 항상 있는 것이므로 조심스럽지만
A/B테스트는 통계학에서 나온 것이므로 통계학자들이 더 잘 알것이므로 이쪽을 더 신뢰하는 것이 맞습니다. 통계학자들은 경험과 이론을 통해 그게 왜 문제인지 설명하지만 개발자들은 그런 설명을 하지 않습니다.
개발자들은 근거를 말하지 않지만 통계학자들은 근거를 말합니다.
A/B 테스트, 버킷테스트는 여러개의 샘플에 각기 다른 처치(작용 또는 변화를 주는것)를 하고 그게 정말 효과가 있는 지 살펴보는 것이라는 것을 기억해야 합니다.
A/B 테스트는 샘플이 중요하다
A/B 테스트는 통계학에서 다루는 실험 운영 방법입니다. 실험계획법이라는 통계학 과목이 있습니다. 과목이 따로 있을 만큼 만만한 것이 아닙니다
통계학은 샘플을 매우 중요하게 생각합니다. 적어도 통계학파 중에 빈도주의자(Frequatist)들은 매우 중요하게 생각합니다. 그와 비교되는 다른 학파들도 있지만 이건 다음에 얘기하겠습니다.
샘플은 어떤 집합에서 일부를 떼어 낸 것을 말합니다.
통계학에서 샘플을 중요하게 생각하는 이유는 샘플을 통해서 원래 전체 데이터의 특성을 파악해야 하기 때문입니다. 샘플을 사용해서 원래 집합을 알아내려고 하는 이유는 대부분의 전체 데이터를 다 확인하는 것은 불가능하기 때문입니다.
“빅데이터 플랫폼도 있는데 전체데이터 확인을 왜 못하냐?” 라고 물어볼 수 있습니다. 잘못 이해한 것인데 거기서 말하는 전체데이터는 실제로 알고자 하는 사실을 얻어야 하는 대상의 전체가 아니기 때문입니다. 예를 들어서 어제까지 가입한 쇼핑몰 전체의 고객 데이터는 전체 데이터가 맞긴 하지만 쇼핑몰의 고객 전체는 아닙니다. 앞으로도 가입할 사람이 있을 것이고 탈퇴할 사람도 있을 것이기 때문입니다. 그런 관점에서 통계학에서 생각하는 전체 데이터를 얻는 것은 불가능하다고 할 수 있습니다.
어제까지 전체 고객 데이터는 통계학에서는 전체데이터가 아닌 그냥 매우 큰 샘플데이터입니다.
A/B테스트에서 A와 B는 각각 전체 모집단에 대한 샘플이라고 봅니다.
A/B테스트에서 샘플 수가 균등하지 않으면 통계 검정을 할 수 없는가?
그래서 A/B의 비율이 5:5로 균등하지 않으면 정확한 비교를 하지 못하는가? 라는 의문이 있을 것이다. 할 수는 있습니다. 다만 꽤 복잡한 방법을 써야 하고 정확하지 않은데다 선택한 검정 자체를 적용하는 것 자체가 맞는지 안맞는지는 확인하려고 하는 것은 노련하고 뛰어난 통계학자도 매우 어렵게 하는 것입니다.
간단하게 공식 몇 개 넣어서 계산하면 되는 것이 아닙니다.
그래서 이렇게 불균등한 샘플 비교를 최대한 피해야 합니다.
샘플 간의 성능 비교를 한다면 균등한 것이 낫다
균등하지 않은 샘플로 샘플의 불균형성을 극복하면서 테스트하는 것 보다 균형 샘플을 만들어서 테스트하는 것이 더 쉽고 돈도 더 적게 듭니다. 균등하지 않은 샘플로 서로를 비교하는 것은 일반적으로 실험계획이 잘못된 경우나 하지 못한 후시 테스트일 가능성이 높습니다.
A/B 테스트와 관련되었대고 하면 무조건 샘플 수를 맞추고 시작합니다.
불균등한 것이 뭐가 그리 문제인가?
샘플이라고해서 그렇게 거창한 것은 아닙니다. A그룹에서 추출한 숫자들, B그룹에서 추출한 숫자들을 비교하는 것인데 샘플이 균등하지 않으면 크게 달라질 수 있는 것이 파라미터(모수, parameter)인데 평균과 분산입니다. A/B테스트는 A와 B의 평균과 분산이 실험 후에 많이 차이가 나는지 아닌지를 보는 것입니다. 이때 샘플의 수 그러니까 숫자의 갯수가 많이지면 숫자의 갯수가 적을 때 보다 분산은 무조건 커집니다. 이게 자연적인 현상입니다. 그래서 샘플의 수가 50대 50으로 균등하지 않으면 샘플 수로 인해서 생길 수 있는 기본적인 분산의 차이를 보정하고 검정을 해야 하는데 보정이 매우 어렵고 보정을 해도 정확도가 떨어집니다.
실험결과를 잘못 해석하게 됩니다. 이런 결과로 결정을 하면 비즈니스에 큰 실패를 가져올 수 있습니다.
실험 자체를 잘못하는 것은 그 실험을 없었던 것으로 하면 되기 때문에 피해가 덜하지만 결과를 잘못해석하면 틀렸다는 것 자체를 의심하지 않기 때문에 큰 문제를 생깁니다.
한쪽을 언더샘플링(Under sampling)을 하면 어떤가?
크기(갯수)가 다른 두 샘플들이 있을 때 크기가 적은 샘플 수만큼을 크기가 큰 색플에서 도려내서 숫자를 맞추는 것이 언더샘플링(under sampling)이라는 방법입니다. 간단히 말하면 그냥 큰 쪽을 작은쪽의 크기 만큼 잘라서 맞추는 것입니다. 보통 자를 때 무작정 자르지 않고 랜덤으로 샘플링을 합니다. (확실하게 랜덤으로 분할 한 것과 같은 것으로 분할 할 수 있으면 랜덤 샘플링을 하지 않아도 됩니다. 이건 따로 설명하지요)
어쨌든 이러면 괜찮지 않은가? 라고 생각할 수 있는데 이것도 괜찮지 않습니다.
언더샘플링을 하는 순간 샘플의 모집단이 달라지게 됩니다. 샘플이 뽑힌 것의 자유도라는 것도 다르기 때문에 두 샘플은 비교하기 어렵게 됩니다. 부모가 낳은 형과 동생을 비교하다가 형과 동생의 아들인 조카를 비교하는 꼴인 것이다. 부트스트래핑을 쓰면 하게되면 이러 불균형에서 샘플링을 통해 문제를 해결할 수 있지만 역시 그 보다는 샘플 수를 맞추는게 편하고 낫습니다.
대부분의 버킷시스템은 샘플 수를 맞추도록 설계되어 있다
빅테크 회사들의 버킷시스템이 존재합니다. A/B테스트를 할 수 있도록 플랫폼이 갖춰줘 있고 샘플의 수 등을 수정할 수 있습니다. 저런 대형 기업들의 시스템에서도 기본으로 두 비교군의 샘플 수를 맞추도록 설계되어 있습니다. 다른 대기업들도 모두 마찬가지입니다. 그들은 왜 모두 그렇게 하는지 생각을 해보기로 합시다. 그냥 그렇게 하거나 단순한 전통이어서 그렇게 하는 걸이다 아닙니다. 그것이 통계적이고 과학적으로 실험의 결과를 오해석하지 않는 최선의 방법이기 때문입니다.
통계학자들이 무능하고 실력이 없으면서 복잡해 보이기 좋아하기 때문에 저렇게밖에 못한다고 생각할 수도 있지만.
버킷시스템에서는 언더샘플링이 가능하다
추가로 말하면 대부분의 버킷시스템은 사용자의 ID 또는 비식별ID를 비트연산을 통해 그룹을 나눠서 관리하도록 되어 있습니다.
따라서 많은 쪽의 비트 몇개를 무시해서 언더샘플링을 하면 샘플비교를 할 수 있습니다. 조금 복잡하니 자세한 것은 따로 설명하겠습니다.
참고
A/B테스트에 대해 포스트를 올린적이 있습니다. 시간이 있다면 자세한 내용은 그걸 참조하세요.
머신 러닝 분야에서 평가 지표는 모델이 얼마나 잘 동작하는지를 측정하는 데 중요한 역할을 합니다. 이 중에서도 다중 클래스 분류 문제에서는 클래스별 성능을 평가하는 데 있어서 다양한 방법들이 있습니다. 그 중에서도 대표적으로 사용되는 방법으로는 Macro-average와 Micro-average가 있습니다.
Macro-average 매크로 평균
Macro-average는 클래스별 성능 지표를 각각 계산한 후 평균을 내는 방식입니다. 이 방법은 클래스별 데이터 셋이 균등하게 분포되어 있을 때 적합합니다. 예를 들어, 10개의 클래스가 있는 다중 클래스 분류 문제에서 5개의 클래스는 100개의 데이터를 가지고 있고, 나머지 5개의 클래스는 10개의 데이터만 가지고 있다고 가정해 봅시다. 이 경우, Macro-average는 모든 클래스의 성능을 동일하게 취급하므로, 각 클래스의 데이터 수에 관계 없이 모든 클래스가 동일한 비중으로 반영됩니다.
Micro-average는 클래스별로 성능 지표를 계산하기 전에 모든 클래스를 하나의 클래스로 간주하고 전체적인 성능 지표를 계산합니다. 이 방법은 클래스별 데이터 수가 다르더라도 모든 클래스의 성능을 동일하게 고려하므로, 클래스별 데이터 수가 차이가 많이 나는 문제에서 유용합니다.
다음은 Micro-average를 계산하는 과정입니다.
전체 데이터셋에서 TP, FP, FN, TN을 계산합니다.
Precision, Recall, F1-score 등 성능 지표를 전체 데이터셋에 대해 계산합니다.
이제 간단한 예시를 들어보겠습니다. 다음과 같은 3개의 클래스(0, 1, 2)가 있고, 각각의 클래스에 대해 TP, FP, FN, TN의 개수가 다음과 같다고 가정해 봅시다.
이처럼 average Micro-average는 다중 클래스 분류 문제에서 클래스별 성능을 평가하는 데 사용되는 방법 중 두 가지입니다. Macro-average는 클래스별 데이터셋이 균등하게 분포되어 있을 때 유용하며, Micro-average는 클래스별 데이터 수가 차이가 많이 나는 문제에서 유용합니다.
계산 법의 선택
어떤 방법을 선택할지는 데이터셋의 특성에 따라 달라질 수 있습니다.
예를 들어, 클래스별로 데이터 수가 크게 차이가 나지 않고 균등하게 분포된 경우에는 Macro-average를 사용하는 것이 적절할 수 있습니다.
반면에 클래스별로 데이터 수가 크게 차이가 나는 경우에는 Micro-average가 더 적절할 수 있습니다.
클래스별로 데이터가 균등한지 아닌지는 카이제곱검정을 하면 알 수 있습니다.
또한, Macro-average는 클래스별 성능을 독립적으로 평가하기 때문에, 각 클래스가 동등하게 중요한 경우에 적합합니다. 반면에 Micro-average는 모든 클래스가 동일한 중요도를 가지는 것이 아니라, 전체적인 성능이 중요한 경우에 적합합니다.
마지막으로, Macro-average와 Micro-average는 모델의 성능을 평가하기 위해 단독으로 사용하기 보다는, 다른 지표와 함께 사용하는 것이 좋습니다. 또한, 클래스별로 데이터 수가 매우 작거나 없는 경우에는 이를 해결하기 위해 Weighted average 방법을 사용하기도 합니다. 이는 클래스별 데이터 수를 고려하여 평균을 계산하는 방법으로, Macro-average와 Micro-average의 중간 형태라고 볼 수 있습니다. 이러한 방법들을 적절히 사용하여 다중 클래스 분류 모델의 성능을 정확하게 평가할 수 있습니다.
“팔 여러 개 달린 산적” “Multi Armed Bandit”은 슬롯머신의 별명인데 이 알고리즘은 이름처럼 “어떤 슬롯 머신의 팔을 당겨야 돈을 딸 수 있는가?” 와 같은 문제를 풀기위한 방법입니다.
엄밀한 의미의 강화학습에 포함되지 않지만 상당히 간단하고 쓸만하고 강화학습의 개념을 익히기 좋기 때문에 강화학습을 설명할 때 가장 먼저 설명하는 것이기도 합니다.
여러 대의 슬롯 머신이 있고 이 슬롯 머신 중 어떤 것의 레버를 당겨야 돈을 딸 수 있는가를 푸는 문제입니다. 한 번에 1대의 슬롯머신의 레버를 당기고 계속해서 반복합니다.
이 문제의 전제 조건이 있는데 한 번에 하나의 슬롯머신의 팔을 당길 수 있다는 것입니다.
그래서 동시에 모든 슬롯머신의 팔을 당겨서 그리고 여러번 당겨서 어떤 슬롯머신이 돈을 딸 학률이 높은지 알아낼 수 없습니다.
그래서 한 번에 하나씩만 선택해서 돈을 최대한 많이 따는 것이 이 문제의 푸는 목적입니다.
복잡한 공식은 여기에 안 적겠습니다. 구글에서 찾아보시면 수식과 코드가 다 있습니다.
첫번째 방법. Greedy 욕심쟁이
모든 슬롯머신에 순차적으로 한 번씩 팔을 내려봅니다. 그래서 돈을 못땄다면 다시 한 번씩 다 팔을 내려봅니다.
몇번을 수행한 후에 딴 돈이 가장 많은 슬롯머신에게 계속해서 몰빵합니다.
이게 그리디(Greedy, 탐욕스러운) 방식입니다. 단순하면서도 조금 무식한 방법입니다.
두번째 방법. epsilon
Greedy 방법을 사용하되 무작정 사용하지 않고 랜덤으로 팔을 당길 확률을 정해놓습니다.
만약 50%의 확률로 랜덤을 고르겠다고 하면 한 번은 지금까지 가장 돈을 많이 딴 슬롯머신을 당기고 한 번은 랜덤으로 아무것이나 고르는 방법입니다.
그나마 다른 것들에게 기회를 준다는 것 때문에 낫습니다.
epsilon이라는 이름은 랜덤으로 고를 확률값을 epsilon이라고 이름을 붙여서 부르기 때문입니다.
세번째 방법. UCB(Upper-Confidence-Bound)
위의 epsilon에서 약간의 공식을 주어서 랜덤 찬스가 왔을 때 무조건 랜덤으로 어떤 슬롯머신을 팔을 다기지 않고 덜 뽑혔던 슬롯머신에 가중치를 두어서 더 뽑아서 팔을 내려줍니다.
네번째 방법. Tompson sampling
톰슨 샘플링은 설명을 하면 조금 복잡해지는데 확률 분포 중 하나인 베타분포를 이용해서 확률이 가장 높은 것을 선택하는 것입니다.
베타분포 함수에 선택된 횟수와 돈을 딴 횟수를 입력하면 베타분포를 각각 구할 수 있고 그 베타분포를 확률 분포로 이용해서 값을 구하면 선택할 것을 찾을 수 있습니다.
저장된 데이터를 이용할 수 있는 장점이 있고 UCB 보다 성능이 조금 더 좋아서 온라인 추천 시스템에서 많이 이용되고 있습니다.
A/B 테스트와 MAB의 관계
A/B 테스트는 통계학의 실험계획법 중 하나 인데 2개 또는 2개 이상의 그룹을 동일한 수(최대한 비슷한 수) 만큼 각각 분할해서 한쪽에만 다른 처리를 해서 두 그룹의 차이를 보는 방법입니다
온라인에서는 흔히 버킷테스트라고 하는 방법입니다.
예를 들어 광고배너가 있는데 원래 배너는 테두리가 하얀색인데 테두리를 빨간색으로 바꿨을 때 사람들이 어떤 것을 클릭을 더 많이 하는지 알아 보고 싶을 때 같은 경우에 합니다.
A/B 테스트가 오랫동안 사용한 방법이기 때문에 잘 알려져 있지만 문제는 두 그룹을 방해받지 않게 불한하는 방법이 상당히 어렵고 두 그룹의 차이를 알아보는 방법이 데이터의 양상과 원래 데이터의 특성에 따라 여러가지 통계적인 방법을 써야하는 데 실수로 잘못된 방법으로 확인을 했다고 하더라도 그 실수를 알아내기 어렵다는 문제가 있습니다.
A/B 테스트를 하는 것은 많이 어렵지 않지만 A/B테스트의 결과를 해석하는 것은 매우 숙련된 통계학자가 필요하고 시간도 많이 걸립니다.
그래서 A/B 테스트를 하지 않고 각각 반응을 그대로 볼 수 있는 어떤 환경이 있다면 그 환경에서는 각각 매번의 결과에 따라서 결과가 좋은 것에 점수를 더 줘서 그것을 선택하게 만드는 방법을 쓰자는 것입니다.
그래서 MAB는 온라인 시스템의 추천시스템이나 평가에 굉장히 적합합니다.
광고시스템과 MAB
한 번에 5개의 제품을 동시에 보여지는 광고 이미지가 있다고 가정합니다.
사용자 별, 또는 사용자 그룹별로 어떤 제품에 더 관심을 가지는 지를 보고 클릭을 많이 하는 제품을 MAB에 의해서 더 많이 노출한다고 하겠습니다.
흔히 쓰는 방법이지만 이게 문제가 좀 있습니다.
선택할 제품이 매우 많은 경우에는 못합니다. 아마도 제품의 카테고리가 있고 그것들 중에 가장 잘 팔리는가 하는 전략을 취할 수 있지만 상식적으로 좋은 방법은 아닐 것입니다.
선호도는 계절성 효과, 요일 효과, 캠페인에 피로도에 따라 달라집니다. 슬롯머신 처럼 확률이 안변한다는 가정을 두기가 좀 어렵습니다. 변동이 너무 많습니다.
또 가중치를 변경하는 것 때문에 생기는 문제가 파생적으로 생기는데
쿠키로 인해 신규 및 재이용자의 분포에 영향을 미칩니다.
변화에 대한 적응이 느리기 때문에 인해 관성때문에 결과가 왜곡될 수 있습니다.
아주 단순한 경우에만 사용이 가능하며 복잡한 시스템으은 오히려 결과를 왜곡할 수 있습니다.
저렇게 선택한 것이 여전히 가장 좋은 방법 또는 그리 좋은 선택이 아닐 수도 있겠지만 그 자체를 확실하게 확인 못합니다. 이건 다른 알고리즘도 동일한 문제이긴 합니다만.
이런 것은 KNN (K-nearest-neighbor) 와 같은 기계학습 모델에 사용하는 것입니다. KNN은 판별 모델에서 사용할때 매우 강력한 알고리즘이지만 검색할 때 너무 느리고 자원을 많이 사용하는 문제로 인해서 실제로는 거의 사용을 못하는 알고리즘이지만 Faiss를 이용하면 이걸 쓸 수 있습니다.
Faiss 색인을 생성할 때 벡터의 차원을 지정해주고, Index의 유형도 결정을 해줘야 하는 것이 중요합니다. 검색은 입력한 k의 갯수만큼 리턴하게 되어 있고 벡터의 색인 번호와 거리를 리턴하게 되어 있늡니다.
색인 번호는 그냥 입력한 입력한 벡터의 순번입니다.
import faiss
import numpy as np
import random
# Euclidean distance 기반으로 가장 가까운 벡터를 찾는다.
# 랜덤으로 10차원 벡터를 10개 생성
vectors = [[random.uniform(0, 1) for _ in range(10)] for _ in range(10)]
# 10차원짜리 벡터를 검색하기 위한 Faiss index 생성
index = faiss.IndexFlatL2(10)
# Vector를 numpy array로 바꾸기
vectors = np.array(vectors).astype(np.float32)
# 아까 만든 10x10 벡터를 Faiss index에 넣기
index.add(vectors)
# query vector를 하나 만들기
query_vector = np.array([[random.uniform(0, 1) for x in range(10)]]).astype(np.float32)
print("query vector: {}".format(query_vector))
# 가장 가까운 것 10개 찾기
distances, indices = index.search(query_vector, 10)
# 결과룰 출력하자
idx = 0
for i in indices:
print("v{}: {}, distance={}".format(idx+1, vectors[i], distances[idx]))
idx += 1
Faiss로 코사인 유사도로 검색하기
유클리디안 거리(Euclidean Distance)로 가장 가까운 벡터를 찾으면 특정 차원의 양적 수치에 따라는 거리가 가깝다고 판별되는 편향의 문제가 있습니다. 이게 문제가 될 때가 있고 그렇지 않을 때가 있는데 이것은 문제의 도메인에 따라 다릅니다. 그러니까 문제가 주어진 환경에 따라 그때그때 다르다는 뜻입니다.
이런 문제를 피하는 방법은 유사도를 계산할 때 거리측정 방법을 유클리디안 거리를 사용하지 않고 코사인 유사도를 사용해서 벡터의 방향이 가까운 것을 찾는 것입니다. 보통 검색엔진들도 이 방법을 기본으로 사용합니다.
Faiss도 이걸 지원하는데 예제는 아래 코드를 보시면 되고 앞서 설명했던 유클리디안 거리 기반의 검색과 다른 점은 index를 생성할 때 타입을 다르게 생성해야 하고 벡터를 노말라이즈 해줘야 한다는 것입니다. 벡터가 이미 노말라이즈되어 있다면 안해도 됩니다.
import faiss
import numpy as np
import random
# 코사인 유사도 (Cosine Similarity) 를 이용해서 가장 가까운 벡터를 찾으려면 몇가지를 바꿔줘야 한다.
# 코사인 유사도 (Cosine Similarity) 를 사용하려면 벡터 내적으로 색인하는 index를 만들면 된다.
# 코사인 유사도를 계산하라면 벡터 내적을 필연적으로 계산해야 하기 때문이다.
# 랜덤으로 10차원 벡터를 10개 생성
vectors = [[random.uniform(0, 1) for _ in range(10)] for _ in range(100)]
# 10차원짜리 벡터를 검색하기 위한 Faiss index를 생성
# 생성할 때 Inner Product을 검색할 수 있는 index를 생성한다.
index = faiss.IndexFlatIP(10)
# 아래는 위와 동일하다.
# index = faiss.index_factory(300, "Flat", faiss.METRIC_INNER_PRODUCT)
# Vector를 numpy array로 바꾸기
vectors = np.array(vectors).astype(np.float32)
# vectors를 노말라이즈 해준다.
faiss.normalize_L2(vectors)
# 아까 만든 10x10 벡터를 Faiss index에 넣기
index.add(vectors)
# query vector를 하나 만들기
query_vector = np.array([[random.uniform(0, 1) for x in range(10)]]).astype(np.float32)
print("query vector: {}".format(query_vector))
# 가장 가까운 것 10개 찾기
distances, indices = index.search(query_vector, 50)
# 결과룰 출력하자.
idx = 0
for i in indices:
print("v{}: {}, distance={}".format(idx+1, vectors[i], distances[idx]))
idx += 1
먼저 스타벅스 매장 주소 데이터는 스타벅스 웹사이트에서 가져오면 되는데 csv나 엑셀 파일로 다운로드하게 지원하지 않으니 웹페이지의 내용물을 읽어서 파싱(parsing)해야 합니다.
이 작업은 웹 스크랩이라고 하는데 흔히 크롤이라고 부릅니다. 사실 원래 크롤과 스크랩은 서로 차이가 많습니다만 이 글에서는 그냥 널리 알려진 대로 크롤이라고 하겠습니다.
또 스타벅스 웹페이지는 지도상에 매장의 위치를 표시하기 위해서 Ajax로 데이터를 호출하는 방식을 사용하는데 이것의 방식을 알아내서 어떻게 데이터를 가져와야 하는지도 알고 있어야 합니다.
보통 크롬이나 파이어폭스의 개발자도구를 사용해서 알아내는데 연습과 방법을 익히는데 시간과 노력이 필요합니다. IT활용능력, 웹개발능력과 관련이 있는 것이라서 이것까지 설명하려면 설명이 길어지므로 이것을 알아내는 방법은 여기서는 생략합니다. 다음 기회에 다른 포스트에서 하겠습니다.
이 글에 소스코드를 넣어 두었으니 이미 완성된 코드를 참고 참고하세요.
인구데이터는 국가통계포털 웹사이트에서 가져오면 됩니다. csv나 excel로 다운로드 할 수 있게 지원하므로 매우 편합니다만 그래도 역시 데이터 정제, 정돈 작업은 좀 필요합니다.
인구데이터는 여기 말고도 받을 수 있는 곳이 더 있습니다. 더 편한곳이 있으면 그냥 거기를 이용하세요.
데이터를 크롤하는 법
R언어는 텍스트 파일을 파싱하거나 json 데이터를 처리하는 것이 조금 복잡한 편에 속합니다. R언어가 수치와 벡터 계산에 중점을 두기 때문에 이런 텍스트 처리에는 매우 약합니다.
하기가 까다롭다는 말입니다.
이런 것을 하려면 Python이나 Javascript가 더 나은 선택이지만
R언어로 이걸 하면 한 코드에서 데이터 크롤, 정제, 분석, 시각화까지 한 번에 할 수 있어 관리가 편하고 나중에 코드를 다시 볼 때 전체 흐름을 이해하기 편하다는 장점이 있습니다.
데이터랭글링이라는 것을 할 텐데 이런 작업은 tidyverse 패키지에 포함된 여러 패키지를 이용하는 것이 가장 세련되고 좋은 방법입니다.
그리고 시각화는 ggplot2를 사용하겠습니다.
결과
스타벅스 전체 매장수: 1658개
1658개로 나옵니다. 스타벅스는 모두 신세계에서 운영하는 직영점이라고 알려져 있고 관리가 웹사이트 관리가 잘 되고 있을 것이라고 생각돼서 이 수치는 맞을 것입니다.
수천개는 될 것 같지만 제 예상보다는 적습니다.
시도별 매장수
sido n
<chr> <int>
1 서울특별시 571
2 경기도 383
3 부산광역시 128
4 대구광역시 71
5 인천광역시 67
6 경상남도 66
7 광주광역시 59
8 대전광역시 59
9 경상북도 48
10 충청남도 36
11 울산광역시 29
12 전라북도 29
13 강원도 28
14 충청북도 26
15 전라남도 25
16 제주특별자치도 22
17 세종특별자치시 11
시도별 매장수는 역시 서울이 가장 많고 그 다음은 경기도, 부산 순입니다. 인구수가 많은 시도에 매장이 더 많은 것을 알 수 있습니다.
네 당연하죠. 물론 지역별로 로컬 카페나 다른 프렌차이즈, 브랜드의 커피매장이 더 인기가 있는 지역이 있을 수도 있으니 이 가설이 틀렸을 여지는 있습니다.
차트로 보며 시도별 매장수의 규모를 더 직관적으로 확인할 수 있는데 서울특별시와 경기도를 합치면 다른 시도를 다 합친 것 보다 더 많습니다.
우리나라 스타벅스 매장은 수도권에 크게 집중되어 있습니다.
구군별 매장수
sido gugun n sido_gugun
<chr> <chr> <int> <chr>
1 서울특별시 강남구 88 서울특별시 강남구
2 서울특별시 중구 52 서울특별시 중구
3 서울특별시 서초구 48 서울특별시 서초구
4 경기도 성남시 47 경기도 성남시
5 경기도 고양시 42 경기도 고양시
6 서울특별시 영등포구 40 서울특별시 영등포구
7 서울특별시 종로구 39 서울특별시 종로구
8 경기도 수원시 35 경기도 수원시
9 경기도 용인시 34 경기도 용인시
10 서울특별시 송파구 34 서울특별시 송파구
구군별로 매장수를 살펴보면 역시 서울 강남구가 가장 많습니다. 한국에서 아마 인구밀도가 가장 높은 지역이며 유동인구와 일과시간에 직장인이 가장 많이 있는 곳입니다.
그 다음은 역시 유동인구가 가장 많고 오피스밀집 지역이며 인구밀도가 높은 서울 중구입니다. 중구에는 명동, 충무로, 을지로가 있습니다.
그 다음은 서울 서초구인데 서초구는 강남구와 인구밀도는 비슷하지만 오피스공간 보다는 주거지역이 훨씬 많기 때문에 강남구나 중구에 비해서 낮시간에 직장인이 아주 많지는 않습니다. 그래도 괘나 많습니다.
그리고 그 다음은 경기도 성남시인데 성남에는 분당과 판교가 있으며 성남전체의 인구도 많으므로 이것도 당연합니다.
서울-강남구에 스타벅스가 압도적으로 많으며 다른 대형 지역구들도 제법 많습니다. 앞서 말했듯이 이 지역은 직장인들이 주중에 많이 머무는 지역들입니다. 물론 여기 나온 인구수는 거주 인구수이기 때문에 직장인이 주중에 많다는 것과의 상관관계를 다시 확인해야 할 필요가 있습니다만 알려진 바로는 매우 특별한 경우를 빼면 거주인구가 많은 지역에 직장도 많습니다.
인구수와 매장수의 상관관계
Pearson's product-moment correlation
data: sido_tbl$n and sido_tbl$total
t = 7.6707, df = 15, p-value = 1.439e-06
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
0.7216524 0.9609928
sample estimates:
cor
0.8926678
시도별 인구수와 스타벅스 매장수의 상관관계를 보면 상관계수가 0.89로 강한 상관이며 검정에서 대립가설 채택으로 상관이 있다는 결과가 나옵니다.
더 해볼 것
상관관계를 볼 때 단순 인구수가 아닌 면적을 인구수로 나눠서 인구밀집도를 구한 다음에 상관관계를 보는 것이 더 합리적이겠지만 면적데이터를 가져와서 붙여야 하니 귀찮아서 생략하겠습니다.
또 구군별로도 면적데이터를 가져와서 구군별로도 인구수와 스타벅스 매장수가 상관이 있는지 확인해 보는 것도 필요합니다만 이것도 생략하겠습니다.
혹시 해보고 싶으시면 아래 소스를 보시고 고쳐서 직접 한 번 해보세요.
결론 및 인사이트
매장수와 지역의 인구밀집도는 관계가 있습니다.
시도별, 구군별로 모두 상관관계가 있습니다.
따라서 스타벅스매장이 많은 곳은 인구밀집도가 높은 지역일 가능성이 큽니다.
인구밀집도는 유동인구수와 상관관계가 있는 것으로 알려져 있습니다.
스타벅스 매장이 많은 곳(있는 곳)은 유동인구가 많은 곳입니다.
마약 누군가 많은 유동인구가 필요한 점포를 개업하려고 한다면 스타벅스 부근에 개점하면 됩니다.
길거리 음식을 팔거나 판매하려면 패션 팟업스토어, 푸드 트럭을 열려면 스타벅스 근처에 하면 잘 될 것입니다. 물론 그게 가능하다면 말이죠.
최근에 데이터과학자(Data Scientist)가 되려면 뭘 배워야하고, 어떻게 해야하며, 커리어는 어떻게 키워나가야 하는지 물어보는 분들이 다시 늘어서 이런 내용으로 포스팅을 한 번 해보려고 했었습니다.
짧고 이해하기 쉽게 해보자라는 생각으로 제가 받았던 질문에 대한 답변형식으로 적습니다.
※ 글에서는 데이터사이언티스 (Data Scientist) 대신 데이터과학자라고 적습니다.
데이터과학자는 뭐하는 사람인가요?
하는 일은 데이터를 처리하고 분석해서 통찰을 얻고 사실을 검증합니다. 그리고 그 결과를 결정권자에게 주고 좋은 결정을 할 수 있게 도와줍니다.
중요한 것은 “데이터 기반 (Data Driven)”이라는 것과 “결정을 돕는 다”는 것입니다. 데이터과학자가 결정을 하지는 않습니다. 하지만 판단은 합니다. 과학적으로 판단하고 논리에 따라 합리적인 의견을 결정권자 또는 의뢰인에게 전해줍니다. 그리고 심사숙고하지 않은 즉흥적 결정, 충동적 결정, 막연한 결정을 하지 못하도록 돕습니다.
예를 들면 게임회사의 데이터과학자라면 특정 게임 A의 아이템들의 가격을 올려야 할지 내려야 할지에 대한 판단을 하고 그 결과를 기획자 및 전략담당자에게 알려준다거나 하는 것입니다.
데이터과학자는 개발자가 아닌 거죠?
네.
대부분 이렇게 아니라고 대답합지만 사실은 개발자인 것도 맞습니다. 그런데 개발자라고 하지 않는 이유는 개발자라고 대답하는 순간 데이터과학자에게 개발을 물어보고개발일을 맡기기 때문입니다. 그것 말고도 할 일 많으니까 그냥 아니라고 대답합니다.
뭘 공부하면 되나요?
확률/통계, 수학, 프로그래밍, 데이터 베이스(SQL)를 배워야 합니다.
수학은 고등학교 수준이면 되나요?
고등학교 과정의 고급 수학 과정을 무난하게 다 기억하고 있다면 수학을 굉장히 잘하는 것입니다. 무난하게 한다는 것은 고등학교 졸업을 의미하는 것이 아닙니다.
흔히 선형대수학, 미적분학 까지는 해야 한다고 말하는데, 이걸 잘하면 훨씬 유리합니다. 잘 못하면 지금부터 시작해도 안 늦습니다. 포기하지만 않는다면요.
데이터과학자가 되려면 얼마나 걸리나요?
타이틀을 데이터과학자로 명함에 넣어주는 것은 회사가 해주는 것이므로 회사마다 다릅니다.
괜찮은 데이터과학자라는 말을 들으려면 대략 제 경험으로 유사 학문을 전공한 사람은 5년 정도는 현장에서 훈련하면 되고. 전공자라면 3년이면 되는 것 같습니다. 적성에 안맞는 사람은 몇년이 되어도 제대로 못합니다.
아주 잘하는 것은 그 이상의 시간이 걸립니다.
참고로 박사학위 소지와 데이터과학을 잘하고 못하고는 크게 관련없습니다. 개인의 능력차이와 학습량의 차이입니다.
데이터과학자는 전망이 좋은가요?
무슨 전망이요? 미래에서는 인공지능, 로봇이 모든 사람들의 일을 뺏을 것이라서 어둡습니다. 데이터과학자도 예외는 아닙니다.
급여는 많이 받나요?
아직까지는 다른 직군에 비해 많이 받는 편이라고 봅니다. 최근에 데이터과학자 숫자가 많이 늘어서 이제 많이 높지는 않습니다.
랭귀지는 Python을 배워하나요? R을 배워야 하나요?
둘다 해야 합니다. 둘다 못하겠고 꼭 하나만 하고 싶다면 Python을 하면 됩니다.
그래도 다시 말하면 데이터과학을 하려면 둘다 하는 것이 나중에 매우 좋습니다.
둘 다 하라고 하는 이유는 R과 Python은 각각 문제해결이나 일처리를 쉽고 빠르게 할 수 있는 영역이 있습니다. 하나만 알게 되면 그런 문제를 해결할 때 때로 굉장히 어렵고 힘들게 해결해야 할 수 있습니다.
디지털마케팅을 하고 싶은데 데이터 분석, 데이터 과학을 할 줄 알아야 하나요?
몰라도 됩니다.
알면 좋습니다. 하지만 필수는 아닙니다. (당연한 것이지만)
엑셀은 잘하는데 엑셀로는 데이터과학을 못하나요?
할 수 있습니다. 하는 사람도 많습니다.
다만 “모냥빠진다!”, “없어보인다!”라고 해서 기피할 뿐입니다.
문제를 쉽게 해결할 수 있는 쉬운 방법을 사용해서 해결하는 것이 가장 좋은 것입니다. 엑셀로 쉽게 할 수 있는 것은 엑셀로 하면 됩니다. 하지만 엑셀만으로 모든 문제를 해결할 수는 없습니다. 아마도.
회사에서 SAS, 매트랩을 씁니다. 계속 이걸로 데이터과학해도 되나요?
다니는 회사/연구소에서 SAS 또는 매트랩을 주력으로 사용하고 있고 선임자가 매니저가 그걸 쓰도록 말했다면 그렇게 하는 것이 신상에 좋습니다. 뭐 잘 아시겠지만요.
하지만 취업, 이직, 커리어전환, 오픈소스 패키지 사용, 새 알고리즘이나 패키지사용, 비용 등을 볼때 R 또는 Python을 선택하는 것이 낫습니다.
데이터 과학을 할 때 사용할 컴퓨터 언어로 R이 좋은지 Python이 좋은지에 대한 비교글은 구글 검색을 하면 비교적 많은 자료를 얻을 수 있을 것입니다. 사람들이 논쟁하기에 딱 좋은 주제이기 때문입니다. 어차피 사람마다 차이가 있기 때문에 명확하게 결론을 내기는 어려우니 대충 하기 나름이다라고 하면 욕먹을 일도 없습니다.
그래서 이 주제도 R과 SAS 비교와 같이 결론이 잘 나지 않고 애매모호하게 끝을 맺게 됩니다만.
R은 표준어법에 따르면 “아르”로 읽는 것이 맞습니다. 그래서 글을 쓸때도 “R는”, “R가” 처럼 조사를 맞춰서 써야 하는 것이 맞습니다만 이게 너무 어색해서 그냥 “알”로 하겠습니다.
무엇을 선택하는 것이 유리한가?
데이터사이언스(Data science) 또는 데이터분석( Data Analysis)같은 것을 하려고하는데 아니면 이제 막 시작하려고 하는데 요즘 유행인 R, Python같은 것들 중에서 “무엇을 배워야 하는가? ” 또는 “무엇을 선택해야 나중에 유리한가?”라는 것입니다.
대세는 Python인 것 같은데 Python을 해야 하는지 아니면 좀 더 통계 분석가나 과학자들이 쓸 것 같아 보이는 R을 선택할 것인지 말입니다.
어떤 도구를 선택하느냐에 대해서 물어보면 전문가 또는 경험자들의 대답은 언제나 사용하는 사람에 따라 다르고 환경에 따라 다르다고 합니다. 그게 답이라는 것은 누구나 압니다.
하지만 사람들이 원하는 답은 그것이 아닐 것입니다. 뭔가를 선택하게 해주는 것입니다.
랭귀지를 선택할 때 고려할 것
데이터 분석이나 데이터 과학을 하는데 있어 컴퓨터 랭귀지를 선택할 때 고려할 것들에 대해서 몇가지를 적어봅니다.
범용성이 높은 것을 선택
사람들이 많이 쓰는 것을 선택
가격이 비싸지 않은 것을 선택
쉽게 구할 수 있고 쉽게 사라지지 않을 솔루션을 선택 (의존성이 적은 것을 선택)
범용성이 높다는 것은 여기저기 다양한 용도로 쓸 수 있는가를 말합니다. Python이 범위가 가장 넓고 좋습니다. R은 범용적으로 쓸 수 없는 것은 아니지만 실제로는 통계 또는 데이터분석에만 적합하다고 보는 것이 맞습니다. 사실 R은 범용적으로 쓸 수 없다고 해야 더 정직한 답변일 것입니다.
현재 데이터과학자들이 많이 쓰는 컴퓨터 언어는 Python, R순입니다. SAS나 Julia같은 것도 많이 씁니다만 Julia는 아직 사용자 층이 두텁지 않습니다. 그 외에 다른 일반 컴퓨터 랭귀지는 데이터 분석, 데이터 과학을 하는데 적합하지 않습니다.
그래서 결국 선택할 것은 Python과 R로 좁혀집니다.
결국 이대로라면 Python을 쓰는 것이 좋습니다.
혹시 Java나 C++ 같은 저수준 랭귀지로는 데이터분석이나 데이터과학을 못하는가?
우선 이것부터 얘기하면 컴퓨터 랭귀지 중에 범용성이 가장 좋은 Java, C++, C# 같은 것들을 배우면 Python이나 R을 배우지 않아도 되는것 아닌가? 라는 의문일 것입니다.
결론을 말씀드리면 생산성이 너무 떨어져서 이 언어들로는 데이터 분석이나 데이터 과학을 빠르게 하기 어렵습니다.
못하는 것은 아닙니다만 효율이 떨어집니다.
그래도 저수준에 조금이라도 가까운 것은 Python입니다.
만약 C++를 할 수 있거나 후에 반드시 익히겠다면 R이든 Python이든 뭘 고르더라도 좋습니다. C++로 만든 모듈을 붙여 넣어서 R과 Python을 직접 강화시킬 수 있으니까요.
데이터 과학에서의 R과 Python의 공통점, 차이점, 장단점
대화형 작업의 중요성
대화형 작업(interactive working mode)이란 어떤 분석이나 모델을 만드는 코드를 처음부터 끝까지 다 작성한 후에 일괄 실행하는 것이 아니라 부분부분 완성해 가면서 완성한 부분 또는 일부만 실행해서 그 결과를 계속해서 확인하고 고치는 방식을 말합니다.
데이터 분석과 모델링에서는 이 대화명 작업이 필수입니다. 잘못된 것, 예상한 것과 다르게 된 것, 데이터에 클린징 작업, 모델링 작업은 처음부터 끝까지 주욱 흐름에 따라 코딩하고 한 두번 훑어 보고실행한다고 다 끝나지 않습니다. 계속해서 같은 코드를 반복해서 고치고 수정하고 결과를 보고는 것을 반복해서 보정해 나간 후 최종 완성합니다.
이 작업을 효율적으로 하려면 코드를 분할해서 작성한 부분까지 완성을 하고 다음 부분으로 넘어가는 것을 지원하는 것이 좋습니다.
여기에서는 R의 손을 들어주고 싶습니다.
R과 Python중 하나를 선택
아직도 선택을 못했겠지만 이 2개 중 하나를 선택해야 합니다.
앞서 설명한 바 있습니다만 R과 Python은 둘 다 모두 스크립트(script) 언어이면서 둘다 대화형 언어(Interpretor)이기도 합니다.
스크립트 언어라는 것은 C++이나 Java 처럼 컴파일을 하거나 중간코드를 빌드하지는 않는 것을 말하는 것이고 대화형 언어라는 것은 코드를 입력하고 그 결과를 즉시 확인할 수 있다는 것입니다.
그래서 가능하다면 R과 Python을 둘 다 하는 것이 훨씬 좋습니다. 하지만 R이 PYthon보다는 학습장벽이 매우 높기 때문에 둘 중에 어떤 것을 먼저해야 하냐고 묻는다면 Python을 먼저 선택하는 것이 대체로 유리합니다.
선택할 때 고려할 것
위에서 말씀드린 몇 개의 중요한 항목을
선택을 할 때 이렇게 하시면 됩니다.
앞으로 통계 분석을 더 많이 하게 될 것 같다. R
시각화가 편하고 빠르면 좋겠다. R
일괄 처리 작업이나 텍스트마이닝 같은 처리도 하고 싶다. Python
기계학습 모델을 자주 만들고 많이 만들것 같다. Python
데이터 전처리와 이관, 자동화 같은 것도 해야 한다. Python
최신 통계 패키지가 많아야 한다. R
최신 기계학습 패키지가 많아야 한다. Python
딥러닝을 해야 한다. Python
IOT도 해야 한다. Python
시계열 분석, 수리 통계, 금융 분석 이런 고급 통계나 수학과 관련된 것을 할 것이다. R
빅데이터 플랫폼들에 접속해서 비정형 데이터를 가져오거나 처리해야 한다. Python
웹개발도 좀 해야 한다. Python
웹개발도 해야 하지만 위젯 정도나 간단한 시각화 수준이면 된다. R (Shiny가 있으므로)
주로 연구하고 논문쓰는 일을 많이 할 것 같다. R
나는 의사이고 실험을 많이 한다. R
분석 리포트를 많이 쓰거나 논문을 많이 써야 한다. R
바이오인포메틱스이고 유전자 데이터 이런 일과 관련이 있다. Python
클라우드의 자원 활용모 하게될 것 같다. Python
대부분 R과 Python 둘다 가능한 것이지 둘 중에 더 유리한 것 하나를 답으로 했습니다.
자 대체로 PYthon을 선택하면 된다는 쪽으로 보여집니다만 위에 열거한 것들에서 선택된 것의 숫자만 보고 그렇게 판단하시면 안됩니다.
R의 좋은 점
R을 옹호하는 입장이 되서 장점을 어필해보면.
R의 강점은 커뮤니티와 커뮤니티에서 제공되는 패키지가 있습니다. 최신 통계 분석, 알고리즘이나 기법들이 패키지가 가장 빨리 제공되고 있으며 품질도 상당히 좋습니다.
대부분 패키지를 만들어서 제공하시는 분들이 그 분야의 석박사이거나 교수들입니다. 100% 믿을 수 있는 것은 아니지만 보통은 쓰는 사라들보다 그 부분에 대해서는 훨씬 전문적인 분들이라서 믿고 쓸 수 있습니다.
또 패키지가 중앙집중식으로 엄격하게 관리되고 있습니다. 패키지가 등록될 때 절차도 까다롭고 검증도 까다롭습니다. 그래서 패키지가 작동하지 않는다거나 하는일이 거의없고 오래된 패키지들도 비교적 관리가 잘됩니다.
Python의 좋은 점
PYthon을 옹호하는 입장에서 장점을 어필해보면.
쓰는 사람이 워낙 많아서 자료를 구하기 쉽고 샘플 코드를 구하기도 쉽습니다.
랭귀지가 배우기 쉬운 편입니다. 물론 그렇다고 해서 책 한 권 읽고 바로 할 수 있을 만큼 젼짜 쉽다는 얘기는 아닙니다.
그래서 어떻게 뭘 하면 되는데?
“하는 일” 또는 “하려고 하는 일”의 직군이
엔지니어, 개발자 쪽에 가깝다면 Python
분석가, 연구원에 가깝다면 R
과학자는 둘 다 해당됩니다. 둘 다 하면 좋고 둘 중 하나만 해도 됩니다. 적어도 지금은 말이죠.
작성한 코드의 실행 속도 문제
구현체의 성능은 Python이 R보다 빠릅니다. 단순하게 비교할 수는 없지만 작성한 코드의 실행 속도가 대부분 Python이 R보다 빠릅니다.
텍스트 데이터, 음성, 비디오 같은 비정형 처리는 Python도 느립니다만 R은 정말 느립니다. 물론 해결책이 없는 것은 아니지만 이런 것은 순수하게 R로 해결하기 어려운 경우가 많습니다.
물론 코드의 실행 속도가 데이터과학에 가장 중요한 요소는 아닙니다. 그리고 어차피 속도가 요구되는 고속 모듈들은 Python이나 R모두 C++작성된 것을 호출해서 사용하는 방식이 대부분입니다.
R은 편리를 위한 언어이지 처리 속도를 고려한 언어는 아닙니다. 물론 Python도 처리 속도가 빠른 언어가 아닙니다. 계산 속도가 빠른 것도 아닙니다.
계산 속도가 빠른 것은 Julia가 있습니다. 새로운 도전을 좋아하고 이렇 신문물에 선구자로 깃발꽂기를 좋아한다면 Julia를 해보는 것도 좋겠습니다.
Excel, Tableau, SAS, SPSS 같은 것들로는 데이터 과학을 할 수 없는가?
할 수 있습니다.
어떤 종류의 작업에 더 적합하고, 능숙한지에 따라 다릅니다. 중요한 사실은 훈련된 능숙한 데이터 과학자 일수록 사용할 수 있는 랭귀지가 툴이 많다는 것입니다.
데이터 과학은 데이터 과학 도구 사용법을 익히는 것이 아니라 데이터에서 원하는 사실을 찾고 그것을 토대로 좋은 결정을 하기 위해서 필요한 도구는 뭐든 가져다 쓰고 과학적인 결과를 얻어 내는 것입니다.
R과 Python 중 하나를 먼저 배우고 다른 것을 마저 배울때
두 언어는 만들어진 철학이 매우 다릅니다. 그래서 하나를 배우고 나면 다른 하나를 배우기가 어렵습니다. 배울 때나 사용할 때 각각 의 언어에 따라 사용자가 관점을 많이 바꿔야 이해할 수 있는 것들이 많기 때문입니다.
즉, 하나를 배우고 다른 하나를 배울 때 이점이 별로 없습니다. 오히려 방해가 될 수 있습니다.