본문 바로가기
Logistic Regression의 환장파티 - Sigmoid 출력값이 왜 확률인가요?

종속변수가 연속형인 경우의 회귀를 해 보았는데 말이죠, 그러면 종속변수가 1, 0만 갖는 Binary인 경우에도 회귀가 가능할까 한번 들여다보시죠. 

일단 Logistic 회귀를 다룰 때 0과 1만 다룬다굽쇼? 그렇다면 이거 만만하겠는걸 이라고 생각하고 덤비게 됩니다. 짜잔. 굉장히 쉬울 줄 알았는데, 실제로 사용하려고 보면 이거 다 이해했다고 생각했는데도 불구하고 막상 뒤통수를 맞게 되고, 내가 이해한 게 아니구나.. 하고 어디서부터 잘못된 거지... 하게 됩니다. 가장 큰 헷갈림은 종속변수가 1, 0으로 시작했으니까, 회귀 모형 출력이 1,0으로 나와야 할 것 같은데 회귀 모형의 출력이 확률이라고 합니다. 엥? 왜죠? 분명히 종속변수 1, 0을 Regression 했는데, 왜 모형의 출력이 확률이라는 건지 어리둥절하게 됩니다. 

어쨌든 각설하고 당장 로지스틱회귀를 자세히 알아봅시다. 종속변수가 1, 0으로 이루어진 로지스틱 회귀가 나올 때 흔히 설명하는 방식은 다음과 같이 굉장히 심플합니다. 

 

간단하군요. 으흠~ 시그모이드라는 걸 쓰면 되겠구만요? 간단하구먼, 그렇다면 이제 종속변수 1,0에 맞춰서 회귀선을 구할 수 있겠구만. 이해 끗~. 별거 없구만.인줄 알았습니다만. 여기에서 갑자기 Sigmoid의 출력은 확률이다. 그리고 Odds라는 게 불현듯 끼어들면서부터 이게 무슨 돼지 뚱딴지같은 소리 다냐 싶습니다. 왜 1/0의 종속변수를 Regression 했는데 회귀 결과가 1/0이 아니라 확률인가요? 

아, 더 자세히 살펴보기 전에 꼭 짚고 넘어가야 하는 것이 하나있는데 그게 뭐냐면 Sigmoid라는 것인데요, 이것의 정의를 살펴보면 S자 곡선을 그리면서 한정된 a~b사이의 값을 갖고 항상 Monotonically 증가하는 함수를 "통칭"해서 시그모이드라고 부릅니다. 그래서 Sigmoid 함수에는 Logistic 함수, tanh(x) (하이퍼볼릭 탄젠트) 함수, Smoothstep 함수, algebraic 함수등 많은 함수들이 Sigmoid 함수라고 구분될 수 있습니다. 조금 이르지만 기계학습에 이야기가 이르게 되면 Activation Function을 Sigmoid로 퉁쳐서 부르는 경우가 있는데, S곡선을 그리는 한정된 치역을 갖는 함수는 Activation Function으로 뭐든지 쓸 수 있어서 그렇습니다. 여튼 지금 필요한 함수는 S곡선 모양의 함수가 필요하니 로지스틱 함수를 Sigmoid로 퉁쳐서 가보도록 하시죠.

자, 그럼 본격적으로 이걸 잘 이해하기 위해서 조금 더 자세하게 로지스틱 회귀를 어떤 식으로 이해하면 좋을지 다시 한번 보겠습니다. 

 

아주 자연스러웠어. 방금 전과 같은 당연한 접근입니다. 그런데요?

 

자, 어떤가요? x를 구획을 나눠서 각각의 구획에서 $\cfrac{\#1}{\#1+\#0}$을 이용하여 각 구획의 1의 비율을 구합니다. 여기에서 #은 개수라는 뜻입니다. 그러니까 결국 1이 나올 확률이죠. #1은 1의 개수, #0은 0의 개수입니다. 그러니까 실제로는 y가 1,0 값을 갖는 것에 대한 회귀하는 것이 아니라, y가 갖는 확률값을 회귀하는 것입니다. 후후. 뭔가 보이기 시작하는군요.

 

이렇게 하면 실제로는 확률값에 대한 회귀식을 구하는 것이기 때문에 Sigmoid의 출력값은 확률이 됩니다. 뙇. 그렇군요! 오. 그러면 이해가 됩니다. 이런 식으로 들여다보면 아주 쉬운 이야기로군요. 이걸 건너뛰면 모든 이해가 엉망이 됩니다. 

후후. 이제 그 느낌 아니까~ 수준이 될 수 있을 거라 생각합니다. 

자, 이제 여기에서 확률값 자체를 회귀하겠다는 의미를 알았으니까, 이제는 확률값 P(x)를 Sigmoid에 맞추어 회귀를 하면 됩니다. - 그러니까 다시한번 강조하자면 Sigmoid의 출력은 애초에 확률 값을 회귀분석했기 때문에 확률입니다. - 

자, 이제부터는 조금 더 Specific하게 Sigmoid를 Logistic 함수로 특정해서 이야기해 보시죠. 이 글의 제목이 Logistic 회귀니까요. 흐흐. Logistic 함수는 다음과 같습니다. 

$$f(x) = \cfrac{1}{1+e^{-x}}$$

Logistic 함수로 Sigmoid를 특정해서 이야기하게 되니깐,

 

짜잔 , P(x)를 Logisitc 함수를 이용해서 회귀 분석하여 표현할 수 있겠습니다. 여기에서 Logistic 함수의 가파른 정도와 꺾이는 시점이 여러 가지가 있겠죠. 그것을 감안해서 분모의 $e^{-x}$를 조금 더 여러가지 모양새의 시그모이드 형태가 가능하도록 $f(x) = b_0 + b_1 x$ 같은 식으로 대체를 하게 되면 b₁에 의해서 가파른 정도가 결정될 수 있고, b₀에 의해서 어디서 부터 꺾이기 시작할지의 모양새를 결정할 수 있습니다. b₁ 값이 클 수록 Logistic함수가 가파르게 서게 되고, b₀값이 양수로 클 수록 더 왼쪽으로 Shift됩니다. 이렇게만 된다면 종속변수가 1,0인 것에 대해서는 어떤 모양이라도 종속변수가 확률인 것에 대한 회귀를 할 수 있습니다. 


어쨌든 여러가지 모양새의 Logisitc 함수의 변형은 말이죠.

이런 식으로 결정될 수 있습니다.  

그냥 이렇게 쓰고 보니, $b_0 + b_1 x$이 딱 단순 선형회귀식 느낌이잖아요? 그러니까 이 회귀식을 우변에 두고 $P(x) = \cfrac{1}{1+e^{-(b_0 + b_1 x)}} $를 정리해 보면 $$ \cfrac{P(x)}{1-P(x)} = e^{b_0 + b_1 x} $$ 요런 식이 나옵니다. 드디어 나와 버렸습니다. Odds라는 거. Odds라는 게 뭐냐면, 1을 성공 0을 실패라고 했을 때 성공과 실패의 비율, 즉,  P(1)/P(0)을 말합니다. 실패에 비해서 얼마나 성공 확률이 큰가를 따지는 것인데요. 난데없이 등장한 Odds 때문에 이야기가 옆으로 새면 안 되니까, 지금은 오~ 그런 게 있단 말인가 정도로 받아들여 주세요. 

어쨌든 Exponential이 나왔으니까 양변에 로그를 취하면 우변에 선형회귀식과 비슷한 꼴이 남습니다. 

$$ ln \left(\cfrac{P(x)}{1-P(x)}\right)  = b_0 + b_1 x $$

결국 요렇게 됩니다. 오흥~ 이거 보니까 ln(Odds)가 우변의 선형회귀처럼 된다는 것인데 이렇게 함으로써, Logistic함수의 모양새를 결정하는 선형회귀식을 구할 수 있다는 뜻입니다. 이것은 으하! 회귀문제를 선형회귀와 마찬가지의 같은 방법으로 일관성 있게 풀 수 있다는 뜻입니다. 그게 무슨 멍멍인가 하면 P(x)를 Log(odds)로 변환한 후 쭉 뻗은 직선에 맞는 확률 선형회귀를 하면 된다는 뜻입니다. 헛. 대발견 

 

결국 Log(Odds)가 이렇게 쭉 뻗은 직선이 됩니다. 헛. 그러면 우리가 이제까지 했던 Linear Regression을 그대로 적용해서 분석할 수 있겠군요? 그러니까,
$ln \left(\cfrac{P(x)}{1-P(x)}\right) = y = b_0+b_1 x$의 회귀식으로 선형회귀를 풀 수 있다는 의미입니다. 이때 이제까지 Log(Odds)라고 부르던 것을 세상 사람들은 Logit이라고 부릅니다. 어허. 이 Logit을 선형회귀하면 된다! 이것이 로지스틱회귀의 정체인 것입니다. 짜잔.

 

이게 다 Logistic 회귀에서 Logit입니다. 참고로 Logit은 Log+Probit이라는 말의 합성어라고 하는데, Probit은 Probability Unit의 합성어라고 합니다. 이 이야기는 나중에 하도록 하겠습니다. 어쨌든 Logit이라고 합니다. 

합쳐보면 이런 느낌이라고나 할까요? 그러면

 

이제부터 Logit이라는 것의 유용함이 나오는데요, 종속변수를 p/(1-p)로 생각하면 로그를 적용한 종속변수라고 볼 수 있겠습니다. 이 경우의 해석은 "데이터를 로그변환했을 때 벌어지는 일과 결과해석"편에서 본 것을 그대로 적용하여 

"독립변수 x가 1 단위 변하면 P/(1-P) 즉, 성공/실패확률의 값이 (100•b₁)%만큼 변하게 됩니다." 라고 해석할 수 있겠습니다. - 변수에 로그를 취했을 때 어떤 일이 벌어지는 지 미리 봐두길 잘했습니다. -  Logit을 이용하니까 이런 해석도 가능하군요. 대박. 실제로는 뒤에 이야기 할 작정이지만 엄밀하게 이야기한다면 우변을 Exponential로 만들어서 x가 1단위 변할 때 Odds비가 $e^{b_1}$ 만큼 변한다고 해석하는 것이 맞긴 맞습니다.

자, 그럼 여기까지 온 김에 급물살을 타보면, 이 로지스틱회귀라는 것도 다중회귀가 가능하겠습니다. 어떻게요?  일반화 한번 해볼까요. 

$$
\ln \left(\frac{P(y=1 |\,\boldsymbol{x})}{1-P(y=1 |\,\boldsymbol{x})}\right)=b_{0}+b_{1} x_{1}+\cdots+b_{i} x_{i}
$$
자세히 보면 x가 여러 종류 즉, $x_1 , x_2 , x_3 , \cdots x_i $라는 의미에서 bold입니다. 
$$
\therefore \frac{P(y=1|\,\boldsymbol{x})}{1-P(y=1|\,\boldsymbol{x})}=e^{ \left(\beta_{0}+\beta_{1} x_{1}+\ldots+\beta_{i} x_{i}\right)}
$$

똑같지요? 이번에는 j번째 x를 1만큼 증가시키면!

$$
\frac{e^ \left(b_{0}+b_{1} x_{1}+\cdots+b_{j}\left(x_{j}+1\right)+\ldots+b_{i} x_{i}\right)}{e^ \left(b_{0}+b_{1} x_{1}+\cdots+b_{j} x_{j}+\cdots+b_{i} x_{i}\right)}
$$

$$
\therefore e^{b_j}  
$$

다중회귀에서 j번째 계수가 얼마나 영향을 미치는지 알 수 있겠네요. 이것은 $odds_{new} = odds_{old} \cdot e^{b_j}$ 라고 해석할 수 있겠습니다. - 원래 odds비에 $e^{b_j}$배가 된다는 의미입니다 - 예를 들어, 원래 odds ratio가 1였고, $b_j=0.3 → e^{0.3})\approx 1.34 $일 때 $x_j$를 1만큼 올리면! odd는 1.34배가 된다는 뜻입니다요. 이거 로그를 씌운 변수에 대해서 대략적으로 읽어도 j번째 x가 1 변할 때 계수가 0.3이라면 종속변수 odds는 30% 정도 늘어난다고 읽어도 되겠네요. ㅎㅎ 

이야기가 자꾸 거꾸로 거슬러 올라가고 있긴 한데, 그러니까 로지스틱 다중회귀에 대해서 간단한 예를 들어 본다면, 간경화를 판단하는 로지스틱 회귀에 대한 각각의 계수의 영향력은 그림과 같겠죠. 헤헤.

 

이 시점에서 다중회귀의 독립변수와 계수를 일일이 표기하기 어려우니까, $\hat{y} = \cfrac{1}{1+e^{-W^T X}}$ 형태로 행렬을 이용해서 표현합니다. 여기에서 W는 Weight의 의미인데, 이제까지의 분석에서는 계수를 b로 표현하고, 기계학습에서는 계수를 Weight, W로 표현합니다. 똑같은 이야기입니다. 자, 다중로지스틱회귀까지 모두 하찮게 살펴보았습니다. 훗. 결과만 보았을 때 꽤나 성의 없이 별거 없는 내용인 줄 알았는데 꽤나 많은 내용들이 포함되어 있군요.

자, 그러면 진짜로 그런가? 실전! Logistic 회귀를 해 봅시다. 

일단 이렇게 생긴 데이터가 있습니다. 129개의 데이터가 있고, 각 x에 대하여 1/0의 데이터가 있습니다. 굳이 쉽게 예를 든다면 x는 공부시간 y는 Pass/Fail로 보면 좀 더 쉽게 이해할 수 있지 않을까 합니다. 원시 데이터는 분석하는데 그렇게 중요하지 않으니까 걱정 마세요.

이 데이터는 df_raw_data라고 부르겠습니다. 

어쨌든 이 데이터로 Logistic 회귀를 하기 위해서 확률과 Logit을 계산해 두겠습니다. Logit은 log(odds)인 $ln \cfrac{P}{1-P}$ 라는 거 다시 한번 상기하면서~

 

이 데이터는 df_raw_data_prob라고 부르겠습니다. 

설명하자면, 각 x에 대하여 y=0인 경우와 y=1의 경우를 세어 보았고, 이때의  1일 확률을 prob에 정리했습니다. odds는 p/1-p 즉 prob/(1-prob)를 계산해 두었고, logit은 ln(p/(1-p))를 계산했습니다. Label은 성공 label을 1, 실패를 0으로 Labeling 해 두었고요. 

자, 이제 $logit(x) = ln\left(\cfrac{p}{1-p}\right) = b_0 + b_1 x$ 를 단순회귀 해 보도록 하겠습니다. 종속변수는 Logit(x)이고요, 독립변수는 x입니다. 

import statsmodels.formula.api as ols

model_ols = smf.ols("logit ~ x", data=df_raw_data_prob).fit()
model_ols.summary()

 

 

호~ 계수들을 구했습니다. 어떤가요? 이 경우에 x의 계수는 0.63입니다. 그러니까 $$ y = Logit(x) = ln\cfrac{P(x)}{1-P(x)} = -1.3 + 0.63x $$ 로 Logit(x)에 대한 단순회귀식을 구할 수 있겠습니다. 결국 로지스틱 회귀식은 $P(x) = \cfrac{1}{1+e^{-(-0.13 + 0.63 x ) }}$이 됩니다. 

그러면 이번에는 Logit 모델을 활용하여 직접 Logistic 회귀를 해 보겠습니다. 이때는 종속변수는 1/0 데이터인 Label이고, 독립변수는 x입니다. 이렇게 데이터를 넣어주면 자동으로 확률을 계산해서 회귀를 해 줍니다. 여기에서 주의할 점은 x에 상수항을 추가해줘야 한다는 점인데, 이것은 이전에 다중회귀에 관련한 "다중회귀 - 결과해석과 손으로 회귀 구해보기, 그리고 R²는 줄어들지 않는다."편에서 행렬로 회귀를 했을 때 보았던 그것인데 Intercept=0이 아닌 회귀식을 구하기 위해서 X의 첫 열에 1을 추가해서 회귀를 해야 합니다. 다시 말해 로지스틱 회귀는 $\cfrac{1}{1+e^{-w^T x}}$ 를 회귀하는 것이고, $w^T$ 에 상수항이 포함되어 있기 때문에 이것을 그대로 만들어 줘야 합니다. 

import statsmodels.api as sm

X = df_raw_data[['x']]
Y = df_raw_data['y']

X = sm.add_constant(X)  # 상수항 추가 → 이게 자동으로 1을 첫열에 넣어줍니다.

model = sm.Logit(Y,X).fit() # 자동으로 종속변수의 확률을 계산하여 회귀를 해 줍니다. 
model.summary()

 

 

호~ 계수들을 구했습니다. 

단순회귀와 로지스틱회귀의 계수를 보면 0.63으로 같군요? 캬~ 한 가지 차이가 있다면 Logit 단순회귀에서는 계수가 유의하였는데, 로지스틱에서는 유의하지 않게 나왔거든요. 결론을 먼저 이야기하자면 로지스틱 회귀에서는 표본수가 너무 작아서 그렇습니다. 이건 혀를 쉽게 놀린다면, 표본을 늘리면 해결될 일입니다. 후후.

이제 계수들을 해석하자면, 이미 데이터를 로그변환했을 때 벌어지는 일 편에서 보았듯이 종속변수인 Odds에 로그를 취한 것과 같다고 해석한다면 독립변수 1 단위가 변할 때 (계수×100)% 변한다고 했으니까, 이 경우에는 공부시간을 x로, Pass/Fail을 y로 두었으니까 공부시간이 1시간 늘 때마다 실패확률에 비해 성공확률이 63% 늘어난다고 해석하면 되겠습니다. 훗.

statsmodels의 OLS를 이용한 회귀는 그 원리를 쉽게 이해할 수 있는 장점이 있습니다만, 실무에서는 sklearn을 이용해서 로지스틱 회귀를 많이 합니다. 이때 나오는 두 회귀결과가 다릅니다. 왜냐하면 statsmodel은 회귀를 그대로 실행하여 설명가능한 모형을 만드는 것이 목적이고, sklearn은 예측모형을 만드는 것이 목적입니다. 그러니까 sklearn의 경우에는 모형의 Overfitting을 방지하기 위해서 특별하게 지시하지 않아도 Regularization을 포함하여 회귀를 하게 되어서 그런 결과가 나옵니다. 그러니까 두 개의 결과가 다르더라도 놀라면 안 됩니다. 

갑자기 난데없이 Overfitting(과적합)을 꺼내 들어서 미안하게 생각합니다. Overfitting은 예측모형을 만들 때 분석모형에서 다중공선성이 분석 결과를 안 좋게 하는 것 처럼 예측성능이 안좋게 하는 것인데, 머지않은 미래에 이어서 이야기할 요량이니까 조금만 참아주세요.

'시그모이드'라는 단어는 그리스어 'σιγμοειδής'(시그모에이데스)에서 유래한 것으로, '시그마(Σ)와 같은 모양'을 뜻하고요, 결국 알파벳으로 따지면 S자형을 의미하겠군요. 그리고, Logistic은 도대체 어디에서 온 거냐 한다면 모양새가 어떤 값으로부터 증가하기 시작하면서 어떤 값으로 S자 모양으로 수렴하잖아요? 이 모양새가 원래 물류성장 수용곡선 뭐 이런 곳 모델링에 사용되었다고 합니다. 거기에서부터 Logistics가 온 것 같은데, 어쨌든 금방 연상되는 관계는 아니라서 처음에 받아들이는데 조금 어려울 수도 있지 않을까 합니다. 

logit은 logistic + probit이라고 한다는데, 그러면 probit은 무엇이냐 하면 Probability + unit을 의미합니다. 이건 또 뭐냐 하는 궁금증이 생길 텐데, probit모형은 Logistic 모형과 마찬가지로 0, 1을 구분하는 모형이거든요. 그런데, 종속변수의 확률 분포가 가우시안 분포를 이루는 경우로써 조금 접근이 다릅니다. 일단은 요기까지만 알아보기로 해요.  

이미 본문에서 이야기하였지만, 나중을 위한 밑밥을 하나 먼저 깔아 둔다면, 이 로지스틱 회귀를 뉴럴넷으로 구현한다면, feed-forward neural network의 Fully connected Layer의 하나의 셀에 활성함수(activation function)로 시그모이드를 쓰면 이항 로지스틱 회귀와 같다는 점을 미리  이야기해 둡니다. 

친절한 데이터 사이언스 강좌 글 전체 목차 (링크) -



댓글





친절한 데이터 사이언스 강좌 글 전체 목차 (링크) -