ML Insights/Build ML From Scratch

로지스틱 회귀 + L1 규제로 중요한 변수만 골라내기!

Data Jun 2025. 3. 28. 10:03

머신러닝에서 모델 성능도 중요하지만, 어떤 변수가 중요한지 해석할 수 있는 능력도 매우 중요하다.
특히 금융, 의료처럼 설명력이 필요한 분야에선 더욱 그렇다.

이번 글에선 로지스틱 회귀 + L1(Lasso) 규제를 활용해서 유의미한 변수만 선택하는 과정을 소개한다.

 

목표

select_features_by_logistic_lasso(df, '채무 불이행 여부')
 -> 이 함수는 데이터프레임 df에서 채무 불이행 여부를 타겟으로,
중요한 변수만 골라내고 학습된 로지스틱 회귀 모델까지 반환한다!

 

주요 단계 설명

파이프라인 구성

clf = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('classifier', LogisticRegression(
        penalty='l1',
        solver='liblinear',
        C=C,
        random_state=random_state))
])

 

  • preprocessor: 앞서 구성한 수치형 + 범주형 전처리기
  • classifier: L1 규제를 사용하는 로지스틱 회귀
    • penalty='l1': L1 규제 (Lasso)
    • solver='liblinear': L1을 지원하는 최적화 알고리즘
    • C: 규제의 강도 (작을수록 규제가 강함)

 

모델 학습

clf.fit(X, y)

 

전체 파이프라인을 통해 전처리 + 학습을 한 번에 진행

 

전처리된 피처 이름 얻기

encoded_feature_names = clf.named_steps['preprocessor'].get_feature_names_out()

범주형 변수는 OneHotEncoder를 거쳐 여러 개의 피처로 바뀌기 때문에, 전처리 후 실제 피처 이름을 정확히 알아야 해!

c lf.named_steps['preprocessor']는 어떤 의미일까?

파이프라인을 구성하고 나면, 아래와 같은 코드가 종종 등장한다:

clf.named_steps['preprocessor'].get_feature_names_out()

처음 보면 "named_steps?", "이건 뭐 하는 거지?" 싶은데, 알고 보면 굉장히 유용한 속성이다!

 

named_steps란?

Pipeline 객체 내부에는 여러 단계(step)가 순서대로 저장되어 있다.
이 각각의 단계를 우리가 이름 붙여 등록했었지:

clf = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('classifier', LogisticRegression(...))
])

여기서 'preprocessor'와 'classifier'는 우리가 지정한 **이름(name)** 그래서 clf.named_steps['preprocessor']는 말 그대로 파이프라인에서 'preprocessor'라는 이름으로 등록된 객체를 가져와라! 즉, 전체 파이프라인 중에서 전처리 파트만 꺼내오는 코드인 거지.

 

그 다음 .get_feature_names_out()는?

전처리기 내부에 있는 인코더나 변환기(예: OneHotEncoder, ColumnTransformer)는
전처리 이후 만들어진 실제 feature 이름들을 .get_feature_names_out()을 통해 알려줘.

예: 범주형 컬럼 'gender'가 인코딩되어 'gender_Male', 'gender_Female'처럼 바뀌었을 때
-> 전처리기만이 그 이름을 정확히 알고 있음!

 

그래서 전체 의미는?

clf.named_steps['preprocessor'].get_feature_names_out()

전체 파이프라인(clf)에서 전처리기(preprocessor)만 꺼내서, 전처리 후 피처 이름을 받아온다.

 

요약 정리

 

회귀 계수에서 중요 변수만 추출

coefs = clf.named_steps['classifier'].coef_[0]

selected_features = [
    feature for coef, feature in zip(coefs, encoded_feature_names)
    if coef != 0
]

 

  • L1 규제의 특징은 불필요한 변수의 계수를 0으로 만듦
  • 따라서 계수가 0이 아닌 변수만 선택하면, 모델이 중요하게 본 변수만 남는다!

 

최종 반환값

return selected_features, clf.named_steps['classifier']

 

 

 

왜 L1(Lasso)을 쓰는 걸까?

L1은 변수 선택 기능이 내장된 셈!

 

요약

  • Pipeline으로 전처리 + 모델 학습을 묶는다
  • LogisticRegression에 L1 규제를 주면 불필요한 변수는 제거됨
  • 최종적으로 중요한 변수만 뽑아내는 자동 변수 선택 기능이 된다!