Quiz / ML 비지도학습 / 전체 문항
GitHub

ML 비지도학습 전체 문항

클러스터링, 차원 축소, 이상 탐지. 문항과 선택지별 해설을 글 순서대로 나열했습니다.

30문항 · 글 5편
직접 풀어보기 →

중심점을 옮겨가며 군집을 찾는 K-Means 클러스터링

원문 읽기 →
개념 확인구조

K-Means가 할당과 이동을 번갈아 돌리는 것만으로 언젠가 멈추는 이유는 무엇인가?

  1. 반복 횟수 상한이 걸려 있어 그 횟수에 닿으면 강제로 중단되기 때문이다.

    상한은 안전장치일 뿐이다. 그것이 없어도 절차 자체가 유한한 단계 안에 멈춘다.

  2. 중심점의 이동량이 매 반복마다 절반으로 줄어들어 기하급수적으로 수렴하기 때문이다.

    이동량이 일정한 비율로 줄어든다는 보장은 없다. 수렴의 근거는 이동량의 크기가 아니라 목적값이 늘지 않는다는 성질이다.

  3. 정답두 단계 모두 목적값을 늘리지 않고 가능한 소속 조합이 유한하기 때문이다.

    소속을 고정하면 최적 중심점은 평균이고 중심점을 고정하면 최적 소속은 최근접이다. 값이 단조 감소하는데 상태가 유한하므로 반복이 끝난다.

  4. 목적 함수가 볼록해서 어느 초기값에서 출발해도 같은 최솟값으로 모이기 때문이다.

    이 문제는 볼록하지 않다. 멈추는 것은 맞지만 멈춘 자리가 전역 최적이라는 보장은 없다.

해설

K-Means가 줄이려는 값에는 미지수가 두 종류 들어 있다. 중심점의 위치와 각 점의 소속이다. 둘을 동시에 최적으로 푸는 문제는 계산이 감당되지 않으므로 한쪽을 고정하면 나머지가 쉽게 풀린다는 성질을 쓴다. 소속을 고정하면 목적값을 최소로 만드는 중심점은 그 클러스터의 평균이고, 중심점을 고정하면 각 점의 최적 소속은 가장 가까운 중심점이다. 두 단계 어느 쪽도 값을 늘리지 않으므로 번갈아 돌리면 값이 단조 감소하고, 가능한 소속 조합이 유한하니 언젠가 멈춘다. 다만 멈춘 자리가 전역 최적이라는 보장은 없다. 초기 중심점을 어디에 두었느냐에 따라 서로 다른 지역 최적에 갇히고, 그래서 초기화가 하이퍼파라미터 취급을 받는다.

이 내용 다시 읽기 →
상황 적용함정
# sklearn 1.4 이상
km = KMeans(n_clusters=5, random_state=42)
km.fit(X_scaled)

# random_state를 바꿀 때마다 결과가 크게 달라진다

여기서 무엇을 놓쳤는가?

  1. random_state를 고정했으므로 초기화가 매번 같아 다양성이 사라졌다.

    값을 바꿀 때마다 결과가 달라진다는 것이 문제의 내용이다. 고정 여부가 아니라 시도 횟수가 원인이다.

  2. 정답n_init 기본값이 auto이고 기본 초기화에서는 한 번만 돌아 초기화 운에 그대로 노출된다.

    auto가 10회를 뜻하는 것은 무작위 초기화일 때뿐이다. 기본값에서는 단 한 번 돌므로 초기화에 민감한 데이터라면 숫자를 직접 적어야 한다.

  3. max_iter 기본값이 낮아 수렴하기 전에 멈춘 것이므로 반복 상한을 올려야 한다.

    상한에 걸렸는지는 실제 반복 횟수를 확인하면 알 수 있고, 대개 그 전에 수렴한다. 수렴은 했는데 어느 지역 최적으로 갔느냐가 흔들리는 상황이다.

  4. tol이 절대 거리 기준이라 스케일링된 데이터에서 너무 이르게 멈춘다.

    이 값은 절대 거리가 아니라 피처 분산의 평균에 곱해지는 상대값이라 데이터의 스케일이 달라져도 같은 기준이 유지된다.

해설

sklearn 1.4부터 초기화 반복 횟수의 기본값이 auto로 바뀌었고, 이 값이 10회를 뜻하는 것은 무작위 초기화를 지정했을 때뿐이다. 기본 초기화에서는 단 한 번만 돈다. 1.4 이전 기본값이 10이었기 때문에 여전히 열 번 도는 줄 알고 쓰는 코드가 많다. 개선된 초기화는 중심점끼리 서로 멀리 떨어지도록 유도해 나쁜 출발을 크게 줄여주지만 한 번의 실행으로 지역 최적을 완전히 피하지는 못한다. 그래서 서로 다른 초기화로 여러 번 돌린 뒤 목적값이 가장 낮은 결과를 고르는 방법을 함께 쓰고, 그 횟수를 정하는 값이 이 파라미터다. 초기화 운에 민감한 데이터라면 숫자를 직접 적는 편이 안전하다. 미니 배치 구현도 기본 초기화에서는 한 번만 돈다.

이 내용 다시 읽기 →
상황 적용진단
K를 1부터 9까지 늘리며 목적값을 재봤더니 꺾이는 자리 없이 고르게 줄어들기만 한다. 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 감소폭이 매번 비슷하다

이 곡선을 어떻게 읽어야 하는가?

  1. K를 더 크게 잡아 20이나 30까지 늘리면 꺾이는 자리가 나타날 것이다.

    K가 데이터 개수에 닿으면 목적값이 0이 되므로 어디선가 완만해지기는 한다. 그 자리가 구조를 뜻한다는 근거는 없다.

  2. 정답클러스터끼리 겹쳐 있거나 밀도가 이어져 있다는 신호이고 실제 데이터에서 흔한 모양이다.

    덩어리 사이의 경계가 뚜렷하면 그 개수를 넘어서는 순간 감소폭이 확 줄지만, 경계가 흐리면 K를 늘릴 때마다 비슷한 몫이 계속 깎인다. 이 기준 하나로 K를 정하면 안 되는 이유다.

  3. 스케일링을 하지 않아 한 피처가 거리를 독점하고 있다는 신호다.

    그런 경우에도 곡선의 모양은 데이터에 따라 다르게 나온다. 꺾임이 없다는 것만으로 스케일 문제를 진단할 수 없다.

  4. 초기화 횟수가 부족해 매 K마다 다른 지역 최적에 갇혀 곡선이 흐려진 것이다.

    지역 최적에 갇히면 곡선이 들쭉날쭉해진다. 여기서는 오히려 고르게 감소하고 있으므로 다른 이야기다.

해설

엘보우 기준은 K를 늘리면 목적값이 반드시 줄어든다는 성질에서 출발하므로 값 자체가 아니라 줄어드는 속도를 본다. 급하게 떨어지다 완만해지는 지점이 있으면 거기를 고른다. 문제는 그 지점이 보이지 않을 때가 많다는 것이다. 클러스터끼리 겹쳐 있거나 밀도가 이어져 있으면 K를 늘릴 때마다 비슷한 몫이 계속 깎여 어디를 골라도 근거가 약해지고, 실제 데이터에서 오히려 이쪽이 더 흔하다. 그래서 실루엣 같은 다른 기준을 함께 보고, 두 기준이 다른 K를 가리키면 각각으로 돌려 클러스터의 내용이 해석되는 쪽을 고르는 편이 낫다. K를 정하는 일에는 데이터 바깥의 판단이 반드시 들어간다.

이 내용 다시 읽기 →
분석과 판단구조
안쪽 원과 바깥 고리로 나뉜 데이터에 K=2로 K-Means를 돌렸다. 스케일링도 했고 초기화도 20번 반복했는데 두 고리를 가르지 못하고 공간을 좌우로 반 나눈다.

왜 튜닝으로 풀리지 않는가?

  1. 정답중심점 두 개가 그릴 수 있는 경계는 둘을 잇는 선분의 수직이등분선뿐이기 때문이다.

    결과로 나오는 영역은 언제나 직선으로 둘러싸인 볼록한 조각이다. 고리는 그런 조각으로 표현할 수 없으므로 K를 어떻게 골라도 답이 나오지 않는다.

  2. 두 고리의 중심이 같아 중심점이 겹치면서 학습이 퇴화했기 때문이다.

    중심점은 겹치지 않고 서로 다른 자리로 수렴한다. 문제는 중심점의 위치가 아니라 그것이 만들 수 있는 경계의 모양이다.

  3. 목적값이 거리의 제곱합이라 바깥 고리의 점들이 큰 벌점을 받아 왜곡되기 때문이다.

    제곱합은 이상치에 민감해지는 요인이지만 여기서는 원인이 아니다. 제곱을 쓰지 않아도 볼록한 경계라는 제약은 그대로다.

  4. 초기화가 아무리 반복돼도 두 고리가 같은 밀도라 목적값이 구별되지 않기 때문이다.

    목적값은 초기화마다 다르게 나오고 최선의 값도 존재한다. 그 최선의 해 자체가 원하는 답이 아닐 뿐이다.

해설

K-Means가 그릴 수 있는 경계는 중심점 두 개를 잇는 선분의 수직이등분선뿐이다. 결과적으로 공간은 중심점들의 보로노이 다이어그램으로 쪼개지고 각 조각은 직선으로 둘러싸인 볼록한 영역이 된다. 고리나 초승달처럼 이 조각들로 표현할 수 없는 모양이면 K를 아무리 잘 골라도 답이 나오지 않는다. 알고리즘의 정의에서 곧장 나오는 제약이라 튜닝으로 풀리지 않고 모델을 바꿔야 한다. 밀도로 군집을 정의하는 방법이나 스펙트럴 클러스터링이 이런 모양에 맞는다. 같은 뿌리에서 나오는 약점이 몇 개 더 있다. 중심점이 평균이라 이상치 하나에 크게 끌려가고, 클러스터의 크기와 밀도가 제각각이면 큰 덩어리의 중심점이 작은 덩어리 쪽 점까지 가져간다.

이 내용 다시 읽기 →
상황 적용운영
K=5에서 실루엣 평균이 0.61로 가장 높게 나와 그 값을 골랐다. 그런데 점마다의 값을 클러스터별로 나눠 보니 한 클러스터만 평균이 0.18이고 음수 구간도 넓다.

이 상황을 어떻게 다뤄야 하는가?

  1. 평균이 가장 높은 K가 정답이므로 그대로 두고 낮은 클러스터는 잡음으로 처리한다.

    실루엣에는 잡음이라는 범주가 없다. 그 클러스터에도 상당한 수의 점이 들어 있으며 통째로 버릴 대상이 아니다.

  2. 음수 값을 가진 점들을 제거하고 다시 학습해 평균을 끌어올린다.

    경계에 걸친 점을 지우면 점수는 좋아지지만 데이터의 구조가 아니라 지표만 손본 것이다. 실제 예측에는 그 점들도 들어온다.

  3. 정답그 클러스터를 더 쪼개는 쪽이 나은 상황이므로 K를 올린 결과와 견줘 본다.

    음수는 다른 클러스터가 더 가깝다는 뜻이라 그 안에 서로 다른 무리가 섞여 있다는 신호다. 평균만 보면 이런 국소적인 문제가 다른 클러스터의 높은 값에 가려진다.

  4. 실루엣이 점 쌍 거리를 다 계산하는 지표라 표본이 크면 값이 불안정해진 것이므로 표본을 나눠 다시 잰다.

    계산량이 많은 것은 사실이지만 값이 불안정해지지는 않는다. 한 클러스터에만 낮은 값이 몰린 것은 표본 크기와 무관한 구조적 신호다.

해설

실루엣은 점마다 같은 클러스터의 다른 점들과의 평균 거리와 가장 가까운 다른 클러스터까지의 평균 거리를 견줘 계산한다. 1에 가까우면 자기 클러스터에 잘 붙어 있고, 0 근처면 경계에 걸쳐 있으며, 음수면 다른 클러스터가 더 가깝다는 뜻이라 잘못 할당된 점이다. 전체 평균만 보면 이런 국소적인 문제가 다른 클러스터의 높은 값에 가려지므로, 점마다의 값을 꺼내 클러스터별로 나눠 봐야 한다. 특정 클러스터 하나만 값이 낮거나 음수 구간이 넓다면 그 안에 서로 다른 무리가 섞여 있다는 신호이고 더 쪼개는 쪽이 낫다. 지표 하나의 평균으로 K를 결정하는 대신 분포를 들여다보는 습관이 여기서 값을 한다.

이 내용 다시 읽기 →
분석과 판단확장구조
K-Means++는 첫 중심점만 무작위로 뽑고, 그다음부터는 이미 뽑힌 중심점까지의 최단 거리 D(x)에 대해 다음 확률로 뽑는다. P(x) = D(x)² / Σ D(x')²

가장 먼 점을 결정적으로 고르지 않고 확률로 뽑는 이유는 무엇인가?

  1. 결정적으로 고르면 계산량이 커져 대규모 데이터에서 감당되지 않기 때문이다.

    최댓값을 찾는 것과 확률로 뽑는 것의 계산량은 비슷하다. 둘 다 모든 점의 최단 거리를 한 번씩 봐야 한다.

  2. 정답가장 먼 점은 대개 이상치라 결정적으로 고르면 이상치가 중심점이 되기 때문이다.

    거리의 제곱에 비례하는 확률로 뽑으면 먼 점이 유리하되 반드시 뽑히지는 않는다. 아직 중심점을 못 얻은 덩어리에서 나올 가능성을 높이면서 이상치 하나에 끌려가지는 않는다.

  3. 확률로 뽑아야 매 실행의 결과가 달라져 여러 번 돌린 뒤 최선을 고를 수 있기 때문이다.

    결과가 달라지는 것은 부수적인 성질이다. 결정적으로 골라도 첫 중심점이 무작위라 실행마다 결과는 달라진다.

  4. 거리의 제곱을 쓰면 목적 함수와 단위가 맞아 초기값이 곧바로 목적값의 하한이 되기 때문이다.

    제곱을 쓰는 것은 먼 점에 무게를 더 싣기 위해서다. 초기값이 하한이 되는 관계는 성립하지 않는다.

해설

무작위 초기화의 위험은 중심점 두 개가 나란히 뽑혀 한 덩어리를 나눠 갖고 다른 덩어리는 통째로 남의 클러스터에 묻히는 것이다. 그 자리에서 수렴해도 목적값은 나쁜 값에 머문다. K-Means++는 이미 뽑힌 중심점까지의 최단 거리 제곱에 비례하는 확률로 다음 중심점을 뽑아 이 문제를 완화한다. 먼 점일수록 유리하므로 아직 중심점을 못 얻은 덩어리에서 나올 가능성이 커지고, 그러면서도 확률이라 가장 먼 점, 즉 이상치일 가능성이 높은 점에 결정적으로 끌려가지 않는다. 이 초기화만으로 기대 목적값이 최적값의 로그 K 배 안에 든다는 보장이 붙고, 순수 무작위 초기화에는 그런 보장이 없다. 다만 보장은 기댓값에 대한 것이라 여러 번 돌려 최선을 고르는 방법과 함께 써야 한다.

이 내용 다시 읽기 →

가우시안 밀도부터 Isolation Forest까지, 이상 탐지의 원리

원문 읽기 →
개념 확인설계
두 과제를 놓고 지도학습 분류와 이상 탐지 중 하나를 골라야 한다. A) 스팸 필터. 라벨된 스팸이 수백만 건 쌓여 있고 새 스팸도 기존과 닮았다 B) 신종 침입 탐지. 공격자가 수법을 계속 바꾼다

어떻게 나누는 것이 맞는가?

  1. 둘 다 이상 탐지다. 정상의 생김새를 배우는 쪽이 언제나 더 안전하다.

    이상 사례가 충분하고 유형이 안정적이면 그것을 직접 배우는 쪽이 더 정확하다. 정상만 배우는 것은 재료가 없을 때의 선택이다.

  2. 둘 다 분류다. 이상 탐지는 라벨이 하나도 없을 때만 쓰는 최후의 수단이다.

    이상 탐지도 임계값을 고를 때 소량의 라벨을 쓴다. 라벨 유무가 아니라 이상 사례의 수와 유형의 안정성이 기준이다.

  3. 정답A는 분류, B는 이상 탐지다. 이상 사례의 확보량과 유형의 안정성으로 갈린다.

    분류기는 학습한 패턴만 잡으므로 수법이 바뀌면 조용히 통과시킨다. 정상의 생김새를 배워두면 수법이 무엇이든 정상이 아니라는 판정은 그대로 나온다.

  4. A는 이상 탐지, B는 분류다. 데이터가 많을수록 분포를 정확히 추정할 수 있기 때문이다.

    방향이 반대다. 이상 사례가 풍부한 A야말로 그 패턴을 직접 배울 수 있는 경우다.

해설

둘 중 어느 쪽이 맞는지는 이상 사례를 얼마나 확보했는지, 그리고 앞으로 나타날 이상이 지금까지 본 것과 비슷할지로 갈린다. 라벨이 충분하고 새 사례가 기존과 닮았다면 이상의 생김새를 직접 배우는 분류기가 낫다. 반대로 이상이 극소수이거나 유형을 미리 알 수 없다면 정상의 생김새를 배우고 그 바깥을 이상으로 판정하는 쪽으로 간다. 정상 데이터는 얼마든지 쌓여 있으니 재료 걱정이 없고, 처음 보는 유형도 정상이 아니라는 이유만으로 걸린다. 더 근본적인 갈림길은 유형 쪽에 있다. 분류기는 학습한 패턴만 잡으므로 공격자가 수법을 바꾸는 순간 그 패턴은 학습 데이터에 없는 것이 되고 모델은 조용히 통과시킨다.

이 내용 다시 읽기 →
상황 적용진단
평균 (50, 100), x1 분산 25, x2 분산 36, 공분산 20인 데이터에서 두 점의 밀도를 쟀다. 점 독립 가우시안 다변량 가우시안 (55, 108) 0.001323 0.002894 (55, 92) 0.001323 0.000118

독립 모델이 두 점에 같은 값을 매긴 이유는 무엇인가?

  1. 정답편차를 제곱해 더하는 순간 부호가 사라져 두 특성 사이의 관계 정보가 지워지기 때문이다.

    두 점 모두 첫 특성의 편차가 5, 둘째 특성의 편차가 절댓값 8이다. 어떤 임계값을 고르더라도 두 점은 같이 통과하거나 같이 걸린다.

  2. 두 점의 유클리드 거리가 같아 어떤 밀도 모델에서도 같은 값이 나오기 때문이다.

    다변량 모델은 같은 유클리드 거리에서도 25배 가까운 차이를 냈다. 거리가 같다고 밀도가 같아지지 않는다.

  3. 독립 가정에서는 분산이 무시되고 편차의 절댓값만 반영되기 때문이다.

    분산은 각 항의 분모로 그대로 들어간다. 지워지는 것은 분산이 아니라 두 특성 사이의 관계다.

  4. 두 특성의 분산이 25와 36으로 비슷해 가중치 차이가 상쇄됐기 때문이다.

    분산이 크게 달라도 같은 값이 나온다. 상쇄가 아니라 부호 정보가 애초에 계산에 들어가지 않는 것이 원인이다.

해설

특성마다 가우시안을 따로 세워 곱하면 각 특성을 혼자 보면 정상 범위인데 조합이 이상한 경우를 통과시킨다. 두 점 모두 첫 특성의 편차가 5, 둘째 특성의 편차가 절댓값 8이라 제곱해서 더하는 순간 부호가 사라지고 완전히 같은 밀도가 나온다. 어떤 임계값을 고르더라도 둘은 같이 통과하거나 같이 걸린다. 다변량 가우시안은 공분산 행렬로 이 관계를 담아, 첫 특성이 크면 둘째도 커야 한다는 사실을 알고 있으므로 그 관계를 거스른 점을 훨씬 드문 사건으로 취급한다. 두 모델은 별개의 알고리즘이 아니라 같은 식에 다른 공분산을 넣은 것이다. 비대각 원소를 0으로 만드는 순간 다변량 가우시안은 독립 가우시안의 곱과 정확히 같아진다.

이 내용 다시 읽기 →
상황 적용함정
IsolationForest(contamination=0.06)으로 학습 데이터 1,000건을 판정했더니 정확히 60건이 이상으로 찍혔다. 실제 이상은 20건이고 그중 19건이 잡혔다.

이 결과를 어떻게 읽어야 하는가?

  1. 재현율 95%로 매우 우수하므로 이 설정을 그대로 배포하면 된다.

    찍힌 개수가 이미 정해져 있으므로 이 숫자만으로는 성능을 판단할 수 없다. 정밀도는 19를 60으로 나눈 값에 불과하다.

  2. 모델이 실제 이상 비율을 20건에서 60건으로 과대 추정했으므로 값을 0.02로 낮춰야 한다.

    이 값은 모델이 추정하는 대상이 아니라 사람이 지정하는 컷이다. 과대 추정이라는 표현이 성립하지 않는다.

  3. 학습 데이터에 이상이 60건 있다는 뜻이므로 라벨이 40건 누락됐는지 확인해야 한다.

    찍힌 60건은 데이터의 사실이 아니라 지정한 비율의 결과다. 라벨 누락을 의심할 근거가 되지 못한다.

  4. 정답이 파라미터가 임계값 그 자체라 60건은 지정한 비율의 결과일 뿐이다.

    sklearn은 학습 데이터의 점수 분포에서 이 비율의 백분위수를 잘라 경계로 삼으므로 실제 이상이 몇 개든 정확히 그 비율만큼 찍힌다. 성능을 물으려면 그 60건 안에 진짜 이상이 몇 개인지를 봐야 한다.

해설

이 파라미터는 이름만 보면 데이터에 이상이 얼마나 섞였는지 모델에 귀띔해 주는 값 같지만 실제로는 임계값 그 자체다. sklearn은 학습 데이터의 점수 분포에서 지정한 비율의 백분위수를 잘라 경계로 삼으므로, 0.06을 주면 실제로 이상이 몇 개든 정확히 6%가 이상으로 찍힌다. 그래서 몇 개 중 몇 개를 잡았다는 숫자를 성능으로 읽으면 안 된다. 찍힌 개수는 이미 정해져 있고 진짜 물어야 할 것은 그 개수 안에 진짜 이상이 들어 있느냐다. 이상 비율을 모른다면 자동 설정으로 두고 점수를 직접 정렬해 자를 지점을 고르는 편이 낫다. 다른 알고리즘의 비슷한 파라미터도 같은 자리를 차지하므로 이름이 아니라 구현이 그 값을 어떻게 쓰는지 확인해야 한다.

이 내용 다시 읽기 →
분석과 판단함정
for eps in np.logspace(-12, -2, 200):
    f1 = f1_score(y_val, (p_val < eps).astype(int))
    ...

후보를 등간격이 아니라 로그 간격으로 잡는 이유는 무엇인가?

  1. F1 점수가 로그 스케일에서만 단조로워 최댓값을 안정적으로 찾을 수 있기 때문이다.

    F1은 어느 스케일에서도 단조롭지 않다. 여러 봉우리가 생길 수 있어 후보를 훑는 방식을 쓰는 것이다.

  2. 정답밀도가 평균에서 조금만 멀어져도 자릿수 단위로 떨어져 등간격으로는 후보가 큰 값 쪽에만 몰리기 때문이다.

    선형 등간격으로 훑으면 200개 후보가 전부 큰 값 근처에 놓여, 정작 이상을 갈라내는 아주 작은 자리는 한 번도 시험해 보지 못한다. 자릿수마다 후보를 고르게 놓아야 한다.

  3. 밀도값이 음수가 될 수 있어 로그 스케일로 부호를 통일해야 하기 때문이다.

    확률 밀도는 언제나 양수다. 부호 문제는 생기지 않는다.

  4. 임계값은 확률이므로 0과 1 사이로 정규화해야 하는데 로그 간격이 그 역할을 하기 때문이다.

    로그 간격은 후보의 배치를 정할 뿐 정규화와 무관하다. 밀도는 애초에 1을 넘을 수도 있는 값이다.

해설

확률 밀도는 평균에서 조금만 멀어져도 자릿수 단위로 떨어진다. 선형 등간격으로 후보를 훑으면 200개가 전부 큰 값 쪽에 몰려서, 정작 정상과 이상을 갈라내는 아주 작은 자리는 한 번도 시험해 보지 못한다. 자릿수마다 후보를 고르게 놓아야 실제로 유효한 구간을 탐색한다. 임계값을 고르는 절차 자체도 짚어둘 만하다. 정상 데이터만으로 파라미터를 추정하고, 정상과 이상이 섞인 소량의 라벨 데이터에서 후보를 훑어 값을 고르고, 손대지 않은 테스트 세트에서 최종 성능을 잰다. 후보를 고를 때 정확도를 기준으로 삼으면 안 된다. 검증 세트도 정상이 압도적으로 많아 아무것도 탐지하지 않는 값이 1등을 차지하기 때문이다.

이 내용 다시 읽기 →
상황 적용설계
주택 위치 데이터에 이상 탐지를 걸려 한다. 도심에서는 집들이 수십 미터 간격으로 붙어 있고 교외에서는 수백 미터씩 떨어져 있다. 교외에서 이웃과 500m 떨어진 집 → 정상 도심에서 이웃과 500m 떨어진 집 → 이상

이 판정을 낼 수 있는 방법은 무엇이고 근거는 무엇인가?

  1. 다변량 가우시안이다. 공분산 행렬이 방향별 퍼짐을 담으므로 지역마다 다른 기준이 적용된다.

    공분산은 데이터 전체에 하나뿐이라 여전히 전역 기준이다. 지역별로 기준이 갈리지 않는다.

  2. Isolation Forest다. 무작위 분할이 밀집 지역과 성긴 지역에서 각각 다른 깊이를 만들기 때문이다.

    경로 길이가 밀도를 반영하기는 하지만 그 값을 데이터 전체 기준으로 비교한다. 교외의 집들은 전체적으로 짧은 경로를 갖게 된다.

  3. One-Class SVM이다. 커널 트릭으로 도심과 교외를 각각 감싸는 두 영역을 만들 수 있기 때문이다.

    두 영역을 감쌀 수는 있지만 각 영역 안에서 얼마나 떨어져야 이상인지는 여전히 하나의 기준으로 정해진다.

  4. 정답LOF다. 전체 분포가 아니라 각 점의 이웃을 기준으로 한 상대 밀도를 보기 때문이다.

    어떤 점의 밀도를 그 점의 이웃들이 가진 밀도와 견주므로, 이웃들이 자기보다 훨씬 빽빽할 때만 이상으로 판정한다. 밀도가 서로 다른 덩어리가 섞여도 각 덩어리의 기준으로 판정한다.

해설

LOF의 강점은 이름에 붙은 Local에 있다. 어떤 점의 밀도를 그 점의 이웃들이 가진 밀도와 견주는 것이 전부이고, 이웃들이 자기보다 훨씬 빽빽하면 값이 1보다 크게 나오고 이웃과 비슷하면 1 근처가 된다. 전체 분포가 아니라 각 점의 이웃을 기준으로 한 상대 밀도를 보므로 밀도가 서로 다른 여러 덩어리가 섞인 데이터에서도 각 덩어리의 기준으로 판정한다. 전역 임계값 하나로는 이 구분을 낼 수 없다. 참조할 이웃 수가 유일한 손잡이인데 작으면 노이즈 한 점에 휘둘리고 크면 국소성이라는 장점이 사라진다. 방법을 고를 때 물어야 할 것은 알고리즘 이름이 아니라 정상 영역이 어떤 모양인가다. 밀도가 불균일하면 LOF, 특성이 적고 정규분포에 가까우면 확률값을 그대로 쓸 수 있는 가우시안 모델이 낫다.

이 내용 다시 읽기 →
분석과 판단구조
Isolation Forest의 이상 점수다. s(x) = 2^( -E[h(x)] / c(m) ) E[h(x)]는 트리들에서 잰 평균 경로 길이, c(m)은 표본 m개짜리 이진 탐색 트리에서 탐색이 실패할 때의 평균 경로 길이다.

c(m)으로 나누는 이유는 무엇인가?

  1. 트리마다 무작위 분할이 달라 경로 길이의 분산이 큰데 그 흔들림을 평균으로 눌러주기 위해서다.

    흔들림을 줄이는 것은 트리를 여러 개 만들어 평균을 내는 단계가 담당한다. 이 나눗셈은 다른 일을 한다.

  2. 경로 길이가 정수라 연속값으로 바꾸어야 지수 함수에 넣을 수 있기 때문이다.

    평균을 내는 순간 이미 연속값이고, 정수라도 지수 함수에 넣는 데 문제가 없다.

  3. 정답표본이 많아지면 트리가 자연히 깊어지므로 그 효과를 상쇄해 점수를 데이터 크기와 무관하게 만들기 위해서다.

    정규화가 없으면 같은 정도로 고립된 점이라도 데이터가 클수록 큰 경로 길이를 갖는다. 나눠 주면 경로가 짧을수록 점수가 1에 가까워지는 해석이 데이터 크기와 상관없이 유지된다.

  4. 이상 점수를 확률로 해석할 수 있도록 전체 합을 1로 맞추기 위해서다.

    점수의 합이 1이 되지 않고 확률도 아니다. 상대적인 고립 정도를 나타내는 값이다.

해설

Isolation Forest는 특성 하나를 무작위로 고르고 그 값 범위에서 분할 지점을 무작위로 잡는 일을 한 점만 남을 때까지 반복한다. 이상치는 다른 점들과 떨어져 있어 몇 번 자르지 않아도 혼자 남고, 밀집 지역의 점은 이웃을 떼어내느라 훨씬 많은 분할을 거친다. 한 트리의 결과는 무작위 분할에 좌우되므로 트리 여러 개의 평균 경로 길이를 쓴다. 그런데 표본이 많아지면 트리가 자연히 깊어져 경로 길이가 함께 커지므로, 같은 크기의 이진 탐색 트리에서 기대되는 평균 경로 길이로 나눠 그 효과를 상쇄한다. 그 결과 경로가 짧을수록 점수가 1에 가까워지는 해석이 데이터 크기와 무관하게 유지된다. 분포를 전혀 가정하지 않고 빠르며 파라미터가 적어 기준선으로 먼저 돌려보기 좋은 방법이다.

이 내용 다시 읽기 →

분산이 가장 큰 방향으로 축을 다시 잡는 PCA

원문 읽기 →
개념 확인구조

분산을 최대로 보존하는 방향이 곧 사영 오차를 최소로 만드는 방향인 이유는 무엇인가?

  1. 분산이 큰 방향에는 점이 많이 몰려 있어 그쪽으로 사영하면 겹치는 점이 줄어들기 때문이다.

    분산이 크다는 것은 점이 넓게 퍼져 있다는 뜻이지 많이 몰려 있다는 뜻이 아니다. 겹침의 개수와도 무관하다.

  2. 고유값이 큰 방향일수록 공분산 행렬의 조건수가 좋아져 계산 오차가 줄어들기 때문이다.

    조건수는 수치 계산의 안정성 이야기이고 사영 오차와는 다른 층위다.

  3. 정답점까지의 거리 제곱이 축 방향 성분과 수직 성분의 제곱 합이라 한쪽이 커지면 다른 쪽이 작아지기 때문이다.

    피타고라스 정리에서 곧장 나온다. 원점에서 점까지의 거리는 어느 축을 잡든 고정이므로 축 위의 몫을 키우면 잘려 나가는 몫이 자동으로 줄어든다.

  4. 주성분들이 서로 직교하므로 한 축의 오차가 다른 축의 오차와 상쇄되기 때문이다.

    직교성은 축들이 겹치지 않는다는 성질일 뿐이고 오차가 서로 상쇄되지도 않는다.

해설

센터링된 데이터에서 원점부터 한 점까지의 거리 제곱은 어느 축을 잡든 고정이고, 그 값이 축 방향 성분의 제곱과 수직 성분의 제곱의 합으로 갈린다. 축 위의 몫을 키우면 잘려 나가는 몫이 자동으로 줄어드는 관계라, 분산을 최대한 보존한다와 가장 적게 뭉갠다는 같은 말이 된다. PCA는 이 방향을 첫 축으로 잡고, 거기에 직교하면서 남은 분산이 가장 큰 방향을 다음 축으로 잡는 식으로 이어간다. 피처가 d개면 주성분도 최대 d개 나오고 서로 전부 직교하며, 그중 분산이 큰 상위 몇 개만 남기면 차원이 줄어든다. 각 주성분이 전체 분산의 몇 퍼센트를 설명하는지는 고유값의 비율로 바로 읽히고, 이 값이 성분 수를 정하는 기준이 된다.

이 내용 다시 읽기 →
상황 적용설계
두 데이터에 PCA를 걸려 한다. A) 연봉(원), 근속 연수, 방문 횟수 B) 같은 계측기에서 나온 12개 채널의 전압값

표준화를 각각 어떻게 다뤄야 하는가?

  1. 둘 다 표준화한다. PCA는 언제나 표준화된 입력을 전제로 유도된 기법이다.

    PCA의 유도에는 표준화가 들어 있지 않다. 센터링만 필요하고 스케일 조정은 데이터의 성격에 따른 선택이다.

  2. 정답A는 표준화하고 B는 그대로 둔다. 피처끼리 분산을 비교하는 것이 의미 있는지가 기준이다.

    단위가 제각각이면 가장 큰 숫자를 쓰는 피처가 첫 축을 통째로 차지한다. 반대로 단위가 처음부터 통일된 데이터에서는 채널 사이의 분산 차이 자체가 정보이므로 표준화가 그것을 지운다.

  3. 둘 다 그대로 둔다. 표준화는 각 축의 분산을 1로 만들어 주성분의 순서를 없애 버린다.

    각 피처의 분산이 1이 되어도 피처 사이의 상관이 남아 있어 주성분마다 고유값이 다르게 나온다. 순서는 그대로 매겨진다.

  4. A는 그대로 두고 B는 표준화한다. 값의 범위가 넓은 쪽이 정보를 더 많이 담고 있기 때문이다.

    값의 범위가 넓은 것은 단위를 어떻게 적었느냐의 결과일 수 있다. 연봉을 만원 단위로 바꿔 적기만 해도 결과가 통째로 달라진다.

해설

PCA는 분산이 큰 방향을 찾는데 분산의 크기는 단위에 딸려 있다. 연봉을 원 단위로 적으면 분산이 압도적으로 커져 첫 주성분이 사실상 연봉 축 그 자체가 되고, 같은 데이터를 만원 단위로 바꿔 적기만 해도 결과가 달라진다. 그래서 단위가 제각각인 데이터에서는 각 피처를 평균 0, 표준편차 1로 맞춘 뒤 PCA를 거는 것이 기본이고, 이것은 공분산 행렬 대신 상관 행렬을 분해하는 것과 같다. 다만 이미지 픽셀 밝기나 같은 계측기의 여러 채널처럼 단위가 처음부터 통일된 데이터에서는 피처 간 분산 차이 자체가 정보라 표준화가 오히려 그것을 지운다. 판단 기준은 하나다. 피처끼리 분산을 비교하는 것이 의미 있는 데이터인가.

이 내용 다시 읽기 →
상황 적용진단
유방암 데이터에서 주성분 수를 바꿔가며 교차 검증했다. 주성분 10개 로지스틱 회귀 0.9807 랜덤 포레스트 0.9455 원본 30개 로지스틱 회귀 0.9807 랜덤 포레스트 0.9561 로지스틱 회귀는 원본과 같아졌는데 랜덤 포레스트는 어느 성분 수에서도 원본보다 낮다.

두 모델이 다르게 반응한 이유는 무엇인가?

  1. 트리는 표준화에 불변인데 PCA 앞단의 표준화가 트리의 분할 기준을 흐트러뜨렸기 때문이다.

    표준화는 값의 순서를 바꾸지 않으므로 트리의 분할을 흐트러뜨리지 않는다. 문제는 표준화가 아니라 축의 회전이다.

  2. 랜덤 포레스트가 주성분 사이의 직교성을 활용하지 못해 특성 후보 추출이 편향되기 때문이다.

    후보 추출은 어떤 특성 집합에서도 균등하게 이루어진다. 직교성 자체가 트리에 불리하게 작용하지도 않는다.

  3. PCA가 레이블을 보지 않으므로 트리처럼 비선형 모델에서는 분산이 큰 축이 항상 무의미하기 때문이다.

    레이블을 보지 않는 것은 두 모델 모두에 해당하는데 로지스틱 회귀에서는 잘 통했다. 항상 무의미한 것도 아니다.

  4. 정답트리는 축에 수직인 분할로 경계를 만드는데 PCA가 축을 회전시켜 원래 깔끔하던 경계를 계단으로 근사해야 하기 때문이다.

    원래 피처 하나로 갈리던 경계가 회전 후에는 여러 번의 분할을 요구한다. 게다가 트리는 쓸모없는 피처를 알아서 안 고르므로 차원 축소로 얻을 이득도 적다.

해설

선형 모델과 PCA는 궁합이 좋다. 둘 다 피처의 선형 결합만 보기 때문에, 상관이 높은 피처들을 직교하는 축으로 다시 잡아주면 정보를 잃지 않고 입력만 줄어든다. 여기서도 주성분 10개로 원본 30개와 같은 정확도에 닿았다. 트리 계열은 반대다. 축에 수직인 분할로 경계를 만드는데 PCA가 축을 회전시키면 원래 피처 하나로 깔끔하게 갈리던 경계를 여러 번의 계단으로 근사해야 한다. 게다가 트리는 쓸모없는 피처를 알아서 고르지 않으므로 차원을 줄여 얻을 이득도 적다. 차원 축소를 붙일지 판단할 때는 뒤에 오는 모델이 축의 방향에 의존하는지부터 보는 것이 순서다.

이 내용 다시 읽기 →
분석과 판단구조
3차원 공간에서 돌돌 말린 2차원 종이 모양의 데이터(Swiss Roll)에 PCA를 걸어 2차원으로 줄였다. 결과를 보니 종이 위에서는 한참 떨어져 있던 두 점이 이웃으로 찍혀 있다.

왜 이런 일이 생기는가?

  1. 정답PCA가 찾는 축은 직선 방향뿐이라 어느 방향으로 사영해도 말린 층들이 서로 겹쳐 찍히기 때문이다.

    데이터가 휘어진 면 위에 놓여 있으면 직선 축으로는 그 면을 펼 수 없다. 성분 수를 늘려도 축이 직선이라는 사실은 그대로다.

  2. 성분 수가 2개로 부족해 정보가 잘려 나간 것이므로 3개로 늘리면 해소된다.

    원래 차원이 3이므로 3개를 다 쓰면 아무것도 줄이지 못한다. 줄이면서 구조를 살리는 것이 목적인데 직선 축으로는 그것이 불가능하다.

  3. 표준화를 하지 않아 한 축이 첫 주성분을 독점했기 때문이다.

    세 축의 단위가 같은 데이터라 표준화가 원인이 아니다. 표준화를 해도 같은 문제가 남는다.

  4. PCA가 레이블을 보지 않아 색으로 구분되는 구조를 축에 반영하지 못했기 때문이다.

    레이블을 봐도 직선 축으로는 말린 면을 펼 수 없다. 지도 학습형 차원 축소를 써도 같은 한계에 부딪힌다.

해설

PCA가 찾는 것은 직선 방향이다. 데이터가 휘어진 면 위에 놓여 있으면 어느 직선 방향으로 사영해도 말린 층들이 서로 겹쳐 찍히고, 원래 면 위에서 멀리 떨어져 있던 점들이 이웃으로 보인다. 커널 PCA는 데이터를 커널 함수로 더 높은 차원에 올린 뒤 거기서 PCA를 해서, 원래 공간에서 보면 곡선 축을 찾은 셈이 되어 말린 구조를 어느 정도 편다. 대신 표본 수의 제곱 크기 행렬을 만들어야 해서 데이터가 커지면 급격히 무거워지고 커널 파라미터에 결과가 크게 좌우된다. 비선형 구조를 눈으로 확인하는 것이 목적이라면 다른 시각화 전용 기법이 낫고, 모델 파이프라인에 넣을 차원 축소는 여전히 PCA가 표준이다.

이 내용 다시 읽기 →
상황 적용함정
누적 설명 분산 95%를 기준으로 차원을 줄였는데 분류 정확도가 눈에 띄게 떨어졌다.

가장 먼저 의심해야 할 것은 무엇인가?

  1. 95%가 너무 낮은 기준이므로 99%로 올리면 대부분 해결된다.

    기준을 올리면 버리는 축이 줄어 완화될 수는 있지만 원인의 설명이 아니다. 분산이 아주 작은 축에 신호가 있으면 99%로도 잘린다.

  2. 표준화를 빠뜨려 한 피처가 첫 축을 독점한 것이므로 스케일링을 확인해야 한다.

    확인할 값이기는 하지만 그 경우 설명 분산 비율의 분포가 극단적으로 치우쳐 곧바로 눈에 띈다.

  3. 정답PCA가 레이블을 보지 않으므로 분류에 결정적인 신호가 분산이 작은 축에 실려 버려졌을 수 있다.

    분산이 크다는 것과 예측에 유용하다는 것은 다른 이야기다. 두 클래스를 가르는 방향이 데이터 전체의 퍼짐과 무관할 수 있다.

  4. 주성분끼리 직교해 다중공선성이 사라지면서 모델이 쓰던 상호작용 정보가 없어졌기 때문이다.

    다중공선성이 사라지는 것은 대체로 이득이다. 직교화 자체가 정보를 지우지는 않는다.

해설

PCA는 레이블을 보지 않고 축을 잡는다. 분산이 크다고 해서 예측에 유용한 방향이라는 보장이 없으므로, 분류에 결정적인 신호가 분산이 작은 축에 실려 있으면 PCA는 그 축부터 버린다. 차원을 줄였는데 성능이 떨어졌다면 이 가능성을 먼저 의심하는 편이 좋다. 대응은 두 갈래다. 하나는 기준을 올려 더 많은 축을 남기는 것이고, 다른 하나는 레이블을 쓰는 차원 축소나 피처 선택 쪽으로 옮기는 것이다. 여기서 PCA와 피처 선택이 갈리는 지점도 분명해진다. 피처 선택은 남은 피처의 의미가 그대로 보존되는 대신 버린 피처의 정보가 사라지고, PCA는 분산 기준으로는 최적이지만 새 축이 무엇인지 설명하기 어려워진다.

이 내용 다시 읽기 →
분석과 판단구조
PCA의 수식은 공분산 행렬의 고유값 분해로 쓰이지만 sklearn은 공분산 행렬을 만들지 않고 센터링된 데이터를 곧바로 특이값 분해한다.

이렇게 도는 주된 이유는 무엇인가?

  1. 특이값 분해가 고유값 분해보다 계산 복잡도가 낮아 언제나 더 빠르기 때문이다.

    표본 수가 아주 많고 차원이 작으면 공분산 경로가 오히려 가벼울 수 있다. 속도가 유일한 근거는 아니다.

  2. 특이값 분해는 센터링 없이도 동작하므로 전처리 한 단계를 줄일 수 있기 때문이다.

    센터링은 여전히 필요하다. 평균을 빼지 않으면 원점에서 얼마나 떨어져 있는지와 얼마나 퍼져 있는지가 뒤섞인다.

  3. 정답공분산 행렬을 명시적으로 계산하면 조건수가 제곱이 되어 작은 고유값 쪽의 정밀도가 먼저 무너지기 때문이다.

    곱을 만드는 순간 수치적으로 잃는 자릿수가 두 배가 된다. 피처가 수만 개면 그 행렬 자체가 메모리에 들어가지 않는 문제도 겹친다.

  4. 특이값 분해가 고유벡터의 부호까지 유일하게 정해 주어 결과의 재현성이 보장되기 때문이다.

    부호는 어느 경로에서도 유일하게 정해지지 않는다. 구현마다 부호를 맞추는 별도의 규칙을 둔다.

해설

고유값 분해는 PCA가 무엇을 하는지 설명하는 언어이고 계산은 특이값 분해가 맡는다. 센터링된 데이터를 분해하면 오른쪽 특이벡터가 곧 공분산 행렬의 고유벡터이고 고유값은 특이값의 제곱을 표본 수에서 1을 뺀 값으로 나눈 것이라, 두 경로의 결과가 같다. 그런데도 굳이 특이값 분해로 도는 이유는 수치 안정성이다. 공분산 행렬을 명시적으로 계산하면 곱을 만드는 순간 조건수가 제곱이 되어 작은 고유값 쪽의 정밀도가 먼저 무너진다. 뒤쪽 주성분을 남길 생각이라면 이 차이가 실제로 결과에 나타난다. 여기에 더해 피처가 수만 개면 정사각 행렬 자체가 메모리에 들어가지 않는 문제도 겹친다.

이 내용 다시 읽기 →

밀도로 묶는 DBSCAN과 확률로 묶는 GMM

원문 읽기 →
개념 확인구조
min_samples=5로 DBSCAN을 돌렸다. 어떤 점 P는 자기 반경 안에 자신을 포함해 두 점밖에 없지만, 그 두 점 중 하나가 핵심점이다.

P는 어떻게 처리되는가?

  1. 이웃 수가 부족하므로 잡음으로 분류되어 -1 레이블을 받는다.

    잡음이 되는 조건은 어떤 핵심점의 반경에도 들어가지 않는 것이다. P는 핵심점의 반경 안에 있으므로 잡음이 아니다.

  2. 정답경계점이 되어 그 핵심점이 속한 클러스터의 번호를 받는다.

    자신은 핵심점 조건에 못 미치지만 어떤 핵심점의 반경 안에 있으므로 그 클러스터에 딸려 들어간다. 다만 자기 이웃을 다시 끌어오지는 못한다.

  3. 핵심점의 반경 안에 있으므로 P도 핵심점이 되어 자기 이웃까지 클러스터로 끌어온다.

    핵심점 여부는 자기 반경 안의 점 개수로만 정해진다. 다른 핵심점과 가깝다는 이유로 핵심점이 되지 않는다.

  4. 이웃 수가 절반에 미치지 못하므로 새 클러스터의 시작점이 되어 별도 번호를 받는다.

    새 클러스터는 핵심점에서만 시작한다. 조건에 미달한 점이 클러스터를 열지 못한다.

해설

DBSCAN은 반경과 그 안의 최소 점 개수 두 값으로 모든 점을 셋으로 나눈다. 자기 반경 안의 점이 기준 이상이면 핵심점, 자신은 핵심점이 아니지만 어떤 핵심점의 반경 안에 있으면 경계점, 어느 핵심점의 반경에도 들어가지 않으면 잡음점이다. 경계점은 클러스터에 속하되 자기 이웃을 다시 끌어오지는 못한다는 점이 핵심이다. 클러스터를 넓히는 연쇄는 핵심점을 통해서만 이어지므로 경계점에서 성장이 멈춘다. 한 가지 짚어둘 것은 경계점의 소속이 유일하게 정해지지 않는다는 점이다. 서로 다른 두 클러스터의 핵심점 모두에서 도달 가능하면 먼저 도달한 쪽이 가져가므로, 데이터 순서를 바꾸면 경계점 몇 개의 레이블이 달라질 수 있다.

이 내용 다시 읽기 →
상황 적용진단
촘촘한 덩어리 둘과 성긴 덩어리 하나가 섞인 데이터에 DBSCAN을 돌렸다. eps를 줄이면 성긴 덩어리가 통째로 잡음이 된다 eps를 늘리면 촘촘한 두 덩어리가 하나로 합쳐진다

이 상황의 원인과 대응은 무엇인가?

  1. min_samples가 너무 높아 성긴 덩어리가 핵심점을 만들지 못하는 것이므로 그 값을 낮춰야 한다.

    낮추면 성긴 쪽이 살아나지만 촘촘한 쪽에서는 잡음까지 핵심점이 된다. 반경 하나로 두 밀도를 담을 수 없다는 구조는 그대로다.

  2. 데이터의 스케일이 어긋나 거리가 왜곡된 것이므로 표준화를 먼저 적용해야 한다.

    표준화는 축 사이의 불균형을 잡을 뿐 같은 공간 안의 밀도 차이를 없애지 못한다.

  3. 클러스터 수를 알 수 없어 생긴 문제이므로 K를 지정하는 알고리즘으로 바꿔야 한다.

    여기서 어려운 것은 개수가 아니라 밀도 수준이 여럿이라는 점이다. 개수를 지정해도 모양이 임의라면 중심점 기반으로 풀리지 않는다.

  4. 정답반경이 데이터 전체에 하나뿐이라 여러 밀도 수준을 동시에 담을 수 없는 것이므로 계층적 밀도 기반 방법으로 옮겨야 한다.

    고정된 반경 하나 대신 여러 밀도 수준에서 클러스터 계층을 만들고 밀도 변화에 가장 오래 버티는 클러스터를 골라내는 방법이 이 문제를 겨냥한 확장이다. 정할 값도 최소 클러스터 크기 하나로 줄어든다.

해설

DBSCAN의 약점은 반경이 데이터 전체에 하나뿐이라는 데서 나온다. 촘촘한 쪽에 맞춰 줄이면 성긴 덩어리가 통째로 잡음이 되고, 성긴 쪽에 맞춰 늘리면 촘촘한 덩어리들이 합쳐진다. 하나의 반경으로 여러 밀도 수준을 동시에 담을 방법이 없다. HDBSCAN은 이 문제를 겨냥한 확장으로, 고정된 반경 하나를 쓰는 대신 여러 밀도 수준에서 클러스터 계층을 만들고 그중 밀도 변화에 가장 오래 버티는 클러스터를 골라낸다. 정할 값도 최소 클러스터 크기 하나로 줄어들고 sklearn 1.3부터 기본으로 들어와 있으므로, 밀도 기반 클러스터링을 실무에 쓸 생각이라면 이쪽을 먼저 시도해 보는 편이 낫다. 다만 차원이 높아지면 둘 다 약해지는데 거리 자체가 변별력을 잃기 때문이라 알고리즘 교체로는 해결되지 않는다.

이 내용 다시 읽기 →
상황 적용구조

GMM이 K-Means의 일반화라고 말할 수 있는 근거는 무엇인가?

  1. 정답모든 공분산을 같은 구형으로 묶고 분산을 0으로 보내면 정확히 K-Means가 된다.

    EM의 두 단계가 K-Means의 할당과 평균 갱신에 그대로 대응하고, 분산이 0으로 가면 소속 확률이 최근접 컴포넌트에 1로 쏠려 차이가 사라진다. sklearn이 GMM을 K-Means 결과로 초기화하는 것도 이 관계 때문이다.

  2. GMM이 내부적으로 K-Means를 여러 번 돌린 뒤 그 결과를 가우시안으로 근사하기 때문이다.

    초기화에 쓰는 것과 근사하는 것은 다르다. 초기화 이후에는 독자적인 절차로 파라미터를 갱신한다.

  3. GMM의 컴포넌트 수를 1로 두면 K-Means의 중심점 하나와 같아지기 때문이다.

    특수한 한 경우가 일치한다고 일반화라 부르지 않는다. 관계는 임의의 컴포넌트 수에서 성립해야 한다.

  4. 두 방법 모두 목적값이 단조 변화하며 지역 최적에서 멈추기 때문이다.

    수렴 성질을 공유한다는 것만으로 한쪽이 다른 쪽의 일반화가 되지 않는다. 필요한 것은 파라미터를 특수화하면 정확히 같아진다는 관계다.

해설

GMM은 데이터가 여러 가우시안에서 섞여 나왔다고 보고 각 컴포넌트에 중심, 공분산, 전체에서 차지하는 비율을 준다. EM은 현재 파라미터로 각 점이 어느 컴포넌트에서 나왔을 사후 확률을 계산하고, 그 확률을 가중치로 삼아 파라미터를 다시 맞추는 두 단계를 번갈아 돈다. 이 구조가 K-Means와 겹치는 것은 우연이 아니다. 할당 단계가 앞 단계에, 평균 갱신이 뒤 단계에 대응하며 차이는 소속이 확률이냐 0과 1이냐뿐이다. 모든 공분산을 같은 구형으로 묶고 분산을 0으로 보내면 확률이 가장 가까운 컴포넌트에 1로 쏠려 정확히 K-Means가 된다. sklearn이 GMM을 K-Means 결과로 초기화하는 기본 설정도 이 관계에서 나온다.

이 내용 다시 읽기 →
분석과 판단설계
특성 40개, 표본 600개짜리 데이터에 GaussianMixture(n_components=5, covariance_type='full')를 돌렸다. 로그 가능도는 매우 높은데 새 데이터에서 밀도 추정이 엉망이다.

무엇을 바꿔야 하는가?

  1. 컴포넌트 수를 늘려 각 컴포넌트가 담당하는 영역을 좁혀야 한다.

    컴포넌트를 늘리면 컴포넌트당 표본이 더 줄어 상황이 나빠진다. 방향이 반대다.

  2. EM 반복 횟수를 늘려 로그 가능도가 완전히 수렴하게 해야 한다.

    이미 훈련 로그 가능도가 매우 높다. 수렴 부족이 아니라 훈련 데이터에 지나치게 맞춘 상태다.

  3. 정답공분산 타입을 대각이나 구형으로 낮춰 추정할 파라미터 수를 줄여야 한다.

    완전한 공분산은 컴포넌트마다 차원의 제곱에 가까운 값을 추정해야 해서 특성 40개면 컴포넌트 하나에 820개다. 표본 600개로는 감당되지 않아 행렬이 특이해지기 쉽다.

  4. 초기화를 무작위로 바꿔 K-Means가 만든 편향을 없애야 한다.

    초기화 방식은 어느 지역 최적에 도달하는지를 바꿀 뿐이다. 파라미터 수와 표본 수의 불균형은 그대로다.

해설

공분산 타입이 정하는 것은 각 컴포넌트가 표현할 수 있는 모양과 추정해야 할 파라미터 수다. 완전한 공분산은 컴포넌트마다 차원과 차원 더하기 1의 곱을 2로 나눈 만큼의 값을 추정해야 하므로 특성 40개면 컴포넌트 하나에 820개다. 차원이 높거나 표본이 적으면 행렬이 특이해지기 쉽고, sklearn이 대각 성분에 작은 값을 더해 두는 것도 이 때문이다. 차원 대비 표본이 부족하면 대각 성분만 쓰는 쪽부터 시작하는 것이 안전하다. 이 선택은 컴포넌트 수와 함께 정보 기준으로 정리할 수 있다. 공분산 타입을 바꾸면 파라미터 수가 통째로 달라지므로 컴포넌트 수와 공분산 타입을 같이 놓고 정보 기준을 비교하면 두 선택을 한 번에 마무리할 수 있다.

이 내용 다시 읽기 →
상황 적용운영
probs = gmm.predict_proba(X)
uncertain = probs.max(axis=1) < 0.7
print(uncertain.sum())

레이블 대신 확률을 통째로 받아 얻는 것은 무엇인가?

  1. 확률의 최댓값이 곧 예측 신뢰도이므로 이 값으로 모델의 전체 정확도를 추정할 수 있다.

    정답이 없는 문제라 정확도라는 개념 자체가 성립하지 않는다. 확률은 모델의 가정 안에서의 소속도이지 정답과의 일치도가 아니다.

  2. 확률이 낮은 점을 제거하면 클러스터가 깨끗해져 로그 가능도가 올라간다.

    제거로 지표를 올리는 것은 데이터가 아니라 숫자를 손보는 일이다. 실제로는 그 점들이야말로 들여다볼 대상이다.

  3. 정답어디에도 확신이 없는 점을 골라낼 수 있고 그 목록이 그대로 검토 대상이 된다.

    하드 클러스터링에서는 애매하다는 사실 자체가 지워진다. 사람에게 레이블링을 맡길 샘플을 고르는 능동 학습이 대표적인 용처다.

  4. 확률을 임계값으로 잘라 클러스터 수를 자동으로 결정할 수 있다.

    컴포넌트 수는 여전히 입력으로 받아야 한다. 확률로는 개수를 정할 수 없고 정보 기준 같은 별도의 척도가 필요하다.

해설

K-Means와 DBSCAN은 한 점을 정확히 한 클러스터에 넣는다. 경계가 흐릿한 데이터에서는 그 강제 할당이 정보를 지운다. 한쪽 성향이 6할, 다른 쪽이 4할인 점을 어느 하나에 밀어 넣으면 애매하다는 사실 자체가 사라지기 때문이다. GMM이 주는 레이블은 소속 확률의 최댓값 위치일 뿐이므로 값을 통째로 받으면 어디에도 확신이 없는 점을 골라낼 수 있고, 이 목록은 그대로 검토 대상이 된다. 사람에게 레이블링을 맡길 샘플을 고르는 능동 학습이 대표적인 용처다. 클러스터링에는 채점할 정답이 없으므로 남는 일은 내가 세운 가정이 이 데이터에 맞았는지 확인하는 것뿐이고, 확률은 그 확인에 쓸 수 있는 몇 안 되는 재료다.

이 내용 다시 읽기 →
분석과 판단구조
GMM의 컴포넌트 수를 고르는 두 정보 기준이다. AIC = -2·lnL + 2p BIC = -2·lnL + p·ln n p는 파라미터 수, n은 표본 수다.

표본이 수천 건일 때 두 기준이 다른 컴포넌트 수를 고르는 방향은 어느 쪽인가?

  1. 표본이 늘어날수록 두 기준의 벌점이 함께 커지므로 둘 다 같은 컴포넌트 수로 수렴한다.

    한쪽의 벌점만 표본 수에 따라 커진다. 다른 쪽의 계수는 표본 수와 무관하게 고정이다.

  2. 정답BIC의 벌점이 더 무거우므로 BIC 쪽이 더 적은 컴포넌트를 고른다.

    표본이 조금만 커져도 로그 값이 2를 넘으므로 파라미터 하나당 벌점이 BIC 쪽에서 더 크다. 둘 중 하나를 기본으로 쓴다면 이쪽이 무난하다.

  3. AIC가 로그 가능도를 두 배로 반영하므로 AIC 쪽이 더 적은 컴포넌트를 고른다.

    로그 가능도 항은 두 기준에서 동일하다. 갈리는 것은 파라미터에 붙는 벌점의 계수뿐이다.

  4. 표본이 클수록 로그 가능도가 커져 벌점이 상대적으로 무의미해지므로 두 기준 모두 최대 컴포넌트 수를 고른다.

    벌점도 파라미터 수에 비례해 함께 커지므로 무의미해지지 않는다. 그래서 두 기준 모두 어느 지점에서 최솟값을 갖는다.

해설

두 정보 기준은 로그 가능도에 파라미터 수에 대한 벌점을 붙인 값이고, 갈리는 곳은 그 벌점의 계수뿐이다. 표본이 8 정도만 넘어도 로그 값이 2를 넘으므로 BIC의 벌점이 더 무겁고, 그만큼 컴포넌트 수를 적게 고른다. 둘 중 하나를 기본으로 쓴다면 BIC 쪽이 무난하다. 클러스터링에서 이 기준을 쓰는 이유는 GMM이 확률 모형이라 가능도가 정의되기 때문이다. 엘보우나 실루엣 같은 기하학적 기준 대신 모형 선택의 언어를 그대로 쓸 수 있다. 공분산 타입을 바꾸면 파라미터 수가 통째로 달라지므로 컴포넌트 수와 공분산 타입을 함께 격자로 훑어 최솟값을 찾으면 두 선택을 한 번에 정리할 수 있다.

이 내용 다시 읽기 →

고차원 데이터를 2차원에 펼치는 t-SNE와 UMAP

원문 읽기 →
개념 확인함정
t-SNE로 그린 그림에서 A 군집이 B보다 C 쪽에 가까이 놓여 있고, D 군집의 얼룩이 다른 군집보다 두 배쯤 넓다.

이 그림에서 읽어도 되는 것은 무엇인가?

  1. A와 C가 원본 공간에서도 B보다 서로 가깝다는 것.

    군집들의 상대 위치는 초기값과 최적화 경로에 따라 얼마든지 달라진다. 목적 함수가 먼 것을 가깝게 그리는 실수를 거의 벌하지 않기 때문이다.

  2. 정답같은 얼룩 안에 뭉친 점들이 원본 공간에서도 서로 닮았다는 것.

    이 두 기법이 지키는 것은 누가 누구의 이웃인가 하나뿐이다. 거리도 밀도도 축의 방향도 지키지 않으므로 믿을 수 있는 것은 함께 뭉쳤다는 사실까지다.

  3. D 군집이 원본 공간에서 다른 군집보다 분산이 크다는 것.

    점마다 이웃을 재는 척도를 따로 잡아 밀도를 정규화하므로 원본에서 빽빽하던 군집과 퍼져 있던 군집이 비슷한 크기로 나온다.

  4. 군집 사이의 빈 공간에는 실제로 데이터가 없다는 것.

    빈 공간의 넓이에도 의미가 없다. 배치의 결과일 뿐 그 영역에 데이터가 없다는 뜻이 아니다.

해설

t-SNE와 UMAP이 지키는 것은 이웃 관계 하나다. 군집 사이의 거리에는 의미가 없다. 목적 함수가 멀리 있던 것을 가깝게 배치하는 실수를 거의 벌하지 않으므로 군집들의 상대 위치는 초기값과 최적화 경로에 따라 달라진다. 군집의 크기에도 의미가 없다. 점마다 이웃을 재는 척도를 따로 잡아 밀도를 정규화하기 때문에 원본에서 빽빽하던 군집과 넓게 퍼져 있던 군집이 비슷한 크기의 얼룩으로 나온다. 빈 공간의 넓이도 마찬가지다. 축의 방향까지 포함해서, 목적 함수가 점들 사이의 거리만 보므로 임베딩을 통째로 회전시켜도 손실이 그대로다. x축이 무엇을 뜻하느냐는 질문 자체가 성립하지 않는다.

이 내용 다시 읽기 →
상황 적용구조

t-SNE가 저차원에서 가우시안 대신 꼬리가 두꺼운 t-분포를 쓰는 이유는 무엇인가?

  1. t-분포가 이상치에 강해 멀리 떨어진 점이 배치를 흔들지 못하게 막기 때문이다.

    강건성이 목적이 아니다. 꼬리가 두꺼운 성질이 여기서는 이상치 방어가 아니라 배치 공간을 벌리는 데 쓰인다.

  2. t-분포는 자유도를 조절할 수 있어 perplexity와 함께 세밀한 튜닝이 가능하기 때문이다.

    자유도는 1로 고정해 쓴다. 조절 가능성 때문에 고른 분포가 아니다.

  3. 고차원과 저차원에서 서로 다른 분포를 써야 KL 발산이 0으로 수렴하지 않기 때문이다.

    발산이 0에 가까워지는 것은 오히려 원하는 방향이다. 분포를 일부러 어긋나게 할 이유가 없다.

  4. 정답2차원 평면에 이웃을 늘어놓을 자리가 부족해 중간 거리의 점들에게 더 멀리 떨어질 여유를 주기 위해서다.

    고차원 공간은 넓어 한 점 주위에 이웃을 여유 있게 둘 수 있지만 평면에는 그만한 자리가 없다. 꼬리가 두꺼우면 같은 확률값을 만드는 데 필요한 거리가 더 멀어져 군집이 서로 벌어진다.

해설

고차원 공간은 넓어서 한 점 주위에 이웃을 여유 있게 늘어놓을 수 있지만 2차원 평면에는 그만한 자리가 없다. 적당히 떨어져 있던 이웃들을 억지로 밀어 넣으면 전부 한 덩어리로 뭉치는데, 이것이 crowding problem이다. 꼬리가 두꺼운 분포는 가우시안보다 같은 확률값을 만드는 데 필요한 거리가 더 멀어서, 중간 거리의 점들에게 더 멀리 떨어질 여유를 준다. 그 덕분에 군집이 서로 벌어져 선명하게 보인다. 이름의 t가 여기서 나온다. 대신 이 벌어짐은 시각적 분리를 위해 만들어진 것이지 원본 공간의 거리를 반영한 것이 아니다. 군집 사이의 간격을 정량적으로 읽으면 안 되는 이유가 목적 함수만이 아니라 이 분포 선택에도 있다.

이 내용 다시 읽기 →
상황 적용구조

UMAP의 전역 배치가 t-SNE보다 상대적으로 낫다고 말하는 근거는 무엇인가?

  1. 정답교차 엔트로피에는 떨어져 있어야 할 점이 가까이 놓인 경우를 벌하는 항이 하나 더 있기 때문이다.

    t-SNE의 KL 발산은 가까웠던 점을 떼어놓는 실수만 크게 벌하고 먼 것을 붙여놓는 실수는 거의 벌하지 않는다. 그래서 군집들의 상대 위치가 흐트러진다.

  2. UMAP이 그래프를 대칭화하므로 두 점 사이의 관계가 양방향으로 일치하기 때문이다.

    대칭화는 t-SNE도 결합 확률을 만들며 하는 일이다. 전역 배치의 차이를 만드는 요인이 아니다.

  3. UMAP이 근사 최근접 이웃을 쓰므로 먼 점까지 포함한 전체 거리 행렬을 계산하기 때문이다.

    근사 최근접 이웃은 오히려 가까운 이웃만 빠르게 찾는 기법이다. 전체 거리 행렬을 만들지 않는다.

  4. UMAP이 PCA 결과를 초기값으로 삼아 전역 구조를 미리 잡아두기 때문이다.

    UMAP의 기본 초기화는 PCA가 아니라 스펙트럴 임베딩이라 전제부터 틀렸다. 초기화가 전역 배치에 주는 영향은 실재하지만 목적 함수의 차이와는 별개다.

해설

두 알고리즘의 차이는 목적 함수 한 줄에서 갈린다. t-SNE의 KL 발산은 고차원에서 가까웠던 점을 저차원에서 떼어놓는 실수를 크게 벌하지만, 원래 멀었던 쌍은 앞에 곱해지는 가중치 자체가 작아 어디에 놓이든 손해가 거의 없다. 그래서 군집 내부는 잘 지켜지는 대신 군집들의 상대 위치가 초기값과 최적화 경로에 따라 흔들린다. UMAP이 쓰는 교차 엔트로피에는 떨어져 있어야 할 점이 가까이 놓인 경우를 벌하는 항이 하나 더 있어 이 부분이 어느 정도 잡힌다. 다만 상대적으로 낫다는 것이지 군집 사이 거리를 그대로 믿어도 된다는 뜻은 아니다. 거리를 정량적으로 논해야 하는 자리에서는 두 방법 모두 근거가 되지 못한다.

이 내용 다시 읽기 →
분석과 판단함정
64차원 가우시안 노이즈 1,000개를 넣고 잰 실루엣 점수다. t-SNE 평면을 K-Means로 8등분 0.32 원본 64차원을 K-Means로 8등분 0.01

이 비교가 경고하는 것은 무엇인가?

  1. t-SNE가 노이즈를 제거해 잠재된 군집 구조를 드러내므로 원본보다 신뢰할 만하다는 것이다.

    입력이 순수한 노이즈라 드러날 구조가 애초에 없다. 0.32는 만들어진 값이다.

  2. 실루엣 점수가 2차원에서 과대평가되므로 차원별로 보정한 지표를 써야 한다는 것이다.

    지표의 보정 문제가 아니다. 좌표 자체가 덩어리를 만들도록 재배치된 결과라 어떤 지표로 재도 같은 착시가 생긴다.

  3. 정답두 기법이 덩어리를 만들도록 설계되어 있어 구조가 없는 데이터에서도 그럴듯한 군집을 그려낸다는 것이다.

    그림에서 군집이 보인다는 사실은 데이터에 군집이 있다는 증거가 되지 못한다. 실제 군집은 원본 공간에서 찾고 그림은 그 결과를 눈으로 확인하는 데 써야 한다.

  4. K-Means가 2차원에서만 제대로 동작하므로 클러스터링 전에 반드시 차원을 줄여야 한다는 것이다.

    차원이 높으면 거리의 변별력이 떨어지는 문제는 있지만, 그 대응이 시각화 좌표로 클러스터링하는 것은 아니다.

해설

t-SNE와 UMAP은 애초에 덩어리를 만들도록 설계되어 있다. 구조가 전혀 없는 데이터를 넣어도 평면 위에서는 그럴듯한 군집이 그려지고, 그 좌표로 클러스터링을 하면 지표까지 좋게 나온다. 같은 데이터를 원본 공간에서 자르면 나눌 것이 없다는 정직한 값이 나온다. 그림에서 군집이 보인다는 사실 자체는 데이터에 군집이 있다는 증거가 되지 못한다. 순서를 지켜야 한다. 실제 군집은 원본 공간에서 중심점 기반이든 밀도 기반이든 클러스터링으로 찾고, 시각화는 그 결과를 눈으로 확인하는 용도로 쓴다. 같은 이유로 파라미터 하나에서만 보이는 패턴도 의심해야 한다. perplexity에 5와 30과 50을 각각 넣으면 그림이 눈에 띄게 달라지므로 여러 값에서 함께 살아남는 구조만 믿을 만하다.

이 내용 다시 읽기 →
상황 적용운영
t-SNE로 얻은 2차원 좌표를 분류 모델의 피처로 넣으려 한다. 매일 새 샘플이 수백 건씩 들어오는 서비스다.

왜 이 설계가 성립하지 않는가?

  1. 2차원으로는 정보량이 부족해 어떤 모델도 충분한 정확도를 내지 못하기 때문이다.

    정보량이 적은 것은 사실이지만 그것만이라면 성분 수를 늘려 대응할 수 있다. 여기서 막는 것은 다른 문제다.

  2. t-SNE 좌표가 확률값이라 모델 입력으로 쓰려면 별도의 정규화가 필요하기 때문이다.

    출력은 좌표이지 확률이 아니다. 정규화로 해결되는 문제도 아니다.

  3. 정답새 샘플을 기존 임베딩에 얹을 방법이 없어 전체를 다시 돌려야 하고 그때마다 좌표계가 갈아엎어지기 때문이다.

    sklearn의 구현에는 학습된 임베딩에 새 데이터를 투영하는 메서드가 없다. 다시 돌리면 이전 그림과 비교할 수 없는 좌표가 나오므로 모델이 배운 규칙도 무의미해진다.

  4. KL 발산이 볼록하지 않아 매번 다른 지역 최적에 도달하므로 시드를 고정해도 재현되지 않기 때문이다.

    시드를 고정하면 같은 입력에 대해서는 재현된다. 문제는 입력이 바뀌었을 때 좌표계가 통째로 달라진다는 점이다.

해설

sklearn의 t-SNE 구현에는 학습한 임베딩에 새 데이터를 얹는 메서드가 없고 전체를 한 번에 변환하는 경로만 있다. 새 샘플이 들어올 때마다 전체를 다시 돌려야 하는데 그러면 좌표계 자체가 달라져 이전 그림과 비교할 수 없고, 모델이 배운 규칙도 함께 무의미해진다. 그래서 t-SNE 좌표를 모델 입력으로 쓰는 것은 사실상 불가능하다. UMAP은 학습한 이웃 그래프를 그대로 두고 새 점의 자리만 찾는 구현이 붙어 있어 기존 좌표계에 얹을 수 있다는 점이 실용적인 차이다. 다만 축에 해석할 의미가 없다는 성질은 그대로다. 모델에 넣을 차원 축소는 매번 같은 결과를 내고 역변환도 되는 PCA가 표준이고, t-SNE와 UMAP은 사람이 볼 그림을 그리는 도구다.

이 내용 다시 읽기 →
분석과 판단설계
# 피처 800개짜리 데이터
X_50 = PCA(n_components=50, random_state=42).fit_transform(X_scaled)
X_2d = umap.UMAP().fit_transform(X_50)

800차원을 바로 넣지 않고 PCA를 앞에 두는 이유는 무엇인가?

  1. UMAP이 50차원 이하의 입력만 받도록 구현되어 있기 때문이다.

    입력 차원에 제한은 없다. 800차원을 그대로 넣어도 동작은 한다.

  2. PCA가 이미 이웃 관계를 보존하므로 UMAP이 할 일이 줄어 결과가 안정되기 때문이다.

    PCA가 보존하는 것은 분산이지 이웃 관계가 아니다. 휘어진 구조에서는 이웃이 뒤섞이기까지 한다.

  3. 정답노이즈 차원이 걷히면서 이웃 계산이 정확해지고 속도도 크게 빨라지기 때문이다.

    두 기법 모두 최근접 이웃 탐색 위에서 동작하는데 차원이 높으면 거리의 변별력이 떨어져 이웃 자체가 부정확해진다. sklearn 문서도 이 순서를 권한다.

  4. PCA를 거치면 축이 직교해 UMAP의 그래프가 대칭이 되기 때문이다.

    그래프의 대칭화는 UMAP이 내부에서 따로 수행하는 단계라 입력 축의 직교성과 무관하다.

해설

t-SNE와 UMAP은 모두 최근접 이웃 탐색 위에서 동작한다. 차원이 높으면 거리 자체의 변별력이 떨어져 누가 이웃인지부터 부정확해지고, 계산량도 함께 커진다. 피처가 수백 개를 넘으면 먼저 PCA로 50차원 정도까지 줄인 뒤에 넣는 것이 표준이고 sklearn 문서도 이 순서를 권한다. 노이즈 차원이 걷히면서 이웃 계산이 정확해지고 속도도 크게 빨라진다. 여기서 두 도구의 관계가 드러난다. PCA와 이 둘은 경쟁 관계가 아니라 순서 관계다. PCA는 매번 같은 결과를 내고 역변환이 되며 축이 원본 피처의 선형 결합이라 모델 파이프라인에 넣어도 되는 전처리 도구이고, t-SNE와 UMAP은 그 뒤에 붙어 사람이 볼 그림을 그리는 도구다.

이 내용 다시 읽기 →

이 페이지는 문항 품질을 점검하는 용도로도 씁니다. 한 화면에서 전부 훑어야 중복된 문항, 쏠린 난이도, 소거법으로 풀리는 선택지가 보입니다.

Thank You for Visiting My Blog, Have a Good Day 😆