RyanNerd
라덕'Story
RyanNerd
  • 분류 전체보기 (60) N
    • Study Note (25) N
      • Python (3)
      • R (1)
      • Airflow (7)
      • 통계 (14) N
    • 빅데이터분석기사 (1)
      • 필기 (1)
    • Programmers (28)
      • Python (13)
      • SQL (15)
    • Project (3)
      • Django (3)
    • Mac (2)
    • 맛집 (0)

블로그 메뉴

  • NaverBlog
  • 홈

최근 글

전체 방문자
오늘
어제
hELLO · Designed By 정상우.
RyanNerd

라덕'Story

Study Note/통계

분류 문제의 시작, 로지스틱 회귀(Logistic Regression) 완벽 해부

2025. 12. 16. 16:41

이름은 '회귀(Regression)'지만 사실은 '분류(Classification)' 알고리즘인 로지스틱 회귀. 의료 데이터 분석에서 질병 유무(0/1), 생존 여부(Alive/Dead)를 예측할 때 가장 기본이 되는 모델입니다. 오늘은 그 작동 원리부터 학습 방법, 그리고 실제 코드 구현까지 알아보겠습니다.

 

1. 로지스틱 회귀란 무엇인가?

1) 정의

종속변수($Y$)가 이분법적인 값(0 또는 1)을 가질 때, 특정 사건이 발생할 확률(Probability)을 예측하는 통계 모형입니다.

  • 입력($X$): 나이, 혈압, BMI 등 (연속형 실수 가능)
  • 출력($Y$): 암(1) vs 정상(0), 합격(1) vs 불합격(0)

2) 왜 선형회귀를 쓰지 않을까?

선형회귀($Y = \beta X$)는 결과값이 $-\infty$에서 $+\infty$까지 나올 수 있습니다.

하지만 우리가 원하는 확률은 0과 1 사이여야 합니다. 그래서 선형회귀의 결과를 0~1 사이로 압축해주는 장치가 필요합니다. 이것이 바로 시그모이드 함수(Sigmoid Function)입니다.

 

2. 핵심 원리: 로짓(Logit)과 시그모이드

로지스틱 회귀는 두 단계로 작동합니다.

1단계: 선형 결합 (Logit, $S$)

독립변수들에 가중치($\beta$)를 곱해 더합니다. (선형회귀와 동일)

$$S = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \cdots + \beta_k X_k$$

2단계: 확률 변환 (Sigmoid)

$S$값을 시그모이드 함수에 넣어 0과 1 사이의 확률값($P$)으로 바꿉니다.

$$P(Y=1|X) = \frac{1}{1 + e^{-S}}$$
  • $S$가 매우 크면 $\rightarrow$ $P$는 1에 수렴.
  • $S$가 매우 작으면 $\rightarrow$ $P$는 0에 수렴.
  • $S=0$ 이면 $\rightarrow$ $P=0.5$ (판단의 경계선).

3. 학습 방법: 어떻게 최적의 선을 찾나?

선형회귀는 오차 제곱 합(OLS)을 최소화했지만, 로지스틱 회귀는 로그 우도(Log-Likelihood)를 최대화(또는 손실함수 $L$을 최소화)하는 방식을 씁니다.

경사 하강법 (Gradient Descent)

복잡한 미분 계산을 컴퓨터가 효율적으로 하기 위해 사용하는 알고리즘입니다.

  1. 임의의 $\beta$값에서 시작.
  2. 손실함수의 기울기(Gradient, $\nabla L$)를 계산.
  3. 기울기가 낮은 방향으로 조금씩($\eta$, Learning Rate) 이동.
  4. 최적의 값(기울기가 0인 지점)에 도달할 때까지 반복.

4. [실습] 심장병 발병 예측 (Python & R)

시나리오: 나이(Age)와 콜레스테롤 수치(Chol)를 이용해 심장병 유무(Target: 1=발병, 0=정상)를 예측해 봅시다.

 

Python (sklearn)

import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix

# 1. 가상 데이터 생성
np.random.seed(42)
n = 100
age = np.random.randint(30, 70, n)
chol = np.random.randint(150, 300, n)
# 나이와 콜레스테롤이 높으면 발병 확률 증가하도록 설정
logit = -10 + 0.1 * age + 0.02 * chol + np.random.normal(0, 1, n)
target = (1 / (1 + np.exp(-logit)) > 0.5).astype(int)

df = pd.DataFrame({'Age': age, 'Chol': chol, 'HeartDisease': target})

# 2. 데이터 분할
X = df[['Age', 'Chol']]
y = df['HeartDisease']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 3. 로지스틱 회귀 학습
model = LogisticRegression()
model.fit(X_train, y_train)

# 4. 예측 및 평가
y_pred = model.predict(X_test)
print("정확도(Accuracy):", accuracy_score(y_test, y_pred))
print("회귀계수(Coefficients):", model.coef_) # [나이 계수, 콜레스테롤 계수]
print("오즈비(Odds Ratio):", np.exp(model.coef_)) # 계수에 exp를 취하면 오즈비가 됨

 

R Code (glm)

# 1. 데이터 생성
set.seed(42)
n <- 100
age <- sample(30:70, n, replace=TRUE)
chol <- sample(150:300, n, replace=TRUE)
logit <- -10 + 0.1 * age + 0.02 * chol + rnorm(n)
prob <- 1 / (1 + exp(-logit))
heart_disease <- ifelse(prob > 0.5, 1, 0)

df <- data.frame(age, chol, heart_disease)

# 2. 로지스틱 회귀 학습 (GLM 사용, family=binomial)
model <- glm(heart_disease ~ age + chol, data = df, family = binomial)

# 3. 결과 요약
summary(model)

# 4. 오즈비(Odds Ratio) 확인
# 의료 통계에서는 계수보다 오즈비를 더 중요하게 봅니다.
exp(coef(model))

 

 

5. 의료 데이터 분석가의 핵심 Insight: 오즈비(Odds Ratio) 해석

로지스틱 회귀분석 결과표에서 Estimate(회귀계수)가 양수(+)로 나왔다는 것은 해당 변수가 증가할수록 질병 위험이 커진다는 뜻입니다. 하지만 "그래서 얼마나 더 위험한데?" 라는 질문에 답하려면 오즈비(Odds Ratio)를 봐야 합니다.

R에서 exp(coef(model)) 명령어로 구한 결과를 실제 의료 현장의 언어로 번역해 보겠습니다.

분석 결과 해석

1. 나이 (Age): 오즈비 1.364

  • 수학적 의미: $e^{0.31047} \approx 1.364$
  • 임상적 해석: "다른 조건이 같다면, 나이가 1살 증가할 때마다 심장병에 걸릴 위험(Odds)은 약 1.36배 (36.4%) 증가합니다."
  • 신뢰도: P-value가 $9.40 \times 10^{-6}$ ($<0.001$)이므로 통계적으로 매우 확실합니다.

2. 콜레스테롤 (Chol): 오즈비 1.059

  • 수학적 의미: $e^{0.05751} \approx 1.059$
  • 임상적 해석: "다른 조건이 같다면, 콜레스테롤 수치가 1 단위 증가할 때마다 심장병 발병 위험은 약 1.06배 (5.9%) 증가합니다."
  • 신뢰도: P-value가 $7.57 \times 10^{-5}$ ($<0.001$)이므로 역시 매우 중요한 위험 인자입니다.

Tip: 보고할 때는 "회귀계수가 0.31입니다"라고 하기보다, "나이가 한 살 늘면 발병 확률이 1.36배 높아집니다(오즈비)"라고 설명하는 것이 훨씬 직관적이고 설득력이 높습니다.

 

요약 (Summary)

  1. 로지스틱 회귀: 질병 유무(0/1)나 생존 여부 같은 이진 분류(Binary Classification) 문제를 풀 때 사용하는 확률 예측 모델입니다.
  2. 시그모이드 함수: 선형회귀의 결과($-\infty \sim \infty$)를 확률의 범위인 0과 1 사이로 압축해 주는 핵심 장치입니다.
  3. 학습 원리: 오차 제곱 합(OLS)이 아닌, 정답을 맞힐 확률(로그 우도)을 최대화하는 방향으로 학습합니다.
  4. 결과 활용: 회귀계수($\beta$)에 지수($exp$)를 취해 오즈비(Odds Ratio)로 변환하여, "위험도가 몇 배 증가하는가?"를 설명하는 것이 의료 통계의 표준입니다.

'Study Note > 통계' 카테고리의 다른 글

정확도(Accuracy)의 함정: 민감도, 특이도, 그리고 베이즈 정리  (0) 2025.12.17
숫자를 센다? 무조건 '푸아송 회귀'입니다. (feat. 의료 데이터 활용법)  (0) 2025.12.15
직선을 넘어 곡선으로, 그리고 모델의 성적표 AIC  (0) 2025.12.15
회귀분석의 확장: 과적합 방지와 데이터 특성에 맞는 모델링  (0) 2025.12.15
회귀모형의 진단: 잔차, 레버리지, 그리고 쿡의 거리  (0) 2025.12.15
    'Study Note/통계' 카테고리의 다른 글
    • 정확도(Accuracy)의 함정: 민감도, 특이도, 그리고 베이즈 정리
    • 숫자를 센다? 무조건 '푸아송 회귀'입니다. (feat. 의료 데이터 활용법)
    • 직선을 넘어 곡선으로, 그리고 모델의 성적표 AIC
    • 회귀분석의 확장: 과적합 방지와 데이터 특성에 맞는 모델링
    RyanNerd
    RyanNerd
    라이언 덕후의 일상 스토리~

    티스토리툴바