본문 바로가기
Data Visualization/Python Lib

[Statsmodels] 로지스틱 회귀분석, 칼럼별 오즈비(odds ratio) 구하는 방법

by jangThang 2025. 6. 8.
반응형

 statsmodels를 활용하여 로지스틱 회귀분석 하는 방법을 알아봅니다.

 

[ Contents ]

     

     

    1. 로지스틱 회귀 (Logistic Regression)

     로지스틱 회귀변수는 이진 분류 학습에 주로 사용됩니다. True와 False로 나뉘는 boolean 값을 예측합니다.

     예를 들어 스팸메일 여부, 질병 여부 등을 판별합니다. 범주가 여러 개인 분류학습에는 적합하지 않습니다. 물론 로지스틱을 확장해서 A 클래스 여부, B 클래스 여부, C 클래스 여부 ... 등으로 나눠서 각각 진행 후 앙상블 모델처럼 평가할 수도 있겠지만 잘 사용하진 않습니다.

     아래에서 실제 데이터를 가지고 알아보겠습니다.

     

     

    2. 적용 예시

    import pandas as pd
    
    # 1. 데이터 생성
    data = pd.DataFrame({
        'num_words': [100, 50, 300, 200, 400, 80, 120, 500, 50, 30],
        'num_links': [5, 1, 10, 7, 15, 1, 2, 20, 0, 0],
        'has_offer': [1, 0, 1, 1, 1, 0, 0, 1, 0, 0],  # 특정 단어("offer") 포함 여부
        'is_spam': [1, 0, 1, 1, 1, 0, 0, 1, 0, 0]
    })

     

     임의로 생성한 데이터로, 단어와 링크 개수 그리고 offer 단어 여부에 따라 스팸여부를 로지스틱 회귀분석 해보도록 하겠습니다.

     

    반응형

     

    import statsmodels.api as sm
    
    # 2. 독립변수(X)와 종속변수(y) 설정
    X = data[['num_words', 'num_links', 'has_offer']]
    X = sm.add_constant(X)  # 절편항 추가
    y = data['is_spam']

     

     예측해야할 종속변수 is_spam과, 예측에 필요한 독립변수 num_words, num_links, has_offer를 분리합니다.

     그리고 독립변수에는 add_constant(X)로 상수항[절편]을 추가해줍니다.

     

     

    # 로지스틱 회귀 모델 정의 및 학습
    model = sm.Logit(y, X)
    result = model.fit()

     

     sm.Logit(y, X)로 회귀모델을 정의하고, fit으로 로지스틱 회귀학습을 해줍니다.

     

     

    # 결과 요약
    print(result.summary())

     

     로지스틱 회귀분석 결과, 데이터가 10개로 너무 적어서 0.05 유의 수준 내에 머물지 못 했습니다.

     거기다가 has_offer 변수가 1인 경우에는 무조건 스팸 데이터라서 overfitting 과적합되었죠. 

     

     

    3. 오즈비(odds ratio)

     오즈(odds)는 일어날 확률 : 안 일어날 확률의 비를 뜻하며, 수식은 위와 같습니다.

     오즈가 클수록 일어날 확률이 커지죠. 위 예시에서는 스팸확률일 확률이 커집니다.

     예를 들어 P = 0.8이면, odds = 4로 스팸일 확률이 4배 높습니다.

     

     

     오즈비(odds ratio)는 두 오즈 간의 비율을 비교한 값입니다. 

     두 집단 간의 오즈 차이를 통해, 어느 종속변수가 더 영향력이 큰지 알아볼 수 있죠.

     

     

     로지스틱 회귀의 기본 식은 위와 같고, 여기서 오즈를 구하려면 양변에 지수함수만 씌워주면 됩니다.

     

    그래서 로지스틱 회귀에서 오즈비는 각 독립변수 계수값을 지수함수 exp()로 덮어씌운 값입니다.

     

     

    import numpy as np
    
    odds = np.exp(result.params)

     오즈비만 보면 has_offer 변수가 가장 영향력이 크네요. 그 다음은 링크 개수입니다.

     메일에 offer라는 단어가 있으면 스팸일 확률이 9.7배나 높아진다는 거죠..

     

     


    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import classification_report
    import pandas as pd
    
    # 데이터
    data = pd.DataFrame({
        'num_words': [100, 50, 300, 200, 400, 80, 120, 500, 50, 30, 250, 270],
        'num_links': [5, 1, 10, 7, 15, 1, 2, 20, 0, 0, 3, 5],
        'has_offer': [1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0],
        'is_spam':    [1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1]
    })
    
    # 분할
    X = data[['num_words', 'num_links', 'has_offer']]
    y = data['is_spam']
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
    
    # 모델 훈련
    model = LogisticRegression()
    model.fit(X_train, y_train)
    
    # 예측 및 결과
    y_pred = model.predict(X_test)
    print(classification_report(y_test, y_pred))
    print("모델 계수:", model.coef_)
    print("절편:", model.intercept_)

     

     추가로 sklearn 패키지에 있는 LogisticRegression으로도 해봤습니다.

     물론 여기도 데이터가 적기 때문에 이 점은 감안하고, 로지스틱 회귀분석 개념이나 코드 사용법을 중점적으로 봐주시기 바랍니다.

     

    star가 되고나서 Tistory

     

    반응형

    댓글