개요
지난 글에서 선형회귀를 정리했다. 직선 하나로 숫자를 예측하고, 계수를 읽어 관계까지 해석하는 방법이었다.
이번엔 문제를 바꾼다. “이 고객이 카드값을 연체할까?”처럼 답이 숫자가 아니라 예/아니오인 문제다. 여기에 선형회귀를 그대로 쓰면 왜 안 되는지, 그리고 그걸 어떻게 고친 게 로지스틱회귀인지가 이 글의 내용이다.
미리 못 박아둘 게 하나 있다. 이름에 “회귀”가 붙어 있지만 로지스틱회귀는 분류 모델이다. 이 작명 때문에 초반에 꽤 헷갈렸는데, 이유는 글 중간에 나온다. 속에 선형회귀가 그대로 들어 있어서다.
1. 여기서부터 분류 — 왜 선형회귀로는 안 되나
이제 문제를 바꿔보자. “이 고객이 카드값을 연체할까?” 같은 예/아니오 문제다.
정답이 0(정상) 또는 1(연체)이니, 선형회귀로 0과 1을 예측하면 되지 않을까? 안 된다.
이유는 그림에 다 있다. 직선은 끝없이 뻗어나간다. 그래서 입력값이 크거나 작으면 예측값이 1을 넘거나 0 아래로 내려간다.
“연체할 확률 137%”, “연체할 확률 −20%”
말이 안 되는 값이다. 확률로 쓸 수가 없다.
다중 분류에서는 더 심각하다
범주가 3개 이상이면 문제가 더 커진다. 날씨를 예측한다고 {1: 맑음, 2: 눈, 3: 비}처럼 숫자를 붙이면,
- 맑음(1)과 눈(2) 사이 거리 = 1
- 눈(2)과 비(3) 사이 거리 = 1
- 그러니까 “맑음과 눈의 차이”와 “눈과 비의 차이”가 같다고 주장하는 셈
게다가 맑음 < 눈 < 비라는 순서까지 암묵적으로 생긴다. 실제로는 아무 순서도 없는데.
범주형 변수에 그냥 번호를 매기는 순간, 의도하지 않은 순서와 거리를 모델에게 가르치게 된다. 이건 개발할 때 열거형(enum)을 int로 캐스팅해 쓰다가 사고 나는 것과 정확히 같은 함정이다.
2. 로지스틱회귀 — S자 곡선으로 눌러 담기
해결책은 우아하다. 직선의 출력을 0과 1 사이로 눌러 담는 함수를 하나 씌우는 것이다. 그게 시그모이드(Sigmoid)다.
1
S(z) = ─────────
1 + e⁻ᶻ
말로 옮기면 “어떤 숫자를 넣어도 0과 1 사이 값으로 바꿔주는 함수”다.
| z가 | S(z)는 |
|---|---|
| 아주 큰 양수 | 1에 한없이 가까워짐 |
| 0 | 정확히 0.5 |
| 아주 큰 음수 | 0에 한없이 가까워짐 |
중요한 건 0과 1에 절대 도달하지는 않는다는 점이다. 무한히 가까워질 뿐이다. 그래서 로지스틱회귀의 출력 범위는 0과 1을 포함하지 않는 사이값이다. “절대 100% 확신하지 않는다”는 성질인데, 개인적으로 꽤 마음에 들었다.
그래서 로지스틱회귀는 이렇게 만들어진다.
로지스틱회귀 = 선형회귀 + 시그모이드
범주가 3개 이상이면? 시그모이드 대신 소프트맥스를 쓴 다항 로지스틱회귀로 확장한다. 각 범주에 점수를 매긴 뒤 전부 더해서 1이 되도록 나눠주는 방식이라, 위에서 지적한 “번호를 매기면 없던 순서가 생긴다” 문제가 사라진다. 원리는 같으니 이 글에서는 이진 분류만 본다.
선형회귀로 숫자를 하나 뽑고, 그 숫자를 시그모이드에 통과시켜 확률로 바꾼다. 이름에 “회귀”가 붙은 이유가 이거였다. 속에 선형회귀가 그대로 들어 있다.
3. 오즈와 로짓 — 왜 굳이 로그를 씌우나
로지스틱회귀를 설명할 때 반드시 나오는 개념이 오즈와 로짓이다. 처음엔 “왜 굳이 이런 걸?” 싶었는데, 이유를 알고 나니 납득이 됐다.
오즈(Odds)
오즈 = 성공 확률 ÷ 실패 확률
“실패에 비해 성공이 몇 배나 되는가”다. 스포츠 중계에서 “이 팀이 이길 확률 9대 1”이라고 할 때의 그 9대 1이 오즈다.
- 성공 확률 0.5 → 오즈 = 0.5 ÷ 0.5 = 1 (반반)
- 성공 확률 0.9 → 오즈 = 0.9 ÷ 0.1 = 9 (성공이 9배 유력)
- 성공 확률 0.1 → 오즈 = 0.1 ÷ 0.9 = 0.11
확률은 0~1에 갇혀 있지만, 오즈는 0부터 무한대까지 늘어난다. 위쪽 제한이 풀렸다. 확률이 0.999가 되면 오즈는 999, 0.9999면 9999로 끝없이 커진다.
로짓(Logit) = 로그 오즈
문제는 아래쪽이다. 오즈는 아무리 작아져도 0 밑으로는 못 간다. 그래서 로그를 한 번 더 씌운다.
로짓 = log(오즈)
로그는 1보다 작은 수를 음수로 보내는 함수다. 그래서 이 한 방으로 아래쪽 벽도 사라진다.
- 오즈가 1보다 크면 → 로짓은 양수
- 오즈가 1이면 → 로짓은 0
- 오즈가 1보다 작으면 → 로짓은 음수
실제 숫자로 보면 이 변환이 무슨 일을 하는지 한눈에 들어온다.
| 확률 p | 오즈 = p / (1−p) | 로짓 = log(오즈) |
|---|---|---|
| 0.01 | 0.010 | −4.60 |
| 0.10 | 0.111 | −2.20 |
| 0.25 | 0.333 | −1.10 |
| 0.50 | 1 | 0 |
| 0.75 | 3 | +1.10 |
| 0.90 | 9 | +2.20 |
| 0.99 | 99 | +4.60 |
이 표를 보고 두 가지가 눈에 들어왔다.
① 로짓은 0.5를 기준으로 완벽하게 대칭이다. 확률 0.9와 0.1은 로짓에서 +2.20과 −2.20이다. 확률로 보면 0.9와 0.1은 “0.8만큼 차이”지만, 로짓으로 보면 부호만 뒤집힌 같은 크기다. 훨씬 다루기 좋은 형태다.
② 양 끝으로 갈수록 로짓이 급격히 벌어진다. 확률이 0.90에서 0.99로 갈 때, 확률은 0.09밖에 안 늘었는데 로짓은 2.20에서 4.60으로 2배가 됐다. “거의 확실”에서 “진짜 확실”로 가는 게 그만큼 어려운 일이라는 걸 숫자가 반영한다.
이제 −∞부터 +∞까지 전 구간을 쓸 수 있다. 그리고 이게 정확히 직선이 필요로 하는 범위다.
그래서 결론은 확률에 직접 직선을 붙이면 범위가 안 맞아서 터지지만, 로짓으로 바꿔놓으면 직선을 그대로 얹을 수 있다.
즉 로지스틱회귀는 이렇게 두 방향으로 읽을 수 있다.
| 방향 | 읽는 법 |
|---|---|
| 예측할 때 | 선형회귀 결과를 시그모이드에 넣어 확률을 만든다 |
| 해석할 때 | 로짓(로그 오즈)이 입력에 대해 직선으로 변한다 |
같은 걸 뒤집어 본 것뿐이다. 문제를 직접 풀지 않고, 풀기 쉬운 축으로 옮겨서 푸는 발상이다.
이건 데이터 시각화를 정리하면서 만났던 것과 같은 기술이다. 값의 범위가 너무 넓어 그래프가 뭉개질 때 y축을 로그 스케일로 바꾸면 갑자기 읽히는 그림이 되는데, 데이터를 고친 게 아니라 보는 축을 바꾼 것이다. 로짓 변환도 정확히 그 일을 한다.
해석할 때 주의할 점
이 구조 때문에 계수 해석이 선형회귀보다 까다롭다.
계수가 0.0055라면, 이건 “확률이 0.0055 오른다”가 아니라 “로그 오즈가 0.0055 오른다”는 뜻이다. 로그를 되돌리면 덧셈이 곱셈으로 바뀌므로, 확률 변화는 원래 위치에 따라 달라진다.
로짓이 1 오르면 오즈는 e배(약 2.7배)가 된다. 이게 로지스틱회귀 계수를 읽는 핵심 문장이다.
실제 예시로 따라가 보면 이렇다. 카드 사용액이 1000에서 2000으로 늘었다고 하자.
| 단계 | 계산 | 결과 |
|---|---|---|
| 로짓 증가량 | 0.0055 × 1000 | +5.5 |
| 오즈 배율 | e^5.5 | 약 245배 |
| 확률 변화 | 0.006 → 0.586 | 약 97배 |
여기서 재밌는 게 하나 보인다. 오즈는 245배가 됐는데 확률은 97배밖에 안 늘었다. 이유는 단순하다. 확률은 1을 넘을 수 없기 때문이다. 0.006에 245를 그대로 곱하면 1.47이 되는데, 그런 확률은 존재할 수 없으니 S자 곡선이 알아서 눌러 담은 것이다.
오즈는 마음껏 커질 수 있고, 확률은 천장이 있다. 그래서 계수를 정직하게 해석하려면 확률이 아니라 오즈 기준으로 말해야 한다.
선형회귀는 “얼마나 더해지는지”를 말하지만, 로지스틱회귀는 “몇 배가 되는지”를 말한다. S자 곡선이니 당연하다. 가운데 구간에서는 조금만 움직여도 확률이 확 변하고, 양 끝에서는 아무리 밀어도 잘 안 변한다.
4. MLE — 계수는 어떻게 정하나
선형회귀에서는 “잔차 제곱합을 최소로”였다. 로지스틱회귀에서는 뭘 최소화하나?
여기서 새로운 개념이 나온다. 우도(Likelihood)다.
우도 = 지금 이 확률 함수가 실제 데이터를 얼마나 잘 설명하는가
이 개념이 이번 강의에서 제일 헷갈렸다. 확률과 뭐가 다른지가 계속 안 잡혔는데, 결국 무엇을 고정하고 무엇을 움직이는지의 차이였다.
| 고정된 것 | 움직이는 것 | 묻는 것 | |
|---|---|---|---|
| 확률 | 모델(계수) | 결과 | “이 모델이 맞다면, 이런 일이 벌어질 확률은?” |
| 우도 | 결과(데이터) | 모델(계수) | “이런 일이 실제로 벌어졌는데, 이 모델은 얼마나 그럴듯한가?” |
데이터는 이미 일어난 사실이라 못 바꾼다. 바꿀 수 있는 건 모델뿐이다. 그래서 “데이터를 가장 그럴듯하게 설명해주는 모델”을 찾는 것이고, 그 그럴듯함의 척도가 우도다.
숫자로 따라가 보기
말로만 하면 계속 미끄러져서, 작은 예로 직접 계산해봤다. 고객 3명의 실제 결과가 이렇다고 하자. 이건 사실이고 안 바뀐다.
| 고객 | 실제 | |
|---|---|---|
| A | 연체함 | |
| B | 정상 | |
| C | 연체함 |
이제 후보 모델 두 개가 각자 연체 확률을 내놓는다.
| 고객 | 실제 | 모델 1이 준 연체 확률 | 모델 2가 준 연체 확률 |
|---|---|---|---|
| A (연체) | 1 | 0.8 | 0.3 |
| B (정상) | 0 | 0.2 | 0.6 |
| C (연체) | 1 | 0.7 | 0.4 |
우도는 “실제로 일어난 일에 이 모델이 매긴 확률”을 전부 곱한 값이다. 여기서 주의할 게 하나 있다. B는 정상이었으니, B에 대해 봐야 할 값은 연체 확률이 아니라 정상일 확률(1 − 연체 확률)이다.
모델 1의 우도 = 0.8 × (1 − 0.2) × 0.7
= 0.8 × 0.8 × 0.7 = 0.448
모델 2의 우도 = 0.3 × (1 − 0.6) × 0.4
= 0.3 × 0.4 × 0.4 = 0.048
모델 1의 우도가 약 9배 크다. 실제로 표를 보면 모델 1은 연체한 사람에게 높은 확률(0.8, 0.7)을, 정상인 사람에게 낮은 확률(0.2)을 줬다. 모델 2는 전부 반대로 찍었다. 계산 결과가 직관과 정확히 일치한다.
그래서 학습이란 이 곱셈 결과가 가장 커지도록 계수를 조정하는 것이고, 이걸 최대우도추정(MLE)이라고 부른다.
| 선형회귀 | 로지스틱회귀 | |
|---|---|---|
| 기준 | 잔차 제곱합(RSS) | 우도(Likelihood) |
| 방향 | 최소화 | 최대화 |
| 뜻 | 덜 빗나가게 | 더 그럴듯하게 |
참고로 교차 엔트로피와 사실상 같은 것이다. 지도학습 평가를 정리한 글에서 “정답에 준 확률에 −log를 씌운 벌점”이라고 했는데, 그걸 전부 더한 게 로그우도에 마이너스를 붙인 값이다. 우도를 최대화하는 것 = 교차 엔트로피를 최소화하는 것. 이름만 두 개고 하는 일은 하나였다.
로그를 씌우는 이유 (또 로그다)
우도는 각 데이터의 확률을 전부 곱한 값이라고 했다. 그런데 곱셈이라 실무에서 바로 터진다.
확률은 전부 1보다 작은 수다. 1보다 작은 수를 계속 곱하면 값이 미친 듯이 작아진다.
데이터 3개 : 0.5 × 0.5 × 0.5 = 0.125
데이터 10개 : 0.5를 10번 곱하면 ≈ 0.00098
데이터 2000개 : 0.5를 2000번 곱하면 ≈ 10⁻⁶⁰²
마지막 줄이 문제다. 컴퓨터가 표현할 수 있는 가장 작은 실수보다도 작다. 실제 계산에서는 그냥 0으로 뭉개진다. 0이 되어버리면 어느 모델이 더 나은지 비교 자체가 불가능해진다. 실무에서 말하는 언더플로가 정확히 이 상황이다.
여기에 로그를 씌우면 곱셈이 덧셈으로 바뀐다.
log(a × b) = log a + log b
곱셈 2000번이 덧셈 2000번이 되고, 값도 10⁻⁶⁰² 같은 극단적인 수 대신 −602 정도의 평범한 숫자가 된다. 이제 컴퓨터가 아무 문제 없이 다룬다.
덤으로 미분도 훨씬 쉬워진다. 곱셈을 미분하려면 규칙이 복잡하지만, 덧셈은 항별로 따로 미분해서 더하면 끝이다. 다음 글의 경사 하강법이 이 성질에 기대고 있다.
그래도 답이 같은 이유
여기서 당연히 이런 의문이 든다. “함수를 바꿔놓고 푼 답이 원래 답과 같나?”
답은 같다. 이유는 하나다.
로그는 단조 증가 함수다. 즉 순서를 절대 뒤집지 않는다.
A가 B보다 크면, log A도 log B보다 크다. 그러니 가장 큰 값의 위치는 변하지 않는다. 그림에서 두 곡선은 모양이 전혀 다른데 꼭대기의 가로 위치는 같다.
앞의 두 모델로 확인해보면 바로 납득이 된다.
| 우도 | 로그우도 | |
|---|---|---|
| 모델 1 | 0.448 | −0.80 |
| 모델 2 | 0.048 | −3.04 |
숫자는 완전히 달라졌지만 여전히 모델 1이 이긴다. (둘 다 음수인 게 어색해 보이는데, 1보다 작은 수에 로그를 씌우면 항상 음수가 나온다. 0에 가까울수록 좋은 것이다.)
더 쉬운 비유로. 키 순서로 줄을 세운 다음 모두를 똑같은 규칙으로 줄여도, 가장 큰 사람은 여전히 가장 크다.
다만 공식으로는 안 풀린다
선형회귀와 결정적으로 다른 점이 여기 있다. 로지스틱회귀에는 닫힌 해가 없다. 공식에 넣어 한 번에 계산할 수가 없다.
그래서 기울기를 보고 조금씩 값을 옮겨가며 반복적으로 찾아간다. 그 방법이 바로 다음 글의 주제인 경사 하강법이다.
정리
- 분류에 직선을 그대로 쓰면 확률이 0~1 범위를 벗어난다 → 시그모이드로 눌러 담는다
- 범주에 번호를 매기면 없던 순서와 거리가 생긴다. 범주는 순서 없는 집합이다
- 로지스틱회귀 = 선형회귀 + 시그모이드. 출력은 0과 1에 닿지 않는 사이값
- 확률 → 오즈 → 로짓으로 갈수록 범위 제한이 풀린다. 로짓은 0.5를 기준으로 대칭
- 계수는 오즈의 배율로 읽어야 정확하다. 로짓이 1 오르면 오즈는 e배(약 2.7배)
- 우도 = 데이터를 고정해두고 모델이 얼마나 그럴듯한지 재는 값. 학습은 이걸 최대화(MLE)
- 로그를 씌우는 건 언더플로를 피하고 미분을 쉽게 하려는 것. 답은 그대로다
- 로지스틱회귀에는 닫힌 해가 없다. 값을 조금씩 옮겨가며 찾아야 한다
다음 글에서
다음 글에서는 신경망의 구조를 뜯어보고, 이번 글에서 미뤄둔 “닫힌 해가 없으면 값을 어떻게 찾느냐” — 경사 하강법과 역전파를 정리한다.
한줄 평
- 어.. 어ㅓㅓ.? ㅓ… 음.. 아하! 의 반복이 지속될 예정이고, 작은 흐름이라도(직관) 읽어가는 걸 추천한다.