Quiz / ML 분류 / 전체 문항
GitHub

ML 분류 전체 문항

로지스틱 회귀, KNN, 나이브 베이즈, SVM, 결정 트리. 문항과 선택지별 해설을 글 순서대로 나열했습니다.

36문항 · 글 6편
직접 풀어보기 →

선형 회귀에 시그모이드를 얹어 만드는 로지스틱 회귀

원문 읽기 →
개념 확인구조
공부 시간으로 합격 여부를 맞히려고 선형 회귀를 돌리고 0.5로 잘랐다. 예측값이 이렇게 나왔다. [-0.13, -0.01, 0.11, 0.23, 0.70, 0.93, 1.17]

이 출력을 확률로 읽을 수 없는 이유는 무엇인가?

  1. 예측값이 소수로 나와 클래스 레이블인 0과 1로 떨어지지 않기 때문이다.

    확률 모델의 출력도 소수다. 오히려 0과 1 사이의 소수가 나오는 것이 우리가 원하는 형태이고, 문제는 그 범위를 벗어난다는 데 있다.

  2. 일곱 개 중 몇 개를 틀렸으므로 확률로 쓸 만큼 정확하지 않기 때문이다.

    0.5로 자르면 일곱 개를 전부 맞힌다. 정확도가 아니라 값의 범위가 문제다.

  3. 선형 회귀는 회귀 모델이라 분류 문제에 수학적으로 적용할 수 없기 때문이다.

    적용 자체는 된다. 실제로 학습이 되고 값도 나오며, 다만 그 값을 확률로 해석할 근거가 없을 뿐이다.

  4. 정답출력이 음의 무한대에서 양의 무한대까지 열려 있어 -0.13이나 1.17이 나오기 때문이다.

    확률은 0과 1 사이에 있어야 하는데 선형 회귀의 출력에는 그런 제약이 없다. 여기서도 양 끝에서 범위를 벗어났고, 이 값을 확률이라 부를 수 없다.

해설

선형 회귀를 분류에 쓰면 두 곳이 깨진다. 하나는 출력 범위다. 음의 무한대에서 양의 무한대까지 열려 있어 1.17 같은 값이 나오는데 이것을 확률로 읽을 수 없다. 다른 하나는 이상치 민감도다. 직선 하나가 모든 점과의 제곱 오차를 줄이려 하므로 클래스 안쪽에서 멀리 떨어진 점 하나가 직선 전체를 끌고 간다. 20시간 공부한 합격자 한 명을 추가하면 직선이 눌려 평평해지고, 원래 잘 맞히던 4시간 합격자의 예측이 0.70에서 0.45로 떨어져 판정이 뒤집힌다. 두 문제를 한꺼번에 푸는 장치가 출력을 0과 1 사이에 가두는 시그모이드다.

이 내용 다시 읽기 →
상황 적용구조
승산은 일어날 확률을 일어나지 않을 확률로 나눈 값이고, 여기에 로그를 씌운 것이 로짓이다. logit(p) = log( p / (1-p) ) = wx + b 이 등식을 p에 대해 풀면 p = 1 / (1 + e^-(wx+b))가 된다.

이 유도가 시그모이드에 대해 말해주는 것은 무엇인가?

  1. 시그모이드는 여러 후보 중 계산이 가장 빠른 함수라 선택된 것이다.

    계산 비용으로 고른 함수가 아니다. 로짓을 선형으로 모델링하겠다고 정하는 순간 다른 선택의 여지 없이 이 형태가 나온다.

  2. 정답출력 범위를 맞추려고 갖다 붙인 것이 아니라 확률과 선형 모델을 잇는 다리다.

    확률은 0과 1 사이에 갇혀 있지만 로짓의 범위는 실수 전체라 선형 모델이 그대로 맞힐 수 있다. 그 등식을 확률에 대해 풀면 시그모이드가 그냥 튀어나오므로, 범위를 압축하려고 고른 함수가 아니라 유도의 결과다.

  3. 시그모이드를 쓰면 확률이 0과 1에 정확히 닿을 수 있게 된다.

    시그모이드의 치역은 0과 1을 포함하지 않는 열린 구간이다. 다만 부동소수점에서는 반올림으로 닿을 수 있어 구현에서는 작은 값을 더해 log 0을 막는다.

  4. 로짓을 쓰면 분류 문제가 회귀 문제로 완전히 바뀌어 같은 코드를 쓸 수 있다.

    모델이 맞히는 대상이 연속량인 로그 승산인 것은 맞지만 비용 함수는 갈아 끼워야 한다. 코드가 그대로 가지 않는다.

해설

확률은 0과 1 사이에 갇혀 있어 선형 모델로 직접 맞히기 어렵다. 승산을 취하면 0에서 무한대로, 로그까지 씌우면 실수 전체로 범위가 열리므로 그 값이라면 선형 모델이 그대로 다룰 수 있다. 이 등식을 확률에 대해 풀면 시그모이드가 유도의 결과로 나온다. 그래서 시그모이드는 범위를 압축하려고 갖다 붙인 함수가 아니라 확률과 선형 모델을 잇는 다리다. 여기서 계수 해석도 따라 나온다. 로지스틱 회귀의 계수는 확률에 대한 기여가 아니라 로그 승산에 대한 기여이므로, 계수에 지수를 씌운 값이 승산비가 된다. 모델 이름에 회귀가 붙은 것도 실제로 맞히는 대상이 이 연속량이기 때문이다.

이 내용 다시 읽기 →
상황 적용진단
선형 회귀로 분류하던 중 20시간 공부한 합격자 한 명을 데이터에 추가했다. 추가 전 0.5 통과 지점 x = 3.2, 4시간 합격자 예측 0.70 추가 후 0.5 통과 지점 x = 5.0, 4시간 합격자 예측 0.45

점 하나가 판정을 뒤집은 이유는 무엇인가?

  1. 정답직선이 모든 점과의 제곱 오차를 줄이려 하므로 멀리 떨어진 점이 직선을 끌고 간다.

    추가된 점은 이미 클래스 1 쪽에 있어 분류에는 아무 정보도 더하지 않는다. 그런데 선형 회귀는 그 점의 제곱 오차까지 줄이려 하므로 직선이 눌려 평평해지고, 0.5를 지나는 자리가 3.2에서 5.0으로 밀린다.

  2. 20이라는 값이 다른 값보다 훨씬 커서 수치 계산이 불안정해졌다.

    20은 계산을 흔들 만한 크기가 아니다. 문제는 정밀도가 아니라 그 점이 최소화 대상에 기여하는 방식이다.

  3. 데이터가 여덟 개로 늘어나 표본이 커진 만큼 예측이 보수적으로 변했다.

    표본이 늘어난다고 예측이 한쪽으로 밀리지는 않는다. 여기서 밀린 것은 개수가 아니라 그 한 점의 위치 때문이다.

  4. 클래스 1의 비율이 3대 4에서 4대 4로 바뀌어 균형이 무너졌다.

    비율은 오히려 균형에 가까워졌다. 클래스 비율이 아니라 입력 축에서 멀리 떨어진 위치가 원인이다.

해설

추가된 점은 이미 클래스 1 영역 깊숙이 있어 분류 판정에는 아무 정보도 더하지 않는다. 그런데 선형 회귀는 그 점의 제곱 오차까지 줄이려 하므로 직선이 눌려 평평해지고, 0.5를 지나는 자리가 밀리면서 원래 맞던 예측까지 틀리게 된다. 로지스틱 회귀가 이 문제에 강한 이유는 시그모이드의 모양에 있다. 이미 1에 가깝게 예측한 점은 손실이 거의 0이라 파라미터를 더 끌어당기지 않으므로, 멀리 있는 같은 클래스의 점이 경계를 밀지 못한다. 로그 손실이 벌하는 것은 정답 클래스에 낮은 확률을 준 경우이지 정답 쪽으로 멀리 떨어진 경우가 아니다.

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

로지스틱 회귀에서 MSE를 버리고 로그 손실을 쓰는 가장 중요한 이유는 무엇인가?

  1. MSE는 확률을 다룰 수 없어 0과 1 사이의 값에 적용되지 않기 때문이다.

    계산 자체는 정상적으로 된다. 값도 나오고 학습도 진행되지만 그 지형이 문제다.

  2. MSE는 분류 정확도를 직접 최적화하지 못하기 때문이다.

    로그 손실도 정확도를 직접 최적화하지 않는다. 정확도는 계단 함수라 미분되지 않으므로 어떤 손실도 그것을 직접 다루지 못한다.

  3. 정답시그모이드를 씌운 MSE는 볼록하지 않아 지역 최솟값이 여러 개 생기기 때문이다.

    볼록하지 않으면 경사하강법이 어디서 출발하느냐에 따라 다른 곳에 멈추고 전역 최솟값에 닿는다는 보장이 사라진다. 로그 손실은 시그모이드와 결합해도 볼록성을 유지한다.

  4. MSE는 두 클래스에 같은 벌점을 주므로 불균형 데이터에서 쓸 수 없기 때문이다.

    로그 손실도 기본적으로는 두 클래스를 같게 다룬다. 불균형 대응은 클래스 가중치로 따로 넣는 문제다.

해설

시그모이드를 씌운 예측에 제곱 오차를 적용하면 그 비용 곡면이 볼록하지 않아진다. 지역 최솟값이 여러 개 생기고 경사하강법이 어디서 출발하느냐에 따라 다른 곳에 멈추므로 전역 최솟값에 닿는다는 보장이 사라진다. 로그 손실은 시그모이드와 결합해도 볼록성을 유지하므로 이 문제가 없다. 벌의 모양도 눈여겨볼 만하다. 잘 맞힌 쪽의 이득은 0에서 멈추지만 확신 있게 틀린 쪽의 벌은 로그를 따라 발산한다. 정답 확률을 0.01로 준 예측 하나의 손실이 4.6인데, 이는 0.5로 어정쩡하게 준 예측 여섯 건분을 넘는 양이다. 확신 있는 오답을 강하게 벌하는 이 비대칭이 분류 학습을 이끄는 힘이다.

이 내용 다시 읽기 →
분석과 판단구조
로그 손실을 파라미터로 미분한 결과다. ∂J/∂w = (1/m)Σ(h(xᵢ) - yᵢ)·xᵢ 선형 회귀에서 MSE를 미분한 결과와 형태가 똑같고 h의 정의만 다르다.

전혀 다른 비용 함수를 썼는데 갱신식이 같은 모양이 되는 이유는 무엇인가?

  1. 우연의 일치다. 두 식이 같아 보일 뿐 계수와 부호가 미세하게 다르다.

    두 식은 문자 그대로 같다. 그리고 이 일치는 우연이 아니라 로그와 시그모이드의 미분이 맞물린 결과다.

  2. 정답로그의 미분에서 나온 1/h와 시그모이드의 미분에서 나온 h(1-h)가 약분되기 때문이다.

    정답 확률에 로그를 씌운 항을 미분하면 분모에 h가 생기고, 시그모이드를 미분하면 h(1-h)가 나온다. 연쇄 법칙으로 둘을 곱하는 순간 h가 지워지면서 잔차 곱하기 입력만 남는다.

  3. 로그 손실을 테일러 전개해 2차까지만 남기면 MSE가 되기 때문이다.

    근사가 아니라 정확한 등식이다. 어떤 전개도 거치지 않고 미분 계산만으로 같은 형태가 나온다.

  4. 시그모이드가 항등 함수에 가까워 미분이 1에 수렴하기 때문이다.

    시그모이드의 미분은 최대 0.25이고 극단에서는 0에 가깝다. 1에 수렴하지 않으며, 그 값이 약분으로 사라지는 것이 요점이다.

해설

정답 확률에 로그를 씌운 항을 미분하면 분모에 예측 확률이 생기고, 시그모이드를 미분하면 예측 확률 곱하기 그 여집합이 나온다. 연쇄 법칙으로 둘을 곱하는 순간 예측 확률이 약분되면서 잔차 곱하기 입력만 남는다. 그래서 비용 함수를 완전히 갈아 끼웠는데도 갱신식은 선형 회귀와 같은 모양으로 돌아온다. 이것이 세 조각이 서로를 붙들고 있다는 말의 의미다. MSE를 버린 것은 볼록성을 얻기 위해서였는데 그 대가로 고른 로그가 시그모이드의 미분과 정확히 맞물려 구현까지 단순하게 만들어준다. 같은 약분이 소프트맥스와 교차 엔트로피의 조합에서도 일어나므로, 신경망 분류기의 마지막 층에서 이 짝이 표준이 된 것도 같은 이유다.

이 내용 다시 읽기 →
분석과 판단함정
과적합이 의심되어 LogisticRegression의 C를 1.0에서 10.0으로 올렸다. 훈련 정확도가 오히려 더 올라가고 검증 정확도는 떨어졌다.

무엇이 잘못됐는가?

  1. C를 올린 만큼 max_iter도 함께 올려야 수렴한다.

    수렴 문제라면 경고가 뜨고 훈련 정확도도 함께 나빠진다. 여기서는 훈련 쪽이 오히려 좋아졌으므로 과적합이 심해진 모습이다.

  2. 정답C는 규제 강도의 역수라 값을 올리면 규제가 약해진다.

    과적합을 줄이려면 규제를 세게 걸어야 하므로 C를 내려야 한다. 규제 계수를 직접 받는 Ridge의 alpha와 방향이 정반대라 값을 옮길 때 자주 뒤집힌다.

  3. C는 클래스 가중치라 값을 올리면 소수 클래스가 과대 대표된다.

    클래스 가중치는 class_weight로 따로 지정한다. C는 규제와 데이터 적합 사이의 저울을 정하는 값이다.

  4. C는 반복 횟수 배수라 값을 올리면 학습이 과도하게 진행된다.

    반복 횟수는 max_iter가 정한다. C를 바꿔도 학습 절차의 길이는 달라지지 않는다.

해설

LogisticRegression의 C는 규제 강도의 역수다. C가 크면 규제가 약해 가중치가 커질 수 있고 과적합 쪽으로 가며, C가 작으면 가중치를 강하게 눌러 경계가 단순해지고 과소적합 쪽으로 간다. 규제 계수를 직접 받는 Ridge나 Lasso의 alpha와 방향이 정반대라 값을 옮길 때 뒤집기 쉽고, 여기서도 과적합을 줄이려다 오히려 키운 셈이 됐다. 라이브러리마다 이런 방향의 차이가 있으므로 새 모델의 규제 파라미터를 만나면 그것이 강도인지 역수인지부터 확인하는 것이 안전하다. 함께 기억할 것은 로지스틱 회귀에도 규제가 기본으로 켜져 있다는 점이다. 규제 없는 순수한 로지스틱 회귀를 원한다면 penalty를 따로 꺼야 한다.

이 내용 다시 읽기 →

모델이 데이터를 가르는 선, 결정 경계

원문 읽기 →
개념 확인구조

임계값 0.5를 쓰는 로지스틱 회귀의 결정 경계가 항상 평평한 이유는 무엇인가?

  1. 학습 데이터가 대개 선형에 가깝게 분포하기 때문이다.

    데이터의 모양과 무관하다. 동심원처럼 전혀 선형이 아닌 데이터에 학습시켜도 경계는 여전히 직선으로 나온다.

  2. 정답예측이 갈리는 자리가 w·x + b = 0의 해집합이기 때문이다.

    시그모이드가 0.5를 지나는 지점은 입력이 0인 곳 하나뿐이라 경계가 이 등식으로 정해진다. 2차원에서 직선, 3차원에서 평면, n차원에서 초평면이라 차원이 올라가도 평평하다.

  3. 경사하강법이 볼록 함수를 최소화하므로 해가 하나뿐이기 때문이다.

    볼록성은 지역 최솟값이 곧 전역 최솟값이라는 성질일 뿐 경계의 모양과는 다른 이야기다. 최적화가 잘 끝나도 경계가 곡선인 모델이 있다.

  4. 규제가 가중치를 눌러 경계가 휘지 못하게 막기 때문이다.

    규제를 완전히 끄고 아무리 오래 학습시켜도 경계는 평평하다. 이것은 학습의 결과가 아니라 모델 구조가 정해놓은 성질이다.

해설

시그모이드가 정확히 0.5를 지나는 지점은 입력이 0인 곳 하나뿐이다. 따라서 0.5를 임계값으로 쓰는 한 예측이 갈리는 자리는 가중치와 입력의 내적에 절편을 더한 값이 0이 되는 점들이고, 이 등식은 2차원에서 직선, 3차원에서 평면, n차원에서 초평면이다. 가중치 벡터는 이 경계의 법선이라 경계는 언제나 그 벡터에 수직이고, 절편은 경계를 원점에서 얼마나 밀어낼지를 정한다. 학습이란 결국 이 평면의 방향과 위치를 옮기는 일이다. 아무리 오래 학습시키고 규제를 어떻게 걸어도 이 사실은 바뀌지 않는다. 곡선 경계를 얻으려면 모델이 아니라 입력을 손봐야 한다.

이 내용 다시 읽기 →
상황 적용진단
합격 예측 모델에 규제를 세게 걸었더니 이렇게 바뀌었다. 규제 전 |w| = 3.26, 경계 기울기 -1.24, 확률 0.9까지 거리 0.67 규제 후 |w| = 0.42, 경계 기울기 -1.11, 확률 0.9까지 거리 5.2

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

  1. 규제가 경계의 위치를 크게 옮겨 예측 클래스가 대부분 뒤집혔다.

    기울기가 -1.24에서 -1.11로 거의 그대로다. 경계 자체는 거의 같은 자리에 있으므로 예측 클래스도 대부분 그대로다.

  2. 규제가 모델을 과소적합시켜 경계가 데이터를 가르지 못하게 됐다.

    경계가 거의 그대로이므로 가르는 능력도 거의 그대로다. 달라진 것은 판정이 아니라 판정에 붙는 확신의 크기다.

  3. 확률 계산에 쓰이는 임계값이 0.5에서 다른 값으로 옮겨 갔다.

    임계값은 규제와 무관하게 0.5 그대로다. 옮겨 간 것은 임계값이 아니라 확률이 0에서 1로 넘어가는 속도다.

  4. 정답경계의 방향은 거의 그대로인 채 확률만 완만해져 모델이 덜 단정적으로 바뀌었다.

    시그모이드에 들어가는 값은 가중치 벡터의 크기 곱하기 경계까지의 거리다. 크기를 누르면 같은 거리에서도 확률이 0.5 쪽에 머물러 확신만 약해진다.

해설

점에서 경계까지의 부호 있는 거리를 구하면 시그모이드에 들어가는 값은 가중치 벡터의 크기 곱하기 그 거리다. 확률이 거리 하나로 정해지므로 확률이 같은 점을 이으면 경계와 나란한 직선이 나오고, 남은 변수는 가중치 벡터의 크기 하나다. 이 값이 크면 같은 거리에서도 확률이 가파르게 변하고, 규제로 눌러 작게 만들면 같은 확률에 닿기까지 훨씬 먼 거리가 필요해진다. 방향은 그대로인데 확신만 완만해지는 것이다. 확률을 그대로 의사결정 비용에 곱해 쓰는 상황이라면 이 차이가 중요하다. 정확도는 같아도 확률이 실제 빈도와 맞지 않을 수 있으므로 보정 곡선을 따로 확인해야 한다.

이 내용 다시 읽기 →
상황 적용구조
# 동심원 데이터에 로지스틱 회귀
LogisticRegression().fit(X, y).score(X, y)   # 0.505

# 모델은 그대로, 앞에 한 단계만 추가
pipe = Pipeline([
    ('poly', PolynomialFeatures(degree=2)),
    ('scaler', StandardScaler()),
    ('clf', LogisticRegression(C=10)),
])
pipe.fit(X, y).score(X, y)                   # 1.0

모델을 바꾸지 않았는데 경계가 원이 된 이유는 무엇인가?

  1. 정답확장된 공간에서는 여전히 평평한 경계가 원래 평면에서 2차 곡선으로 보이기 때문이다.

    제곱 항과 교차 항을 붙이면 로지스틱 회귀는 5차원 공간에서 초평면을 긋는다. 그 식을 원래의 두 변수 평면에서 읽으면 2차 곡선이고, 제곱 항의 두 계수가 비슷하면 원의 방정식이 된다.

  2. PolynomialFeatures가 로지스틱 회귀를 비선형 분류기로 바꿔주기 때문이다.

    전처리 단계는 모델을 건드리지 않는다. 분류기는 확장된 공간에서 여전히 선형이고, 비선형으로 보이는 것은 원래 공간에 되돌려 그렸을 때뿐이다.

  3. C를 10으로 올려 규제를 풀었기 때문에 경계가 휠 수 있게 됐다.

    규제는 이미 가능한 모양의 범위 안에서 얼마나 휠지를 조절할 뿐이다. 제곱 항이 없으면 C를 아무리 올려도 경계는 직선에 머문다.

  4. 스케일러가 데이터를 원형으로 재배치해 선형 분리가 가능해졌기 때문이다.

    표준화는 각 축을 따로 평행 이동하고 늘릴 뿐이라 선형 분리 가능 여부를 바꾸지 못한다. 수렴 속도에만 영향을 준다.

해설

두 변수에 제곱 항과 교차 항을 더하면 로지스틱 회귀는 확장된 5차원 공간에서 여전히 평평한 경계를 긋는다. 그런데 같은 식을 원래의 두 변수 평면에서 보면 2차 곡선이고, 두 제곱 항의 계수가 비슷하고 나머지가 작으면 원의 방정식이 된다. 동심원 데이터가 정확히 그 구조라 2차에서 완전히 갈린다. 모델은 한 글자도 바뀌지 않았고 바뀐 것은 입력의 표현뿐이다. 이 발상은 로지스틱 회귀에서 멈추지 않는다. 커널 SVM은 확장된 특성을 명시적으로 만들지 않고 내적만으로 같은 일을 하고, 신경망의 은닉층은 어떤 특성을 만들지를 학습으로 찾는다. 원래 공간에서 선형으로 안 풀리는 문제를 선형으로 풀리는 공간으로 옮긴다는 점이 셋 다 같다.

이 내용 다시 읽기 →
분석과 판단함정
def softmax(z):
    z = z - np.max(z, axis=1, keepdims=True)
    e = np.exp(z)
    return e / e.sum(axis=1, keepdims=True)

첫 줄에서 최댓값을 빼는 이유는 무엇인가?

  1. 점수의 평균을 0으로 맞춰야 확률의 합이 정확히 1이 되기 때문이다.

    확률의 합은 분모가 모든 항의 합이라는 정의만으로 1이 된다. 어떤 상수를 빼든 합은 1이다.

  2. 가장 큰 점수를 0으로 눌러야 그 클래스의 확률이 최대가 되기 때문이다.

    지수 함수가 단조 증가라 어떤 상수를 빼도 대소 관계는 그대로다. 최댓값을 빼지 않아도 가장 큰 점수의 확률이 가장 크다.

  3. 정답큰 점수에서 exp가 float 범위를 넘겨 inf가 되고 결과가 nan으로 무너지기 때문이다.

    점수에 1000 같은 값이 들어오면 지수 계산이 무한대를 반환하고 무한대 나누기 무한대가 되어 전체가 nan이 된다. 최댓값을 빼면 지수가 0 이하로 눌려 안전해지고, 분자와 분모에 같은 상수가 곱해지는 것이라 출력값은 변하지 않는다.

  4. 작은 점수 쪽에서 exp가 0으로 언더플로되는 것을 막기 위해서다.

    최댓값을 빼도 최대항에서 멀리 떨어진 점수는 여전히 0으로 언더플로되고, 그것은 결과를 해치지 않는다. 빼기의 효과는 최대항이 exp(0) = 1로 고정되어 분모가 1 이상으로 보장되고 큰 양수의 오버플로가 사라지는 쪽이다.

해설

점수에 1000 같은 값이 들어오면 지수 계산이 float 범위를 넘겨 무한대를 반환하고, 무한대 나누기 무한대가 되어 결과 전체가 nan으로 무너진다. 각 행의 최댓값을 빼면 지수가 0 이하로 눌려 계산이 안전해지고, 분자와 분모에 같은 상수가 곱해지는 것이라 출력값은 조금도 변하지 않는다. 값을 지키면서 안정성만 얻는 변형이다. 실제 프레임워크의 소프트맥스와 로그 소프트맥스에도 같은 처리가 들어 있고, 손실까지 한 함수로 묶은 구현을 권하는 이유도 여기에 있다. 소프트맥스를 따로 계산해 로그를 씌우면 확률이 0으로 눌린 자리에서 로그가 무한대로 발산하는데, 묶어서 계산하면 그 항이 지수 계산 없이 처리되어 그 위험이 사라진다.

이 내용 다시 읽기 →
상황 적용설계
문서 한 건에 여러 주제 태그가 동시에 붙을 수 있는 분류기를 만들려 한다. 태그는 12종이고 한 문서에 평균 2.4개가 붙는다.

One-vs-Rest와 Softmax 중 어느 쪽이 맞는가?

  1. Softmax다. 클래스가 셋 이상이면 Softmax가 표준이고 확률의 합이 1이라 해석이 쉽다.

    합이 1이라는 성질이 여기서는 오히려 방해가 된다. 정답 태그가 여러 개인데 확률을 나눠 가지므로 어느 것도 임계값을 넘지 못하는 일이 생긴다.

  2. Softmax다. 클래스끼리 경쟁하며 함께 학습하므로 태그 사이의 관계까지 배울 수 있다.

    여기서 필요한 것은 경쟁이 아니라 독립이다. 함께 붙어야 할 태그끼리 확률을 빼앗는 구조가 된다.

  3. One-vs-Rest다. 학습해야 할 분류기가 12개로 나뉘어 각각의 데이터가 작아지므로 학습이 빠르다.

    결론은 맞지만 이유가 아니다. 각 분류기는 전체 데이터를 다 쓰고, 선택의 근거는 속도가 아니라 한 샘플에 정답이 여럿이라는 문제 구조다.

  4. 정답One-vs-Rest다. 한 샘플에 여러 레이블이 동시에 붙는 문제라 각 분류기가 독립인 구조가 맞다.

    각 태그에 대해 붙는지 아닌지를 따로 판정하므로 확률이 서로를 밀어내지 않는다. Softmax는 확률의 합을 1로 강제해 상호 배타적인 문제에만 맞다.

해설

Softmax는 K개 점수를 한꺼번에 정규화해 확률의 합을 1로 만든다. 한 샘플에 정답이 하나뿐인 상호 배타적 문제라면 이 성질이 정확히 원하는 것이지만, 여러 레이블이 동시에 붙는 문제에서는 정답끼리 확률을 나눠 가지므로 어느 것도 임계값을 넘지 못하는 일이 생긴다. One-vs-Rest는 각 클래스에 대해 붙는지 아닌지를 따로 판정하는 이진 분류기를 K개 만들고 서로를 모른 채 학습하므로 다중 레이블에 그대로 맞는다. 확률의 합이 1이 되지 않아 어떤 점에서 두 클래스의 확률이 모두 높게 나올 수 있다는 성질도, 단일 레이블 문제에서는 단점이지만 여기서는 그것이 곧 원하는 동작이다. 클래스 수와 상관없이 문제의 배타성이 선택 기준이다.

이 내용 다시 읽기 →
분석과 판단함정
특성 10개짜리 데이터에 표본이 2,000건 있다. 성능을 올리려고 PolynomialFeatures의 degree를 2에서 5로 올렸다. degree 2 → 66개 degree 3 → 286개 degree 5 → 3,003개 degree 10 → 184,756개

이때 훈련 정확도가 오르는 것을 성능 향상으로 읽으면 안 되는 이유는 무엇인가?

  1. 다항 특성끼리 상관이 높아 계수가 불안정해지므로 정확도 자체가 신뢰할 수 없는 값이 되기 때문이다.

    다중공선성은 계수 해석을 흐리지만 예측 정확도 자체를 못 믿을 값으로 만들지는 않는다. 문제는 그 정확도를 어떤 데이터에서 쟀느냐다.

  2. 정답특성 수가 표본 수에 가까워지면 모델이 훈련 데이터를 사실상 외우게 되어 경계가 표본 배치에 종속되기 때문이다.

    3,003개 특성에 표본 2,000건이면 특성이 표본보다 많다. 훈련 정확도는 복잡도를 올리는 쪽으로 단조롭게 좋아지므로 그 숫자로는 과적합이 시작된 지점을 볼 수 없다.

  3. 특성이 늘면 학습 시간이 길어져 max_iter 안에 수렴하지 못하기 때문이다.

    수렴하지 못하면 훈련 정확도도 함께 나빠진다. 훈련 정확도가 오르는 상황을 설명하지 못한다.

  4. degree가 높아지면 큰 차수 항의 값이 커져 스케일링이 무의미해지기 때문이다.

    표준화는 어떤 차수의 항에도 똑같이 적용된다. 스케일 문제는 수렴 속도의 이야기이지 일반화 성능의 이야기가 아니다.

해설

다항 특성의 개수는 원래 특성 수와 차수의 조합으로 늘어난다. 특성 10개를 5차까지 확장하면 3,003개가 되어 표본 2,000건보다 많아지고, 이 상태에서는 모델이 훈련 데이터를 사실상 외울 수 있게 되어 경계가 표본의 배치에 완전히 종속된다. 훈련 정확도는 복잡도를 올리는 쪽으로 단조롭게 좋아지므로 그 숫자만 보면 과적합이 시작된 지점을 영영 볼 수 없다. 동심원 데이터에서 2차와 5차가 훈련에서 둘 다 100%인데 5차 경계는 표본 몇 개의 배치에 맞춰 휘어 있어 새 데이터에서 더 자주 틀리는 것이 그 예다. 차수와 규제는 짝으로 움직여야 하고 두 값 모두 교차 검증 점수로 골라야 한다.

이 내용 다시 읽기 →

베이즈 정리로 분류하는 나이브 베이즈(Naive Bayes)

원문 읽기 →
개념 확인구조
클래스마다 추정해야 할 값의 개수를 이진 특성 수에 따라 비교한 표다. 특성 3개 결합 확률표 8칸 나이브 가정 3칸 특성 10개 결합 확률표 1,024칸 나이브 가정 10칸 특성 20개 결합 확률표 1,048,576칸 나이브 가정 20칸

조건부 독립 가정이 실제로 해결하는 문제는 무엇인가?

  1. 여러 특성을 동시에 다루면 계산이 오래 걸려 학습 속도가 느려지는 문제다.

    속도 이전에 값 자체를 구할 수 없는 것이 문제다. 관측되지 않은 조합의 확률은 아무리 오래 계산해도 나오지 않는다.

  2. 정답특성 조합마다 확률을 세려면 관측할 수 없을 만큼 많은 데이터가 필요한 문제다.

    특성 20개의 조합 표를 채우려면 100만 가지 경우를 각각 충분히 관측해야 한다. 동시 확률을 개별 확률의 곱으로 쪼개면 세어야 할 값이 특성 하나하나의 등장 확률로 줄어든다.

  3. 특성끼리 상관이 있으면 모델이 같은 정보를 중복해서 배우는 문제다.

    오히려 반대다. 독립으로 취급하기 때문에 상관된 정보가 중복해서 곱해지고, 그것이 이 가정이 만드는 부작용이다.

  4. 특성 수가 많으면 사전확률을 정확히 추정할 수 없는 문제다.

    사전확률은 클래스 비율이라 특성 수와 무관하게 쉽게 구해진다. 어려운 쪽은 우도다.

해설

여러 특성의 동시 확률을 데이터에서 직접 세려면 특성 조합 전체를 관측해야 한다. 이진 특성 20개면 100만 가지 조합을 각각 충분히 봐야 하고, 어휘가 수만 개인 실제 문서에서 이 표를 채우는 것은 데이터를 아무리 모아도 불가능하다. 클래스가 정해지고 나면 특성들이 서로 독립이라고 가정하면 동시 확률이 개별 확률의 곱으로 쪼개지고, 추정 대상이 조합 표 전체에서 특성 하나하나의 등장 확률로 줄어든다. 지수적으로 늘어나던 것이 선형이 되는 셈이다. 그 결과 최종 분류 규칙도 사전확률에 특성별 확률을 곱하는 형태로 정리된다. 베이즈 정리의 분모는 모든 클래스에서 같으므로 크기만 비교할 때는 계산하지 않아도 된다.

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

스팸 메일에서 '무료'와 '이벤트'는 당연히 함께 등장하므로 독립 가정은 틀렸다. 그런데도 분류가 잘 되는 이유는 무엇인가?

  1. 학습 데이터가 충분히 많으면 상관된 특성의 영향이 서로 상쇄되어 독립에 가까워지기 때문이다.

    데이터가 많아진다고 상관이 사라지지 않는다. 오히려 데이터가 많아지면 이 가정의 한계가 드러나 판별적 모델에 추월당한다.

  2. 라플라스 스무딩이 상관된 단어의 확률을 눌러 중복 계산을 막아주기 때문이다.

    스무딩은 관측되지 않은 단어의 확률이 0이 되는 것을 막을 뿐이다. 특성 사이의 상관과는 무관하다.

  3. 정답분류에 필요한 것은 확률값이 아니라 어느 클래스가 큰지의 순위뿐이기 때문이다.

    상관된 특성을 독립으로 취급하면 같은 정보가 여러 번 곱해져 확률값이 부풀지만, 그 부풀림은 대체로 두 클래스에서 비슷한 방향으로 일어나 부등호를 뒤집지 못한다.

  4. 곱셈이 아니라 로그 합으로 계산하므로 상관에 의한 왜곡이 누적되지 않기 때문이다.

    로그로 바꾸는 것은 수치 안정성을 위한 변환이라 값의 순서가 그대로 보존된다. 왜곡의 크기도 그대로다.

해설

분류가 요구하는 것은 확률의 정확한 값이 아니라 어느 클래스의 사후확률이 큰지 하나뿐이다. 상관된 특성을 독립으로 취급하면 같은 정보가 여러 번 곱해져 확률값이 한쪽으로 부풀지만, 그 부풀림은 대체로 두 클래스에서 비슷한 방향으로 일어나므로 순위를 뒤집지 못한다. 틀린 가정이 확률은 왜곡하되 순위는 대체로 보존하는 것이다. 그래서 이 모델을 쓸지 판단하는 기준은 정확도표가 아니라 용도가 된다. 어느 클래스인지만 알면 되는 자리, 특성 수가 문서 수보다 많은 자리, 모델을 자주 새로 만들어야 하는 자리에서는 여전히 가장 먼저 시도해볼 베이스라인이다. 반대로 특성 사이의 상관 자체가 판단의 핵심인 문제라면 다른 모델을 봐야 한다.

이 내용 다시 읽기 →
상황 적용함정
나이브 베이즈 스팸 필터를 붙였는데 요구사항이 두 개 붙었다. 1) 사용자에게 "스팸일 확률 82%"처럼 수치를 보여준다 2) 오탐 민원에 따라 임계값을 0.5에서 0.7, 0.85로 세밀하게 올린다 출력을 찍어보니 거의 모든 문서가 0.999 아니면 0.001이었다.

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

  1. alpha를 키워 확률을 균등한 쪽으로 밀면 중간값이 생겨 임계값 조정이 가능해진다.

    alpha는 관측되지 않은 단어를 다루는 값이라 극단으로 쏠리는 원인을 건드리지 못한다. 값을 크게 올리면 분류 성능만 나빠진다.

  2. 출력이 극단으로 쏠린 것은 과적합 신호이므로 학습 데이터를 늘려야 한다.

    쏠림은 데이터 부족이 아니라 상관된 특성이 독립으로 곱해지면서 생기는 구조적 결과다. 데이터를 늘려도 그대로다.

  3. 정답이런 두 요구사항이 붙은 자리에는 확률값을 그대로 쓸 수 있는 로지스틱 회귀가 맞다.

    나이브 베이즈의 확률은 순위만 믿을 만하고 값 자체는 믿을 것이 못 된다. 수치를 노출하거나 임계값을 세밀하게 조정해야 하는 자리에서는 모델을 바꾸는 편이 정직하다.

  4. 두 클래스의 확률에 제곱근을 씌운 뒤 합이 1이 되게 다시 나눠 0.5 쪽으로 당기면 두 요구사항을 모두 만족할 수 있다.

    확률의 순위는 그대로라 분류는 유지되지만 그렇게 얻은 값이 실제 빈도와 맞는다는 보장이 없다. 보이기용 숫자를 만들 뿐이다.

해설

상관된 특성을 독립으로 취급하면 같은 증거가 여러 번 곱해지므로 사후확률이 0이나 1 쪽으로 심하게 쏠린다. 순위는 대체로 보존되어 분류는 잘 되지만 값 자체는 실제 빈도와 맞지 않는다. 확률 수치를 사용자에게 보여주거나 임계값을 세밀하게 조정해야 하는 자리라면 이 성질이 곧바로 문제가 되므로 로지스틱 회귀 쪽이 맞다. 모델을 바꾸기 어렵다면 검증 세트로 확률을 사후 보정하는 방법이 있지만, 쏠림이 심할수록 보정으로 되찾을 수 있는 해상도가 줄어든다. 애초에 어느 클래스인지만 필요한 자리인지 확률값까지 필요한 자리인지를 먼저 가르는 편이 낫다.

이 내용 다시 읽기 →
분석과 판단함정
MultinomialNB(alpha=1.0)에서 alpha를 0으로 두면 어떻게 되는지 확인하려 한다.

alpha를 0으로 두면 무엇이 깨지는가?

  1. 정답훈련에 없던 단어가 하나라도 나오면 그 문서 전체의 확률이 0이 되어 판정이 무너진다.

    우도가 곱셈으로 결합되므로 0인 항 하나가 전체를 0으로 만든다. 나머지 단어가 아무리 강하게 한 클래스를 가리켜도 그 정보가 통째로 사라진다.

  2. 모든 단어의 확률이 균등해져 어느 클래스도 우세하지 않게 된다.

    균등해지는 것은 alpha를 크게 올렸을 때다. 0으로 두면 반대로 관측 빈도를 그대로 쓴다.

  3. 확률의 합이 1을 넘어 정규화가 깨지고 계산이 발산한다.

    정규화는 관측 빈도만으로도 성립한다. 합이 깨지는 문제는 생기지 않는다.

  4. 학습 시 로그를 취할 수 없어 feature_log_prob_ 배열을 만들지 못한다.

    어떤 클래스에 안 나온 단어의 로그 확률이 음의 무한대로 저장될 뿐 배열 생성 자체는 된다. 판정이 실제로 무너지는 곳은 예측 시점이다.

해설

훈련 데이터에 한 번도 없던 단어가 테스트 문서에 나오면 그 단어의 조건부 확률이 0이 되고, 우도가 곱셈으로 결합되므로 문서 전체의 확률이 0으로 사라진다. 나머지 단어가 아무리 강하게 한 클래스를 가리켜도 그 정보가 통째로 무의미해진다. alpha는 모든 단어에 가상의 등장 횟수를 더해 이 소멸을 막는 값이다. alpha가 클수록 모든 단어의 확률이 균등해져 데이터가 말하는 바를 덜 듣게 되고, 0에 가까울수록 관측 빈도를 그대로 쓰되 이 소멸 위험에 노출된다. 어휘가 크고 문서가 적을수록 처음 보는 단어가 많으므로 alpha를 조금 크게 잡는 편이 안전하고, 반대의 경우에는 작게 두어도 된다. 교차 검증으로 고를 값이다.

이 내용 다시 읽기 →
상황 적용설계
같은 텍스트 파이프라인에서 분류기만 바꿔 재보았다. 학습 문서 2,254개, 어휘 10,000개 MultinomialNB 0.8739 로지스틱 회귀 0.8200

이 데이터에서 나이브 베이즈가 앞선 이유는 무엇인가?

  1. 텍스트 데이터에서는 단어가 실제로 서로 독립이라 나이브 가정이 성립하기 때문이다.

    문서에서 단어들은 강하게 상관되어 있어 이 가정은 명백히 틀렸다. 앞선 이유는 가정이 맞아서가 아니다.

  2. 로지스틱 회귀에 규제가 걸려 있어 단어 수가 많으면 계수가 지나치게 눌리기 때문이다.

    규제 강도는 조정할 수 있는 값이라 근본 원인이 아니다. 규제를 풀면 오히려 과적합 쪽으로 더 기운다.

  3. 정답특성 수가 문서 수보다 훨씬 많은 상황이라 경계를 통째로 배우는 쪽이 불리하기 때문이다.

    판별적 모델은 경계를 데이터에서 배워야 하므로 표본이 상대적으로 적으면 흔들린다. 나이브 베이즈는 독립 가정이 미리 구조를 정해준 덕에 추정할 값이 적어 덜 흔들린다.

  4. 나이브 베이즈가 클래스 사전확률을 함께 쓰므로 불균형한 카테고리에 강하기 때문이다.

    여기 네 카테고리는 비율이 비슷해 사전확률의 효과가 크지 않다. 로지스틱 회귀도 절편으로 같은 역할을 흡수한다.

해설

판별적 모델은 경계를 데이터에서 통째로 배워야 하므로 특성 수에 비해 표본이 적으면 흔들린다. 여기서는 문서 2,254개에 어휘 10,000개라 정확히 그 상황이다. 나이브 베이즈는 독립 가정이 미리 구조를 정해준 덕에 추정할 값이 특성 수만큼으로 줄어들고, 그만큼 적은 데이터에서 덜 흔들린다. 틀린 가정이 만들어준 안정성이 여기서는 이득이 된 셈이다. 다만 이 이득은 데이터가 적을 때만 유효하다. 표본이 늘어나면 그 구조가 반대로 족쇄가 되어 로지스틱 회귀가 추월한다. 두 모델을 고르는 축이 정확도표가 아니라 표본 수와 특성 수의 관계라는 뜻이다.

이 내용 다시 읽기 →
분석과 판단구조

Gaussian Naive Bayes의 결정 경계가 직선이 아닐 수 있는 이유는 무엇인가?

  1. 정규분포의 지수 항 때문에 사후확률이 비선형이라 경계도 언제나 곡선이 된다.

    지수 항은 로그를 취하면 이차식이 되고, 클래스 사이에서 이차 항이 서로 지워질 수 있다. 언제나 곡선인 것이 아니라 조건에 달렸다.

  2. 정답클래스마다 분산이 다르면 사후확률이 같아지는 자취가 이차 곡선으로 휘기 때문이다.

    두 클래스의 로그 우도를 빼면 이차 항의 계수가 두 분산의 차이로 결정된다. 분산이 모든 클래스에서 같을 때만 그 항이 지워져 경계가 직선이 된다.

  3. 클래스마다 평균이 다르면 경계가 평균을 잇는 선을 따라 휘기 때문이다.

    평균이 다른 것은 경계의 위치와 방향을 정할 뿐이다. 분산이 같다면 평균이 아무리 달라도 경계는 직선이다.

  4. 특성마다 스케일이 다르면 거리 계산이 왜곡되어 경계가 휘기 때문이다.

    각 특성이 자기 클래스 안에서 자기 평균과 분산으로 정규화되므로 스케일링이 필요 없고, 스케일이 경계 모양을 바꾸지도 않는다.

해설

각 클래스에서 특성이 정규분포를 따른다고 가정하면 클래스별 평균과 분산만으로 우도가 정해진다. 두 클래스의 사후확률이 같아지는 지점을 이은 것이 경계인데, 로그를 취해 정리하면 그 식에 입력의 이차 항이 남고 계수가 두 클래스 분산의 차이로 결정된다. 분산이 모든 클래스에서 같으면 그 항이 서로 지워져 경계가 직선이 되고, 다르면 자취가 이차 곡선으로 휜다. 로지스틱 회귀가 언제나 평평한 경계만 만드는 것과 대비되는 지점이다. 학습이라고 부를 것도 클래스별로 평균과 분산을 구하는 계산 한 번이 전부라 경사하강법도 반복도 없고, 각 특성이 자기 클래스 안에서 자기 단위로 정규화되므로 스케일링도 필요하지 않다.

이 내용 다시 읽기 →

거리만으로 분류하는 K-최근접 이웃(KNN)

원문 읽기 →
개념 확인구조

KNN을 게으른 학습이라고 부르는 이유는 무엇인가?

  1. 다수결이라는 단순한 규칙만 쓰므로 최적화 과정이 없기 때문이다.

    규칙이 단순한 것과 계산 시점이 늦은 것은 다른 이야기다. 나이브 베이즈도 규칙이 단순하지만 학습 때 통계량을 미리 계산해두므로 게으르지 않다.

  2. 학습 데이터가 늘어나도 다시 학습할 필요가 없어 갱신을 미룰 수 있기 때문이다.

    재학습이 없다는 것은 게으른 구조에서 따라 나오는 이점이지 이름의 유래가 아니다.

  3. 정답학습 때는 데이터를 저장만 하고 예측 요청을 받는 순간에야 계산을 시작하기 때문이다.

    가중치를 최적화하지도 함수를 피팅하지도 않고 원본을 그대로 들고 있다가, 새 점이 들어오면 그때 전체와의 거리를 잰다. 로지스틱 회귀와는 계산이 일어나는 시점이 정반대다.

  4. 예측 정확도를 높이려는 노력을 하지 않고 이웃의 판단에 그대로 맡기기 때문이다.

    이름에 담긴 뜻은 성능에 대한 평가가 아니라 계산 시점에 대한 서술이다.

해설

KNN이 세우는 가정은 하나다. 비슷한 데이터는 비슷한 레이블을 가진다. 여기서 나오는 절차는 학습 때 데이터를 그대로 저장하고, 예측 때 새 점과 저장된 전체의 거리를 재어 가장 가까운 K개를 다수결로 집계하는 것이 전부다. 학습 시점에 아무 계산도 하지 않고 예측 시점에 비로소 일을 시작하므로 게으른 학습이라 부른다. 이 구조에서 두 가지가 따라 나온다. 좋은 쪽은 데이터가 추가되어도 저장만 하면 되므로 재학습이 없다는 것이고, 나쁜 쪽은 예측 한 번에 저장된 전체와의 거리 계산이 필요하다는 것이다. 학습 데이터가 100만 개면 예측마다 100만 번을 계산해야 하고 그 100만 개를 계속 메모리에 들고 있어야 한다.

이 내용 다시 읽기 →
상황 적용진단
나이와 연봉(만원)으로 고객을 분류하려 한다. 스케일링 없이 두 고객 사이의 거리를 재면 이렇게 나온다. A = (30세, 5000) B = (50세, 5100) d = √( (30-50)² + (5000-5100)² ) = √(400 + 10000) ≈ 102

이 상태의 KNN에서 실제로 일어나는 일은 무엇인가?

  1. 거리값이 100을 넘어 이웃 판정 임계값을 초과하므로 아무도 이웃으로 뽑히지 않는다.

    KNN에는 거리 임계값이 없다. 거리 순으로 K개를 뽑을 뿐이므로 절댓값이 아무리 커도 이웃은 언제나 K개다.

  2. 정답나이가 거리 제곱합의 3.8%만 차지해 사실상 연봉만으로 이웃을 찾는다.

    400 대 10000이라 스무 살 차이가 연봉 100만원 차이보다 훨씬 작게 취급된다. 특성을 하나 넣었지만 모델은 그 특성을 보지 않는 셈이다.

  3. 두 특성의 상관이 높아 사실상 하나의 특성처럼 동작한다.

    상관 여부와 무관하다. 상관이 0이어도 값의 폭이 큰 쪽이 거리를 독점하는 문제는 그대로다.

  4. 유클리드 거리 대신 맨해튼 거리를 쓰면 두 특성의 기여가 같아진다.

    맨해튼으로 바꿔도 20 대 100이라 연봉이 다섯 배를 차지한다. 지수를 바꾸는 것으로는 단위 차이를 없앨 수 없다.

해설

스무 살 차이가 거리 제곱합에 기여하는 몫은 400으로 전체의 3.8%뿐이고, 나머지 96.2%는 연봉 100만원 차이가 가져간다. 이 상태의 KNN은 사실상 연봉이 비슷한 사람만 이웃으로 찾고 나이는 보지 않는다. 특성을 넣기는 했지만 모델에는 없는 것이나 마찬가지다. 실제 데이터에서 차이가 크게 벌어진다. Wine 데이터셋은 알코올 농도가 11.0에서 14.8, 프롤린이 278에서 1680까지라 스케일링 없이 학습하면 정확도가 0.74인데 표준화 한 줄을 넣으면 0.96으로 올라간다. 거리를 계산하는 알고리즘에서 스케일링은 선택적인 전처리가 아니라 알고리즘의 일부다.

이 내용 다시 읽기 →
상황 적용구조
유방암 데이터에서 K를 바꿔가며 교차 검증 정확도를 쟀다. K= 1 0.9543 K= 5 0.9649 K= 7 0.9701 K=15 0.9614 K=30 0.9526

이 뒤집힌 U자 모양이 말해주는 것은 무엇인가?

  1. K가 작을 때는 계산량이 적어 정보가 부족하고 K가 클수록 정보가 늘어난다.

    K가 커지면 표는 늘지만 멀리 있는 점의 표까지 섞이므로 유용한 정보가 늘어나는 것이 아니다. 계산량과도 무관하다.

  2. 이 데이터에 이웃이 7개 있는 자연스러운 군집 구조가 존재한다.

    최적 K는 잡음 수준과 클래스 경계의 국소적 모양이 함께 정하는 값이지 군집의 크기가 아니다.

  3. 정답K는 편향과 분산을 직접 조절하는 손잡이이고 이 데이터의 균형점이 7이다.

    K가 1이면 잡음 하나가 자기 주변을 통째로 차지해 경계가 구불거리는 과적합이 되고, K를 키우면 다른 클래스 영역의 점까지 표를 던져 국소적 패턴을 뭉갠다. 양쪽 끝이 나쁘고 가운데가 좋은 모양이 나온다.

  4. K를 홀수로 두면 동점이 없어 정확도가 올라가고 짝수에서는 떨어진다.

    홀수 여부는 이진 분류에서 동점을 막을 뿐이다. 표의 오르내림은 홀수인 1, 5, 7, 15 사이에서도 나타나므로 홀짝으로는 설명되지 않는다.

해설

K는 KNN의 유일한 하이퍼파라미터이자 편향과 분산을 직접 조절하는 손잡이다. K가 1이면 가장 가까운 점 하나가 답을 정하므로 잘못 라벨링된 점 하나가 자기 주변을 통째로 자기 클래스로 만들고, 결정 경계가 잡음까지 따라 구불거린다. 반대로 K를 키우면 멀리 있는 이웃까지 표를 던져 경계는 매끈해지지만 다른 클래스 영역의 점이 섞여 들어와 국소적인 패턴을 뭉갠다. K를 전체 데이터 수까지 올리면 어떤 입력에도 다수 클래스만 답하는 상수 함수가 된다. 양쪽 끝이 모두 나쁘므로 최적값은 가운데에 있고, 그 자리는 데이터마다 다르므로 교차 검증으로 찾는다. 이진 분류라면 동점이 생기지 않도록 홀수로 두는 것이 관례다.

이 내용 다시 읽기 →
분석과 판단구조
한 변이 1인 초입방체에 데이터가 고르게 흩어져 있다. 전체의 10%를 담는 작은 정육면체의 한 변 길이는 다음과 같다. 1차원 0.100 각 축의 10.0% 2차원 0.316 각 축의 31.6% 10차원 0.794 각 축의 79.4% 100차원 0.977 각 축의 97.7%

이 표가 KNN에 대해 말해주는 문제는 무엇인가?

  1. 정답고차원에서는 가까운 이웃이라는 개념 자체가 성립하지 않아 뽑히는 K개가 사실상 무작위 표본이 된다.

    100차원에서 10%만 모으려 해도 모든 축의 97.7%를 훑어야 하니 이웃이 아니라 공간 전체다. 실제로 차원이 올라가면 가장 가까운 점과 가장 먼 점까지의 거리 비율이 1에 수렴한다.

  2. 고차원에서는 거리 계산량이 차원에 비례해 늘어 예측이 감당할 수 없이 느려진다.

    계산량은 차원에 선형으로 늘 뿐이라 이 표가 보여주는 급격한 붕괴를 설명하지 못한다. 속도가 아니라 거리의 의미가 문제다.

  3. 고차원에서는 데이터가 초입방체의 중심에 몰려 이웃이 한쪽으로 치우친다.

    오히려 반대다. 차원이 높아지면 고르게 흩어진 점들은 부피가 몰려 있는 표면 쪽에 놓이게 되고, 그래서 서로가 엇비슷하게 멀어진다.

  4. 고차원에서는 K를 훨씬 크게 잡아야 표본이 충분해져 이 문제가 해소된다.

    K를 키우면 더 멀고 무관한 점까지 표를 던지므로 나빠진다. 거리가 정보를 잃은 상태에서는 몇 개를 뽑든 마찬가지다.

해설

고르게 흩어진 데이터의 10%를 담으려면 100차원에서는 모든 축의 97.7%를 훑어야 한다. 이것은 이웃이 아니라 공간 전체다. 실제로 차원이 올라가면 가장 가까운 점까지의 거리와 가장 먼 점까지의 거리 비율이 1에 수렴하고, 모든 점이 엇비슷하게 멀어지면 다수결에 뽑히는 K개는 사실상 무작위 표본이 되어 KNN이 동전 던지기에 가까워진다. 대응은 특성 수를 줄이는 쪽이다. PCA로 정보를 압축하거나 기여가 없는 변수를 골라내는 특성 선택을 앞단에 둔다. 특성이 수백 개를 넘고 줄일 여지가 없다면 애초에 거리에 의존하지 않는 트리 기반 모델로 갈아타는 편이 낫다.

이 내용 다시 읽기 →
상황 적용설계
같은 데이터에 KNN과 랜덤 포레스트를 함께 돌렸다. 표준화 단계를 빼먹었는데 랜덤 포레스트 점수는 그대로였고 KNN만 크게 떨어졌다.

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

  1. 랜덤 포레스트가 여러 트리를 평균 내므로 스케일 왜곡이 상쇄되기 때문이다.

    평균은 분산을 줄일 뿐 스케일 왜곡을 상쇄하지 않는다. 트리 하나만 써도 결과는 마찬가지다.

  2. 랜덤 포레스트가 내부적으로 특성을 자동 정규화해 학습하기 때문이다.

    그런 단계는 없다. 정규화가 필요 없는 이유는 처리를 대신 해주기 때문이 아니라 분할 규칙이 값의 크기를 쓰지 않기 때문이다.

  3. 랜덤 포레스트가 특성 중요도를 계산해 값이 큰 특성의 영향을 줄이기 때문이다.

    특성 중요도는 학습 결과를 사후에 요약한 값이라 학습 과정에 되먹임되지 않는다.

  4. 정답트리의 분할 기준은 값의 크고 작음만 보므로 단위를 바꿔도 순서가 그대로이기 때문이다.

    이 값보다 큰가 작은가로만 나누므로 어떤 단조 변환을 해도 같은 분할이 나온다. 반면 KNN은 판단 근거가 거리 하나뿐이라 단위 차이가 곧바로 이웃 선택을 망친다.

해설

트리 계열은 특성을 이 값보다 큰가 작은가로만 나누므로 단위를 바꿔도 값의 순서가 그대로이고 따라서 같은 분할이 나온다. 스케일링이 결과를 바꾸지 못한다. 반면 KNN은 판단 근거가 거리 하나뿐이라 값의 폭이 가장 큰 특성이 거리의 거의 전부를 차지하고, 다른 특성은 사실상 무시된다. 같은 이유로 SVM과 K-Means도 스케일링이 필수다. 나이브 베이즈는 각 특성의 분포를 따로 추정하므로 스케일링이 필요하지 않고, 로지스틱 회귀는 규제가 없다면 예측이 스케일에 불변이지만 기본 규제가 켜진 구현에서는 결과에도 영향이 있어, 수렴 속도까지 생각하면 스케일링이 권장된다. 새 모델을 만났을 때 이 질문부터 던지면 된다. 이 알고리즘이 여러 특성의 값을 한 덩어리로 합치는가, 아니면 특성마다 따로 보는가.

이 내용 다시 읽기 →
분석과 판단운영
특성 40개짜리 데이터로 KNeighborsClassifier를 학습했다. algorithm은 기본값인 'auto'로 두었는데 예측이 데이터 크기에 정비례해 느려진다.

KD-Tree가 쓰이지 않는 이유는 무엇인가?

  1. KD-Tree는 유클리드 거리만 지원하는데 기본 거리가 민코프스키라 조건에 맞지 않기 때문이다.

    기본값은 지수가 2인 민코프스키, 즉 유클리드 거리이므로 KD-Tree가 지원하는 거리다. 걸린 조건은 거리 종류가 아니다.

  2. KD-Tree는 학습 시점에 트리를 만들어야 하는데 게으른 학습에서는 그 단계가 없기 때문이다.

    트리 구축은 실제로 학습 시점에 일어나며 그렇게 구현되어 있다. 자료구조를 만드는 것과 모델을 피팅하는 것은 다른 이야기다.

  3. 정답차원이 높으면 가지치기로 걸러지는 영역이 줄어 트리의 이점이 사라지므로 전수 탐색이 선택되기 때문이다.

    공간을 미리 분할해두어도 고차원에서는 후보를 배제할 수 없어 트리를 타고 내려가는 비용만 남는다. sklearn은 이 사정을 반영해 특성이 15개를 넘으면 전수 탐색으로 넘어간다.

  4. 표본 수가 특성 수보다 훨씬 많을 때만 트리가 유리해 데이터가 커지면 자동으로 꺼지기 때문이다.

    표본이 많을수록 트리의 이점은 오히려 커진다. 여기서 트리를 막은 것은 표본 수가 아니라 특성 수다.

해설

KD-Tree와 Ball Tree는 공간을 미리 분할해 탐색 범위를 좁혀 예측 비용을 낮춘다. 그런데 차원이 커지면 가지치기로 걸러지는 영역이 줄어들어 결국 대부분의 가지를 다 들어가 보게 되고, 전수 탐색보다 트리를 타고 내려가는 비용만 더 든다. 앞서 본 차원의 저주와 같은 뿌리다. 모든 점이 엇비슷하게 멀어지면 어떤 영역도 안전하게 배제할 수 없다. sklearn의 algorithm 기본값인 auto는 이 사정을 반영해 특성이 15개를 넘으면 트리를 만들지 않고 전수 탐색을 고른다. 그래서 고차원에서 예측이 느린 것은 설정 실수가 아니라 그 상황에서 가장 나은 선택을 라이브러리가 이미 한 결과다. 속도를 되찾으려면 알고리즘 설정이 아니라 차원 축소를 앞단에 두어야 한다.

이 내용 다시 읽기 →

마진을 최대화하는 분류기 서포트 벡터 머신(SVM)

원문 읽기 →
개념 확인구조
유방암 데이터로 학습한 SVM의 내부를 들여다봤다. 훈련 표본 455개 서포트 벡터 104개 나머지 351개는 마진 밖

이 351개 점에 대해 옳은 설명은 무엇인가?

  1. 학습에는 쓰였지만 예측 단계에서만 제외되어 추론 속도를 높인다.

    결정 경계 자체를 정하는 데도 기여하지 않는다. 예측만이 아니라 학습 결과에도 영향을 주지 않는 점들이다.

  2. 마진 밖에 있으므로 잘못 분류된 점들이고 모델이 포기한 표본이다.

    마진 밖이라는 것은 오히려 여유 있게 올바른 쪽에 놓여 있다는 뜻이다. 잘못 분류된 점은 마진을 넘어 반대편에 있다.

  3. 정답어디로 옮겨도 마진 밖에 머무는 한 결정 경계가 움직이지 않는다.

    경계를 지탱하는 것은 마진에 정확히 걸친 서포트 벡터뿐이다. 나머지는 아무리 많고 아무리 멀리 옮겨도 최적화 결과를 바꾸지 못한다.

  4. 가중치 계산에 작은 비중으로 참여하므로 수가 늘면 경계가 조금씩 이동한다.

    비중이 작은 것이 아니라 0이다. 마진 밖의 점은 힌지 손실이 정확히 0이라 목적 함수에 아무것도 더하지 않는다.

해설

SVM은 마진 경계에 정확히 걸친 점, 즉 서포트 벡터만으로 결정 경계를 정한다. 그 밖에 여유 있게 놓인 점은 힌지 손실이 0이라 목적 함수에 아무것도 더하지 않으므로, 아무리 많고 아무리 멀리 옮겨도 경계가 움직이지 않는다. 반대로 서포트 벡터 하나를 옮기면 경계 전체가 따라 움직인다. 여기서 SVM의 두 성격이 한꺼번에 나온다. 학습이 끝나면 서포트 벡터만 남기고 나머지를 버려도 되므로 모델이 가볍고, 데이터의 대다수가 결정에 관여하지 않으므로 경계에서 먼 곳의 이상치에는 흔들리지 않는다. 모든 점의 제곱 오차를 줄이려 해 멀리 있는 점 하나에 직선이 끌려가는 선형 회귀와 정확히 대비되는 성질이다.

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

RBF 커널이 대응하는 매핑은 무한 차원이라 물리적으로 계산할 수 없다. 그런데도 학습이 되는 이유는 무엇인가?

  1. 정답SVM의 쌍대 형태에서 데이터가 오직 두 점의 내적으로만 등장하므로 좌표가 필요 없기 때문이다.

    변환된 공간의 내적을 원래 좌표에서 바로 계산해주는 함수만 있으면 실제로 옮길 이유가 사라진다. 커널 트릭이 우회하는 지점이 정확히 여기다.

  2. 무한 차원 중 앞쪽 유한 개만 잘라 쓰고 나머지는 근사로 버리기 때문이다.

    근사가 아니라 정확한 계산이다. 잘라내는 단계 없이 무한 차원의 내적값이 유한한 식으로 정확히 구해진다.

  3. gamma가 큰 항의 기여를 지수적으로 줄여 실질 차원이 유한해지기 때문이다.

    gamma는 각 점의 영향 반경을 정할 뿐 차원을 잘라내지 않는다. 어떤 gamma에서도 대응하는 매핑은 무한 차원이다.

  4. 서포트 벡터만 남기므로 실제 계산에 필요한 차원이 서포트 벡터 수만큼으로 줄기 때문이다.

    서포트 벡터가 적다는 것과 매핑 공간의 차원은 별개다. 서포트 벡터 하나의 좌표만 해도 무한 차원이므로 여전히 옮길 수 없다.

해설

SVM의 최적화 문제를 쌍대 형태로 바꾸면 데이터가 오직 두 점의 내적으로만 등장한다. 좌표 자체는 필요 없고 내적값만 있으면 된다는 뜻이다. 그렇다면 변환된 공간의 내적을 원래 좌표에서 바로 계산해주는 커널 함수만 있으면 실제로 옮길 이유가 없다. 이것이 커널 트릭이고, 무한 차원에 대응하는 RBF 커널을 쓸 수 있는 이유다. 특성이 d개일 때 2차 다항식으로 올리면 새 특성이 d의 제곱 규모로 생기고 차수를 높이면 폭발하는데, 커널은 그 계산을 통째로 건너뛴다. 다만 이 우회에는 조건이 있다. 최적화 문제가 애초에 내적으로만 데이터를 보도록 쓰여 있어야 한다. 커널 트릭이 SVM의 발명이 아니라 그 구조 위에 얹힌 보너스에 가까운 이유다.

이 내용 다시 읽기 →
상황 적용운영
RBF 커널 SVM에서 gamma를 기본값에 고정하고 C만 넓게 훑어 최적값을 골랐다. 그 C를 고정한 뒤 gamma를 훑었더니 다시 다른 값이 좋게 나왔다.

이 방식의 문제는 무엇인가?

  1. 탐색 순서가 잘못됐다. gamma를 먼저 고정하고 C를 나중에 훑어야 한다.

    순서를 바꿔도 같은 문제가 생긴다. 한쪽을 고정한 채 다른 쪽을 최적화하는 절차 자체가 원인이다.

  2. 정답두 값이 같은 방향으로 복잡도를 조절하므로 한쪽을 고정하면 고정한 값에 맞춰진 국소해에 갇힌다.

    C는 위반을 얼마나 봐줄지, gamma는 경계를 얼마나 구불거리게 할지를 정하는데 둘 다 크면 함께 과적합한다. 두 축을 격자로 함께 훑어야 실제 최적 조합을 찾는다.

  3. C를 훑는 동안 gamma의 기본값이 데이터에 따라 자동으로 바뀌어 비교가 성립하지 않는다.

    같은 데이터 안에서는 자동 계산된 값도 고정이다. 폴드마다 조금씩 달라지더라도 문제의 본질은 두 값의 상호작용이다.

  4. 교차 검증 폴드 수를 늘리지 않아 각 단계의 추정이 부정확하다.

    폴드를 늘려도 단계별 탐색의 구조적 문제는 그대로다. 각 단계의 추정이 정확해도 조합을 놓치는 것은 마찬가지다.

해설

C는 마진 위반을 얼마나 비싸게 매길지를, gamma는 각 점의 영향이 미치는 반경을 정한다. gamma가 크면 각 점 주변에만 좁게 작용해 경계가 점 하나하나를 감싸듯 구불거리므로 결국 C와 같은 방향으로 복잡도를 올리는 손잡이가 되고, 둘 다 크면 확실하게 과적합한다. 한쪽을 고정하고 다른 쪽만 최적화하면 고정한 값에 맞춰진 국소해에 갇히므로 두 축을 격자 탐색으로 함께 훑어야 한다. 실험에서 눈여겨볼 지점이 하나 더 있다. C를 키울수록 교차 검증 정확도의 표준편차도 함께 커진다. 경계가 어느 폴드가 걸리느냐에 더 민감해진다는 뜻이라, 평균만 보고 고르면 안정성을 놓친다.

이 내용 다시 읽기 →
분석과 판단진단
반달 데이터에 C를 바꿔가며 교차 검증했다. noise=0.35 C=0.01 → 0.810 C=1 → 0.870 C=100 → 0.840 noise=0.30 C를 키울수록 정확도가 올라가기만 함

잡음을 줄였더니 오른쪽 끝의 과적합이 사라진 이유는 무엇인가?

  1. 잡음이 줄면 표본 수가 실질적으로 늘어난 효과가 생겨 과적합 구간이 뒤로 밀린다.

    표본 수는 그대로다. 달라진 것은 개수가 아니라 두 클래스가 겹치는지 여부다.

  2. 정답두 반달이 겹치지 않으면 위반을 비싸게 매겨도 희생할 것이 없으므로 C를 키우는 손해가 없다.

    C가 큰 것이 손해가 되려면 경계 근처에 겹치는 점이 애초에 있어야 한다. 겹침이 없으면 마진을 조금 좁혀 전부 맞히는 것이 그냥 이득이다.

  3. 잡음이 줄면 RBF 커널의 gamma 기본값이 작아져 경계가 자동으로 매끄러워진다.

    자동 계산된 gamma는 특성 수와 분산으로 정해지므로 이 정도 변화로 경계 모양이 뒤집히지 않는다. 원인은 커널 설정이 아니라 데이터 구조다.

  4. 잡음이 줄면 서포트 벡터 수가 늘어 경계가 더 많은 점의 평균으로 정해지기 때문이다.

    겹침이 줄면 마진 안에 들어오는 점이 줄어 서포트 벡터도 함께 줄어든다. 방향이 반대다.

해설

소프트 마진은 위반을 허용하되 값을 치르게 하는 장치이고 C가 그 값을 정한다. C를 크게 잡는 것이 손해가 되려면 경계 근처에 겹치는 점이 애초에 있어야 한다. 두 반달이 깔끔하게 갈리는 데이터라면 마진을 조금 좁혀 전부 맞히는 것이 그냥 이득이므로 C를 키울수록 좋아지기만 한다. 반대로 겹침이 있으면 그 점들을 맞히려고 경계를 비틀게 되고 그것이 곧 과적합이다. 소프트 마진이 필요한 상황과 C 튜닝이 의미를 갖는 상황이 정확히 같다는 뜻이다. 그래서 C 그리드에서 오른쪽 끝이 꺾이지 않는다면 튜닝이 덜 된 것이 아니라 이 데이터에 겹침이 없다는 신호로 읽어야 한다.

이 내용 다시 읽기 →
상황 적용설계
표본 30만 건, 특성 20개짜리 이진 분류 데이터에 SVC(kernel='rbf')를 걸었더니 학습이 몇 시간째 끝나지 않는다.

어떻게 대응해야 하는가?

  1. n_jobs를 올려 병렬화하면 학습 시간이 코어 수만큼 줄어든다.

    SVC의 학습 자체는 병렬화되지 않는다. n_jobs는 교차 검증이나 격자 탐색에서 여러 학습을 동시에 돌릴 때만 의미가 있다.

  2. 정답커널 SVM의 학습 시간이 표본 수에 최소한 제곱으로 늘어나므로 선형 계열이나 다른 모델로 내려가야 한다.

    libsvm 기반 구현은 수만 건을 넘어가면 현실적이지 않다. LinearSVC나 확률적 경사하강 기반 분류기, 또는 트리 기반 모델로 갈아타는 편이 낫다.

  3. gamma를 키워 각 점의 영향 반경을 좁히면 계산해야 할 커널 값이 줄어 빨라진다.

    커널 행렬은 gamma와 무관하게 같은 크기로 계산된다. gamma를 키우면 서포트 벡터가 늘어 오히려 느려지기 쉽다.

  4. C를 크게 잡아 마진 위반을 막으면 서포트 벡터가 줄어 학습이 빨라진다.

    C가 크면 마진이 좁아져 서포트 벡터는 오히려 줄어들 수 있지만, 최적화가 훨씬 어려워져 학습은 느려지기 쉽다. 표본 수의 제곱이라는 벽도 그대로다.

해설

libsvm을 쓰는 커널 SVM의 학습 시간은 표본 수에 최소한 제곱으로 늘어나 수만 건을 넘어가면 현실적이지 않다. 이 구간에서는 선형 전용 구현이나 확률적 경사하강 기반 분류기로 내려가거나, 트리 기반 모델과 신경망 쪽으로 넘어가는 편이 낫다. SVM이 확실히 앞서는 자리는 반대쪽이다. 특성 수가 표본 수에 견줄 만큼 많은 경우, 마진 최대화 자체가 모델 복잡도에 제동을 걸어주므로 차원이 높아도 거리 기반 모델처럼 무너지지 않는다. 커널만 갈아 끼워 경계의 모양을 바꿀 수 있다는 유연함도 여기서 값을 한다. 표본이 적고 특성이 많으면 SVM, 표본이 아주 많으면 다른 모델이라는 대략의 기준이 선다.

이 내용 다시 읽기 →
분석과 판단함정
SVM 분류기에서 예측 확률이 필요해져 SVC(probability=True)로 바꿨더니 학습 시간이 크게 늘었다.

이 옵션이 하는 일과 대가는 무엇인가?

  1. 결정 함수 값을 시그모이드에 그대로 통과시키는 후처리라 비용은 거의 없고 늘어난 시간은 다른 원인이다.

    시그모이드에 그냥 넣는 것이 아니라 그 시그모이드의 두 파라미터를 데이터로 학습한다. 그 학습이 비용의 원인이다.

  2. 정답SVM이 내놓는 값은 부호 있는 거리라 확률로 보정하려고 내부에서 교차 검증을 한 번 더 돌린다.

    결정 함수 값을 확률로 옮기는 보정 곡선을 학습해야 하는데 그 곡선을 훈련 데이터로 맞추면 편향되므로 5폴드 교차 검증을 따로 돌린다. 학습이 여러 배로 늘어난다.

  3. 모든 표본을 서포트 벡터로 유지해야 확률을 계산할 수 있어 모델이 무거워진다.

    서포트 벡터 집합은 그대로다. 무거워지는 것은 모델이 아니라 학습 절차다.

  4. 커널 행렬을 두 번 계산해야 하므로 메모리와 시간이 정확히 두 배가 된다.

    두 배가 아니라 폴드 수만큼 학습을 반복한다. 늘어나는 것은 커널 계산의 횟수가 아니라 모델 학습의 횟수다.

해설

SVM이 내놓는 값은 경계까지의 부호 있는 거리이지 확률이 아니다. 이 값을 확률로 옮기려면 시그모이드 모양의 보정 곡선을 학습해야 하는데, 그 곡선을 훈련 데이터에 그대로 맞추면 이미 잘 맞히는 점들 때문에 편향된다. 그래서 내부에서 5폴드 교차 검증을 한 번 더 돌려 보정용 예측을 만들고, 결과적으로 학습이 여러 배로 느려진다. 확률이 필요한 자리에서 SVM이 불리한 이유가 여기에 있다. 순위만 필요하다면 이 옵션 없이 결정 함수 값을 그대로 쓰면 되고, ROC 곡선처럼 순위 기반 지표는 보정 없이도 계산된다. 정말 확률값 자체가 필요하다면 애초에 확률을 직접 내놓는 모델을 고르는 편이 낫다.

이 내용 다시 읽기 →

질문을 반복해 데이터를 쪼개는 결정 트리

원문 읽기 →
개념 확인계산
Iris 150건을 꽃잎 길이 2.45cm로 나눴다. 부모 [50, 50, 50] gini 0.6667 왼쪽 [50, 0, 0] gini 0.0 (50건) 오른쪽 [ 0, 50, 50] gini 0.5 (100건)

이 분할의 불순도 감소량은 얼마인가?

  1. 0.4167. 자식 두 노드의 지니를 단순 평균한 0.25를 부모에서 뺀 값이다.

    자식마다 담은 샘플 수가 다르므로 단순 평균이 아니라 샘플 수 비율로 가중해야 한다. 여기서는 50 대 100이라 차이가 크게 벌어진다.

  2. 정답0.3333. 자식의 가중 평균 0.3333을 부모 0.6667에서 뺀 값이다.

    왼쪽에 3분의 1, 오른쪽에 3분의 2의 무게가 붙으므로 가중 평균이 0.5의 3분의 2인 0.3333이다. 부모에서 빼면 정확히 절반이 줄어든다.

  3. 0.5. 오른쪽 노드의 지니가 그대로 남은 불순도이므로 부모에서 그만큼 줄었다.

    오른쪽 노드의 지니 자체와 그것이 전체에 기여하는 몫은 다르다. 100건이 전체의 3분의 2이므로 기여는 0.3333이다.

  4. 0.6667. 왼쪽이 완전히 순수해졌으므로 부모의 불순도가 전부 해소됐다.

    한쪽이 순수해져도 다른 쪽에 불순도가 남아 있다. 오른쪽 100건은 여전히 두 클래스가 반씩 섞여 있다.

해설

분할의 좋고 나쁨은 자식 노드들의 가중 평균 불순도가 부모보다 얼마나 낮아졌는지로 잰다. 가중치는 각 자식에 들어간 샘플 수의 비율이다. 여기서는 왼쪽에 3분의 1, 오른쪽에 3분의 2가 걸리므로 가중 평균이 0.3333이고 부모 0.6667에서 정확히 절반이 줄었다. 트리는 특성과 임계값의 가능한 조합을 전부 시도해 이 감소량이 가장 큰 것을 고르며, 이 조합이 모든 후보 중 최선이라 첫 질문으로 뽑혔다. 지니 불순도 자체는 노드에서 샘플 하나를 뽑고 그 노드의 클래스 비율대로 무작위 레이블을 붙였을 때 틀릴 확률이다. 한 클래스만 남으면 0이고, 클래스가 K개일 때 균등하게 섞이면 1에서 K분의 1을 뺀 값이 최댓값이 된다.

이 내용 다시 읽기 →
상황 적용구조
두 클래스가 45도로 기운 직선을 사이에 두고 깔끔하게 갈리는 데이터가 있다. 로지스틱 회귀는 두 번의 분할도 없이 이 경계를 바로 찾는데, 결정 트리는 깊이를 상당히 키워야 비슷한 정확도가 나온다.

결정 트리가 이 데이터에서 불리한 이유는 무엇인가?

  1. 탐욕적으로 분할하므로 첫 분할이 최적이 아니면 이후 분할이 모두 어긋나기 때문이다.

    탐욕적 탐색은 별개의 약점이다. 여기서는 어떤 순서로 골라도 축에 평행한 조각으로만 근사해야 한다는 제약이 먼저 걸린다.

  2. 두 특성의 상관이 높으면 불순도 감소량이 서로 상쇄되어 좋은 분할을 찾지 못하기 때문이다.

    상관이 높아도 각 특성의 분할은 독립적으로 평가되고 감소량이 상쇄되지도 않는다.

  3. 지니 불순도가 기울어진 경계를 표현하지 못하므로 엔트로피로 바꿔야 하기 때문이다.

    불순도 기준을 바꿔도 분할 조건의 형태는 그대로다. 어느 자를 쓰든 나오는 경계는 축에 평행하다.

  4. 정답분할 조건이 언제나 특성 하나와 임계값 하나라 경계가 축에 평행한 직선뿐이기 때문이다.

    기운 직선을 표현하려면 계단으로 근사해야 하고, 계단을 촘촘하게 만들수록 분할이 많이 필요해진다. 두 특성의 합이나 차를 쓰는 조건은 트리가 만들지 못한다.

해설

결정 트리의 분할 조건은 언제나 특성 하나와 임계값 하나로 이루어지므로 결정 경계가 축에 평행한 직선뿐이다. 기운 경계가 필요한 문제라면 계단으로 근사해야 하고, 매끄럽게 만들수록 분할이 많이 든다. 두 특성의 합이나 차 같은 조건은 트리가 스스로 만들지 못하므로 그런 조합이 의미 있는 데이터라면 특성을 미리 만들어 넣는 것이 해법이다. 반대로 특성 축 자체가 의미 있는 기준인 데이터, 이를테면 임계값이 실제로 존재하는 센서 값이나 나이 구간에서는 이 제약이 오히려 잘 맞는다. 리프 하나가 영역 하나에 대응하므로 학습된 규칙을 그림으로 펼쳐 읽을 수 있다는 성질도 같은 구조에서 나온다.

이 내용 다시 읽기 →
상황 적용진단
Iris의 두 특성만으로 트리를 깊이 제한 없이 키웠더니 리프가 셋에서 여덟으로 늘었다. 새로 생긴 영역 중 셋은 꽃잎 너비 1.75 바로 아래의 좁은 띠를 잘라낸 조각이고, 조각마다 훈련 샘플이 한두 개씩만 들어 있다.

이 좁은 조각들을 어떻게 읽어야 하는가?

  1. 정답훈련 샘플 몇 개의 위치가 그대로 규칙이 된 것이라 과적합이 경계에 드러난 모습이다.

    그 안에 들어온 점의 좌표 말고는 근거가 없으므로 데이터가 조금만 달라져도 사라지거나 자리를 옮긴다. 새 데이터가 이 조각에 떨어지면 판정의 근거가 사실상 없다.

  2. 클래스 경계가 실제로 그 자리에서 복잡하다는 뜻이므로 특성을 더 넣어야 한다는 신호다.

    샘플 한두 개로 만들어진 영역은 실제 구조에 대한 증거가 되지 못한다. 특성을 더 넣는 것과도 무관하다.

  3. 불순도 감소량이 큰 좋은 분할이 그 자리에 있었다는 뜻이므로 유지하는 편이 낫다.

    샘플이 한둘이면 그 노드를 순수하게 만드는 것은 언제나 가능하고 감소량도 자연히 커진다. 감소량 자체는 유용함의 증거가 아니다.

  4. 트리가 축에 평행한 경계만 만들 수 있어 생긴 근사 오차이므로 구조적으로 피할 수 없다.

    축 평행 제약은 경계의 모양에 대한 이야기이고, 여기서 문제는 그 조각이 담고 있는 샘플 수다. 깊이를 제한하면 사라지므로 피할 수 없는 것도 아니다.

해설

깊이 제한이 없으면 트리는 모든 리프가 순수해질 때까지 쪼갠다. 클래스가 섞인 구석마다 분할을 하나씩 더 붙이는 셈이라 훈련 데이터의 잡음까지 규칙으로 새기고, 그 결과가 샘플 한두 개만 감싸는 좁은 영역으로 나타난다. 이런 영역은 그 안에 들어온 몇 개 점의 위치가 그대로 규칙이 된 것이라 데이터가 조금만 달라져도 사라지거나 자리를 옮긴다. 과적합이 결정 경계에 드러나는 모습이 정확히 이것이다. 깊이를 묶으면 훈련 점수를 조금 내주는 대신 이 암기를 막는다. Iris처럼 클래스가 잘 갈라진 데이터에서도 교차 검증 평균은 깊이 3 이후로 낮아지고, 잡음이 섞인 실제 데이터에서는 하락이 훨씬 뚜렷하다.

이 내용 다시 읽기 →
분석과 판단구조

단일 결정 트리가 편향은 낮고 분산은 큰 모델로 분류되는 이유는 무엇인가?

  1. 리프 수가 훈련 샘플 수에 비례해 늘어나므로 파라미터 수가 데이터 크기를 따라가기 때문이다.

    규제 없이 키우면 그렇게 되지만 그것은 결과이지 원인이 아니다. 흔들림의 크기를 만드는 것은 분할이 위에서 아래로 연쇄된다는 구조다.

  2. 지니 불순도가 클래스 비율의 제곱에 의존해 작은 비율 변화에도 값이 크게 흔들리기 때문이다.

    제곱 항은 오히려 작은 비율의 영향을 줄인다. 불순도 값 자체는 데이터가 조금 바뀌어도 완만하게 변한다.

  3. 정답매 단계 눈앞의 이득만 보고 고르므로 위쪽 분할 하나가 바뀌면 그 아래 트리 전체가 다시 그려지기 때문이다.

    루트의 후보 두 개가 감소량에서 근소하게 갈릴 때 훈련 데이터가 조금만 바뀌면 순위가 뒤집히고, 그 아래로 나뉘는 데이터 자체가 달라져 하위 구조가 통째로 다른 모양이 된다.

  4. 축에 평행한 경계만 만들 수 있어 표현력이 제한되므로 데이터에 따라 근사 오차가 크게 달라지기 때문이다.

    표현력의 제한은 편향을 올리는 요인이다. 트리의 편향이 낮다는 성질과 방향이 맞지 않는다.

해설

트리는 매 단계 눈앞의 불순도 감소량만 보고 분할을 고르는 탐욕적 알고리즘이다. 루트에서 후보 두 개가 근소하게 갈릴 때 훈련 데이터가 조금만 바뀌면 순위가 뒤집히고, 그러면 아래로 나뉘는 데이터 자체가 달라져 하위 구조가 통째로 다시 그려진다. 표현력에 제약이 거의 없어 편향은 낮은데 이 연쇄 때문에 분산이 크다. 깊이 제한 같은 규제 파라미터는 이 분산을 눌러주는 대신 편향을 올리므로 맞바꿈 안에서만 움직인다. 여기서 더 나아가려면 다른 장치가 필요하고, 그것이 트리 여러 그루를 학습해 예측을 합치는 방법이다. 실무에서 단일 트리를 그대로 쓰는 일이 드문 이유다.

이 내용 다시 읽기 →
상황 적용운영
양성이 1%인 사기 탐지 데이터에 결정 트리를 학습했더니 거의 모든 리프가 정상으로 예측한다. 깊이 제한도 걸지 않았는데 소수 클래스를 잡아내는 규칙이 생기지 않는다.

무엇이 원인이고 어떻게 대응해야 하는가?

  1. 깊이 제한이 없어 트리가 너무 커진 탓이므로 max_depth를 걸어 규칙을 단순화해야 한다.

    깊이를 줄이면 소수 클래스를 잡는 규칙이 오히려 더 생기기 어려워진다. 방향이 반대다.

  2. 특성 스케일 차이 때문에 소수 클래스를 가르는 특성이 임계값 후보에서 밀린 것이므로 표준화가 필요하다.

    트리는 값의 순서만 보므로 스케일에 완전히 불변이다. 표준화를 넣어도 결과가 한 자리도 바뀌지 않는다.

  3. 정답소수 클래스를 통째로 무시해도 불순도가 거의 줄지 않으므로 클래스 가중치를 걸어야 한다.

    양성이 1%면 그 전부를 틀려도 지니가 0.0198에서 거의 내려가지 않아 분할할 이유가 생기지 않는다. 균형 가중치를 주면 불순도 계산에서 소수 클래스의 몫이 커진다.

  4. 지니 대신 엔트로피를 쓰면 소수 클래스의 기여가 커지므로 기준을 바꿔야 한다.

    엔트로피가 작은 비율에 조금 더 민감하기는 하지만 1% 대 99%의 격차를 뒤집을 정도는 아니다. 두 기준은 거의 같은 분할을 고른다.

해설

양성이 1%인 데이터에서는 소수 클래스를 통째로 무시해도 불순도가 거의 줄어들지 않는다. 그 상태의 지니가 이미 0.02에 가까워 더 낮출 여지가 별로 없기 때문이고, 그래서 트리는 다수 클래스만 맞히는 쪽으로 자란다. 균형 클래스 가중치를 주면 각 클래스에 전체 샘플 수를 클래스 수와 그 클래스의 샘플 수의 곱으로 나눈 값이 붙어, 불순도 계산에서 소수 클래스 한 건이 다수 클래스 여러 건만큼의 무게를 갖는다. 소수 클래스를 잡아내는 분할이 비로소 이득으로 보이게 되는 것이다. 평가 지표도 함께 바꿔야 한다. 이런 데이터에서는 전부 정상으로 찍어도 정확도가 99%이므로 정밀도와 재현율을 기준으로 삼아야 한다.

이 내용 다시 읽기 →
분석과 판단구조
이진 분류에서 두 불순도 기준의 최댓값이 다르다. 엔트로피 p=0.5에서 1.0 지니 p=0.5에서 0.5

최댓값이 두 배나 차이 나는데도 두 기준이 거의 같은 트리를 만드는 이유는 무엇인가?

  1. sklearn이 내부에서 엔트로피를 지니 척도로 정규화한 뒤 비교하기 때문이다.

    그런 변환은 없다. 각 기준의 값을 그대로 쓰며, 같은 기준 안에서만 비교하므로 정규화가 필요하지도 않다.

  2. 정답두 곡선 모두 양 끝에서 0이고 가운데서 최대인 같은 모양이라 후보 사이의 순위가 대체로 같기 때문이다.

    분할 선택은 감소량의 절댓값이 아니라 후보끼리의 순위로 정해진다. 척도가 달라도 순위가 보존되므로 같은 분할이 뽑힌다.

  3. 가중 평균을 낼 때 샘플 수로 나누므로 척도의 차이가 상쇄되기 때문이다.

    샘플 수 가중은 두 기준에 똑같이 적용되므로 척도 차이를 없애지 못한다. 엔트로피의 감소량은 여전히 지니보다 큰 값으로 나온다.

  4. 엔트로피 계산이 느려 sklearn이 지니로 근사한 뒤 결과만 엔트로피로 환산하기 때문이다.

    지정한 기준으로 실제 계산한다. 로그 계산이 없어 지니가 조금 빠른 것은 사실이지만 대체하지는 않는다.

해설

두 곡선은 클래스 비율이 0이나 1일 때 0이고 가운데서 최대인 같은 모양이며, 최댓값만 두 배 차이가 난다. 분할 선택은 감소량의 절댓값이 아니라 같은 기준 안에서 후보끼리 매긴 순위로 이루어지므로, 척도가 달라도 순위가 대체로 보존되어 같은 분할이 뽑힌다. 실무에서 성능 차이가 거의 없다는 말은 이런 뜻이다. 굳이 성격을 나누자면 지니는 로그 계산이 없어 조금 빠르고 큰 클래스를 먼저 떼어내는 경향이 있으며, 엔트로피는 정보량으로 해석되고 조금 더 균형 잡힌 트리를 만든다. 기본값인 지니를 그대로 쓰면 되고, 이 선택으로 성능을 끌어올리려는 시도보다 깊이와 리프 조건을 조율하는 편이 훨씬 큰 차이를 만든다.

이 내용 다시 읽기 →

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

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