🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Ridge, Lasso 정규화 회귀 완벽 가이드 - 슬라이드 1/8
A

AI Generated

2025. 12. 6. · 14 Views

Ridge, Lasso 정규화 회귀 완벽 가이드

머신러닝 모델의 과적합을 방지하는 정규화 기법인 Ridge와 Lasso 회귀를 알아봅니다. 두 기법의 차이점과 실무 적용 방법을 초보자도 쉽게 이해할 수 있도록 설명합니다.


목차

  1. 과적합과_정규화의_필요성
  2. Ridge_회귀의_원리
  3. Lasso_회귀의_원리
  4. Ridge와_Lasso_비교
  5. ElasticNet_두_기법의_결합
  6. 교차_검증으로_최적_파라미터_찾기
  7. 실무_프로젝트_적용_예제

1. 과적합과 정규화의 필요성

김개발 씨는 회사에서 처음으로 머신러닝 프로젝트를 맡았습니다. 학습 데이터로 모델을 만들었더니 정확도가 무려 99%였습니다.

그런데 실제 데이터를 넣어보니 정확도가 60%로 뚝 떨어졌습니다. 대체 무슨 일이 일어난 걸까요?

**과적합(Overfitting)**은 모델이 학습 데이터에만 지나치게 최적화되어 새로운 데이터에는 제대로 동작하지 않는 현상입니다. 마치 시험 문제를 달달 외워서 그 문제만 풀 수 있고, 조금만 바뀌면 못 푸는 학생과 같습니다.

**정규화(Regularization)**는 이런 과적합을 방지하기 위해 모델의 복잡도에 페널티를 부여하는 기법입니다.

다음 코드를 살펴봅시다.

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# 샘플 데이터 생성
np.random.seed(42)
X = np.random.randn(100, 10)  # 10개의 특성
y = X[:, 0] * 3 + X[:, 1] * 2 + np.random.randn(100) * 0.5

# 학습/테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# 기본 선형 회귀 모델
model = LinearRegression()
model.fit(X_train, y_train)

# 학습 점수와 테스트 점수 비교
print(f"학습 점수: {model.score(X_train, y_train):.4f}")
print(f"테스트 점수: {model.score(X_test, y_test):.4f}")

김개발 씨는 입사 6개월 차 데이터 분석가입니다. 첫 번째 머신러닝 프로젝트에서 주택 가격 예측 모델을 만들었는데, 학습할 때는 완벽하게 작동하던 모델이 실제 서비스에서는 엉망이었습니다.

선배 박시니어 씨가 김개발 씨의 모델을 살펴보며 말했습니다. "이건 전형적인 과적합이에요.

모델이 학습 데이터를 외워버린 거죠." 과적합이란 정확히 무엇일까요? 쉽게 비유하자면, 과적합은 마치 수학 시험을 준비하면서 기출문제의 답만 달달 외운 학생과 같습니다.

그 학생은 기출문제가 그대로 나오면 100점을 맞지만, 숫자 하나만 바뀌어도 문제를 풀지 못합니다. 제대로 공부한 학생은 어떤 문제가 나와도 개념을 적용해서 풀 수 있습니다.

머신러닝 모델도 마찬가지입니다. 과적합은 왜 일어날까요?

가장 흔한 원인은 모델이 너무 복잡한 경우입니다. 특성(feature)의 수가 데이터 수에 비해 너무 많거나, 모델이 데이터의 노이즈까지 학습해버릴 때 과적합이 발생합니다.

학습 데이터에 있는 우연한 패턴까지 의미 있는 규칙으로 받아들이는 것입니다. 반대로 **과소적합(Underfitting)**이라는 문제도 있습니다.

이것은 모델이 너무 단순해서 데이터의 패턴조차 제대로 학습하지 못하는 경우입니다. 적절한 균형을 찾는 것이 중요합니다.

바로 이 문제를 해결하기 위해 정규화가 등장했습니다. 정규화는 모델의 복잡도에 페널티를 부여하는 방식으로 작동합니다.

쉽게 말해, 모델에게 "너무 복잡하게 학습하면 벌점을 줄 거야"라고 경고하는 것입니다. 이렇게 하면 모델은 정말 중요한 패턴만 학습하고, 불필요한 노이즈는 무시하게 됩니다.

위의 코드에서 학습 점수와 테스트 점수의 차이를 확인해보세요. 두 점수의 차이가 크다면 과적합이 의심됩니다.

학습 점수는 높은데 테스트 점수가 낮다면, 모델이 학습 데이터에만 맞춰져 있다는 뜻입니다. 실무에서는 어떻게 활용할까요?

금융 회사에서 대출 심사 모델을 만든다고 가정해봅시다. 과적합된 모델은 과거 고객 데이터에는 잘 맞지만, 새로운 고객에게는 엉뚱한 판단을 내릴 수 있습니다.

잘못된 대출 승인이나 거절은 회사에 큰 손실을 가져옵니다. 박시니어 씨가 김개발 씨에게 조언했습니다.

"정규화를 적용해보세요. Ridge나 Lasso 회귀를 사용하면 훨씬 안정적인 모델을 만들 수 있어요." 김개발 씨는 고개를 끄덕였습니다.

이제 본격적으로 정규화 기법을 배워볼 차례입니다.

실전 팁

💡 - 학습 점수와 테스트 점수의 차이가 10% 이상이면 과적합을 의심해보세요

  • 데이터가 적거나 특성이 많을수록 과적합 위험이 높아집니다

2. Ridge 회귀의 원리

김개발 씨는 정규화를 적용하기로 결심했습니다. 검색해보니 Ridge 회귀라는 것이 가장 먼저 나왔습니다.

선배에게 물어보니 "L2 정규화라고도 하는데, 가장 기본적이고 안정적인 방법이야"라고 알려주었습니다.

Ridge 회귀는 일반 선형 회귀에 L2 페널티를 추가한 기법입니다. 모든 가중치(계수)를 0에 가깝게 축소하지만, 완전히 0으로 만들지는 않습니다.

마치 모든 팀원에게 업무를 조금씩 나눠주되, 아무도 완전히 쉬게 하지 않는 팀장과 같습니다. 모든 특성을 유지하면서 각각의 영향력을 줄이는 방식입니다.

다음 코드를 살펴봅시다.

from sklearn.linear_model import Ridge
import numpy as np

# Ridge 회귀 모델 생성
# alpha는 정규화 강도 (클수록 강한 정규화)
ridge_model = Ridge(alpha=1.0)
ridge_model.fit(X_train, y_train)

# 성능 평가
print(f"Ridge 학습 점수: {ridge_model.score(X_train, y_train):.4f}")
print(f"Ridge 테스트 점수: {ridge_model.score(X_test, y_test):.4f}")

# 계수 확인 - 모든 계수가 0이 아닌 값을 가짐
print(f"\n계수 값들: {ridge_model.coef_.round(4)}")
print(f"0이 아닌 계수 개수: {np.sum(ridge_model.coef_ != 0)}")

김개발 씨는 Ridge 회귀의 수학적 원리가 궁금해졌습니다. 박시니어 씨가 화이트보드에 그림을 그리며 설명을 시작했습니다.

일반 선형 회귀는 예측값과 실제값의 차이, 즉 오차의 제곱합을 최소화합니다. 수식으로 표현하면 손실 함수가 됩니다.

Ridge 회귀는 여기에 한 가지를 더합니다. 바로 계수의 제곱합입니다.

쉽게 비유하자면, Ridge 회귀는 마치 예산 관리를 하는 것과 같습니다. 프로젝트 팀장이 예산을 배분할 때, 각 부서에 너무 많은 예산을 주지 않으려고 합니다.

총 예산은 정해져 있으니, 각 부서의 예산을 조금씩 줄여서 균형을 맞춥니다. Ridge 회귀도 각 특성의 가중치를 조금씩 줄여서 전체적인 균형을 맞춥니다.

핵심은 alpha 파라미터입니다. alpha는 정규화의 강도를 결정합니다.

alpha가 0이면 일반 선형 회귀와 같습니다. alpha가 커질수록 정규화가 강해지고, 모든 계수가 0에 가까워집니다.

너무 크면 과소적합이 발생하고, 너무 작으면 과적합을 막지 못합니다. 코드를 자세히 살펴보겠습니다.

Ridge 클래스를 임포트하고, alpha=1.0으로 모델을 생성합니다. 이 값은 기본값이며, 대부분의 경우 좋은 시작점이 됩니다.

fit 메서드로 학습하고, score 메서드로 성능을 평가합니다. 중요한 것은 계수를 확인하는 부분입니다.

Ridge 회귀의 특징은 모든 계수가 0이 아닌 값을 가진다는 것입니다. 계수가 작아질 수는 있지만, 완전히 0이 되지는 않습니다.

이것이 Lasso와의 핵심적인 차이점입니다. 언제 Ridge 회귀를 사용할까요?

모든 특성이 어느 정도 중요하다고 생각될 때 Ridge가 적합합니다. 예를 들어, 주택 가격 예측에서 면적, 방 개수, 위치, 연식 등 모든 요소가 가격에 영향을 미친다면 Ridge를 사용하는 것이 좋습니다.

어떤 특성도 완전히 무시하지 않으면서, 각각의 영향력을 적절히 조절합니다. 또한 다중공선성 문제가 있을 때도 Ridge가 효과적입니다.

다중공선성은 특성들 사이에 높은 상관관계가 있을 때 발생하는 문제입니다. 일반 선형 회귀는 이런 경우 불안정한 계수를 만들지만, Ridge는 안정적인 결과를 제공합니다.

김개발 씨가 물었습니다. "그런데 alpha 값은 어떻게 정하나요?" 박시니어 씨가 대답했습니다.

"좋은 질문이에요. 보통 교차 검증을 사용해서 최적의 alpha를 찾습니다.

sklearn에는 RidgeCV라는 편리한 클래스가 있어요."

실전 팁

💡 - alpha 값은 0.001부터 1000까지 로그 스케일로 탐색해보세요

  • 다중공선성이 의심되면 Ridge부터 시도하는 것이 좋습니다

3. Lasso 회귀의 원리

Ridge 회귀를 적용한 김개발 씨는 모델 성능이 개선되는 것을 확인했습니다. 그런데 특성이 100개나 되다 보니, 어떤 특성이 정말 중요한지 파악하기 어려웠습니다.

박시니어 씨가 말했습니다. "그럴 때는 Lasso를 써보세요.

불필요한 특성을 알아서 걸러줄 거예요."

Lasso 회귀L1 페널티를 사용하는 정규화 기법입니다. Ridge와 달리 일부 계수를 완전히 0으로 만들 수 있습니다.

마치 팀장이 정말 필요한 인원만 남기고 나머지는 다른 프로젝트로 보내는 것과 같습니다. 이 특성 덕분에 Lasso는 특성 선택(Feature Selection) 효과가 있습니다.

다음 코드를 살펴봅시다.

from sklearn.linear_model import Lasso
import numpy as np

# Lasso 회귀 모델 생성
lasso_model = Lasso(alpha=0.1)
lasso_model.fit(X_train, y_train)

# 성능 평가
print(f"Lasso 학습 점수: {lasso_model.score(X_train, y_train):.4f}")
print(f"Lasso 테스트 점수: {lasso_model.score(X_test, y_test):.4f}")

# 계수 확인 - 일부 계수가 정확히 0이 됨
print(f"\n계수 값들: {lasso_model.coef_.round(4)}")
print(f"0이 아닌 계수 개수: {np.sum(lasso_model.coef_ != 0)}")
print(f"선택된 특성 인덱스: {np.where(lasso_model.coef_ != 0)[0]}")

김개발 씨는 Lasso라는 이름이 궁금했습니다. 박시니어 씨가 설명했습니다.

"Lasso는 Least Absolute Shrinkage and Selection Operator의 약자예요. 이름에서 알 수 있듯이 계수를 축소하고 선택하는 역할을 합니다." Lasso와 Ridge의 결정적인 차이는 페널티 계산 방식에 있습니다.

Ridge는 계수의 제곱을 더하지만, Lasso는 계수의 절댓값을 더합니다. 이 작은 차이가 완전히 다른 결과를 만들어냅니다.

수학적으로 L1 노름을 사용하면 최적화 과정에서 일부 계수가 정확히 0이 될 수 있습니다. 비유로 설명하면 이렇습니다.

Ridge는 마치 모든 직원의 급여를 조금씩 깎는 것과 같습니다. 아무도 해고되지 않지만, 모두의 급여가 줄어듭니다.

반면 Lasso는 일부 직원을 해고하고, 남은 직원에게 업무를 집중시킵니다. 어떤 방식이 좋은지는 상황에 따라 다릅니다.

코드를 살펴보면 Ridge와 거의 비슷합니다. Lasso 클래스를 사용하고, alpha로 정규화 강도를 조절합니다.

핵심적인 차이는 결과에서 나타납니다. 계수를 출력해보면 일부가 정확히 0.0000으로 나옵니다.

이 특성들은 모델에서 완전히 제외된 것입니다. 왜 특성 선택이 중요할까요?

특성이 너무 많으면 여러 문제가 생깁니다. 계산 시간이 오래 걸리고, 모델 해석이 어려워지며, 과적합 위험도 높아집니다.

Lasso는 이런 문제를 자동으로 해결해줍니다. 정말 중요한 특성만 남기고 나머지는 제거하니까요.

실무에서 Lasso가 특히 유용한 경우가 있습니다. 유전자 데이터 분석을 예로 들어봅시다.

수만 개의 유전자 중에서 특정 질병과 관련된 유전자를 찾아야 합니다. 모든 유전자가 중요한 것은 아닙니다.

Lasso를 사용하면 관련 있는 유전자만 자동으로 선택됩니다. 이것을 **희소성(Sparsity)**이라고 합니다.

주의할 점도 있습니다. Lasso는 상관관계가 높은 특성들 중에서 하나만 선택하는 경향이 있습니다.

예를 들어, 키와 몸무게는 높은 상관관계가 있는데, Lasso는 둘 중 하나만 선택할 수 있습니다. 이런 경우에는 Ridge가 더 안정적인 결과를 줄 수 있습니다.

김개발 씨가 결과를 보며 말했습니다. "10개 특성 중에서 2개만 선택됐네요.

이 2개가 정말 중요한 특성이군요!"

실전 팁

💡 - Lasso의 alpha는 Ridge보다 작은 값부터 시작하세요. 너무 크면 모든 계수가 0이 됩니다

  • 특성 선택이 목적이라면 Lasso를, 예측 성능이 목적이라면 Ridge를 먼저 시도해보세요

4. Ridge와 Lasso 비교

김개발 씨는 이제 Ridge와 Lasso를 둘 다 사용할 수 있게 되었습니다. 그런데 언제 어떤 것을 써야 할지 헷갈렸습니다.

"둘 다 정규화인데, 어떤 상황에 뭘 써야 하나요?" 박시니어 씨가 두 기법을 나란히 비교해주기로 했습니다.

Ridge와 Lasso는 모두 정규화 기법이지만, 핵심적인 차이가 있습니다. Ridge는 모든 특성을 유지하면서 계수를 축소하고, Lasso는 일부 특성을 제거합니다.

데이터의 특성과 분석 목적에 따라 적절한 방법을 선택해야 합니다. 두 기법의 장단점을 알면 상황에 맞는 선택을 할 수 있습니다.

다음 코드를 살펴봅시다.

from sklearn.linear_model import Ridge, Lasso
import numpy as np

# 동일한 alpha로 비교
alpha = 0.5

# Ridge 모델
ridge = Ridge(alpha=alpha)
ridge.fit(X_train, y_train)

# Lasso 모델
lasso = Lasso(alpha=alpha)
lasso.fit(X_train, y_train)

# 성능 비교
print("=== 성능 비교 ===")
print(f"Ridge 테스트 점수: {ridge.score(X_test, y_test):.4f}")
print(f"Lasso 테스트 점수: {lasso.score(X_test, y_test):.4f}")

# 계수 비교
print("\n=== 계수 비교 ===")
print(f"Ridge 0이 아닌 계수: {np.sum(ridge.coef_ != 0)}")
print(f"Lasso 0이 아닌 계수: {np.sum(lasso.coef_ != 0)}")

박시니어 씨가 화이트보드에 표를 그리기 시작했습니다. "둘의 차이를 정리해볼게요." 먼저 페널티 방식의 차이입니다.

Ridge는 L2 페널티, 즉 계수의 제곱합을 사용합니다. 수학적으로 이것은 모든 계수를 조금씩 줄이는 효과가 있습니다.

Lasso는 L1 페널티, 즉 계수의 절댓값 합을 사용합니다. 이 방식은 일부 계수를 완전히 0으로 만들 수 있습니다.

다음은 특성 선택 관점입니다. Ridge는 특성 선택을 하지 않습니다.

모든 특성이 모델에 남아 있습니다. 다만 중요하지 않은 특성의 계수가 매우 작아질 뿐입니다.

Lasso는 자동으로 특성을 선택합니다. 불필요한 특성의 계수가 정확히 0이 되어 모델에서 제외됩니다.

해석 가능성 측면에서도 차이가 있습니다. 모델을 해석해야 하는 상황을 생각해봅시다.

Ridge 모델은 100개의 특성이 모두 남아 있어서 어떤 특성이 중요한지 파악하기 어렵습니다. Lasso 모델은 10개의 특성만 남아 있다면, 이 10개가 핵심이라는 것을 바로 알 수 있습니다.

다중공선성 처리 방식도 다릅니다. 다중공선성은 특성들 사이에 높은 상관관계가 있는 경우입니다.

예를 들어 온도를 섭씨와 화씨로 둘 다 포함시킨 경우입니다. Ridge는 이런 상황에서도 안정적으로 작동합니다.

두 특성의 계수를 적절히 분배합니다. Lasso는 둘 중 하나만 선택하는 경향이 있어서, 어떤 특성이 선택될지 예측하기 어렵습니다.

그렇다면 언제 무엇을 선택해야 할까요? Ridge를 선택하는 경우는 다음과 같습니다.

모든 특성이 어느 정도 관련이 있다고 생각될 때, 다중공선성이 있을 때, 예측 성능이 가장 중요할 때 Ridge가 적합합니다. Lasso를 선택하는 경우는 이렇습니다.

많은 특성 중 일부만 중요하다고 생각될 때, 모델 해석이 중요할 때, 특성의 수를 줄이고 싶을 때 Lasso가 좋습니다. 위 코드에서 동일한 alpha 값으로 두 모델을 비교했습니다.

결과를 보면 Ridge는 10개 특성이 모두 남아 있고, Lasso는 일부만 남아 있습니다. 테스트 점수도 비교해보면 어떤 방법이 이 데이터에 더 적합한지 알 수 있습니다.

김개발 씨가 정리했습니다. "결국 둘 다 해보고 비교하는 게 좋겠네요!" 박시니어 씨가 고개를 끄덕였습니다.

"맞아요. 실무에서는 두 방법을 모두 시도해보고, 교차 검증으로 최적의 모델을 선택합니다."

실전 팁

💡 - 확실하지 않다면 둘 다 시도해보고 교차 검증 점수를 비교하세요

  • 특성 수가 매우 많다면 Lasso로 먼저 특성을 줄인 후 Ridge를 적용하는 것도 방법입니다

5. ElasticNet 두 기법의 결합

김개발 씨가 물었습니다. "Ridge와 Lasso 둘 다 장점이 있는데, 두 개를 합칠 수는 없나요?" 박시니어 씨가 웃으며 대답했습니다.

"좋은 생각이에요. 실제로 그런 방법이 있어요.

ElasticNet이라고 합니다."

ElasticNet은 Ridge의 L2 페널티와 Lasso의 L1 페널티를 결합한 기법입니다. 두 정규화의 장점을 모두 취할 수 있습니다.

L1 비율을 조절하여 Lasso에 가깝게 또는 Ridge에 가깝게 만들 수 있습니다. 특히 상관관계가 높은 특성들이 있을 때 Lasso보다 안정적인 특성 선택이 가능합니다.

다음 코드를 살펴봅시다.

from sklearn.linear_model import ElasticNet
import numpy as np

# ElasticNet 모델 생성
# l1_ratio: L1 페널티의 비율 (0=Ridge, 1=Lasso)
elastic = ElasticNet(alpha=0.1, l1_ratio=0.5)
elastic.fit(X_train, y_train)

# 성능 평가
print(f"ElasticNet 학습 점수: {elastic.score(X_train, y_train):.4f}")
print(f"ElasticNet 테스트 점수: {elastic.score(X_test, y_test):.4f}")

# 계수 확인
print(f"\n계수 값들: {elastic.coef_.round(4)}")
print(f"0이 아닌 계수 개수: {np.sum(elastic.coef_ != 0)}")

# l1_ratio에 따른 변화 확인
for ratio in [0.1, 0.5, 0.9]:
    model = ElasticNet(alpha=0.1, l1_ratio=ratio)
    model.fit(X_train, y_train)
    non_zero = np.sum(model.coef_ != 0)
    print(f"l1_ratio={ratio}: 0이 아닌 계수 {non_zero}개")

김개발 씨는 ElasticNet이라는 이름에서 탄성(Elastic)의 의미가 궁금해졌습니다. 박시니어 씨가 설명했습니다.

"탄성이 있는 그물(Net)처럼 유연하게 두 방식 사이를 오갈 수 있다는 의미예요." ElasticNet의 핵심은 두 가지 파라미터입니다. 첫 번째는 alpha로, 전체 정규화의 강도를 결정합니다.

Ridge나 Lasso와 마찬가지로 클수록 강한 정규화가 적용됩니다. 두 번째는 l1_ratio로, L1 페널티와 L2 페널티의 비율을 결정합니다.

이 값이 0이면 순수 Ridge가 되고, 1이면 순수 Lasso가 됩니다. 0.5라면 두 페널티가 반반씩 적용됩니다.

왜 이런 조합이 필요할까요? Lasso의 약점 중 하나는 상관관계가 높은 특성들을 다룰 때 불안정하다는 것입니다.

예를 들어 A, B, C 세 특성이 서로 높은 상관관계를 가진다면, Lasso는 이 중 하나만 무작위로 선택할 수 있습니다. 어떤 것이 선택될지 예측하기 어렵고, 데이터가 조금만 바뀌어도 다른 특성이 선택될 수 있습니다.

ElasticNet은 이 문제를 해결합니다. L2 페널티가 추가되면, 상관관계가 높은 특성들이 함께 선택되거나 함께 제외되는 경향이 있습니다.

이것을 **그룹 효과(Grouping Effect)**라고 합니다. 관련된 특성들이 그룹으로 움직이기 때문에 결과가 더 안정적입니다.

코드에서 l1_ratio에 따른 변화를 확인해보세요. l1_ratio가 0.1일 때는 Ridge에 가깝기 때문에 더 많은 특성이 남습니다.

0.9일 때는 Lasso에 가깝기 때문에 더 적은 특성이 선택됩니다. 이렇게 비율을 조절하면서 최적의 조합을 찾을 수 있습니다.

실무에서 ElasticNet이 특히 유용한 경우가 있습니다. 유전자 데이터처럼 특성의 수가 샘플 수보다 훨씬 많은 경우입니다.

이런 고차원 데이터에서는 Lasso만 사용하면 불안정할 수 있습니다. ElasticNet은 특성 선택의 장점을 유지하면서도 안정적인 결과를 제공합니다.

또한 특성들 사이에 그룹 구조가 있을 때도 효과적입니다. 예를 들어 마케팅 데이터에서 TV, 라디오, 신문 광고 비용이 서로 연관되어 있다면, ElasticNet은 이런 그룹을 적절히 처리합니다.

김개발 씨가 정리했습니다. "결국 ElasticNet은 Ridge와 Lasso의 좋은 점을 모두 가져온 거네요.

대신 파라미터가 하나 더 늘어났지만요." 박시니어 씨가 덧붙였습니다. "맞아요.

파라미터가 많아지면 최적화가 어려워지지만, sklearn의 ElasticNetCV를 사용하면 자동으로 찾을 수 있어요."

실전 팁

💡 - 처음에는 l1_ratio=0.5로 시작해서 결과를 보고 조절하세요

  • 특성들 사이에 그룹 구조가 있다면 ElasticNet이 Lasso보다 좋은 결과를 줄 가능성이 높습니다

6. 교차 검증으로 최적 파라미터 찾기

김개발 씨는 정규화 기법들을 이해했지만, alpha 값을 어떻게 정해야 할지 막막했습니다. "alpha를 0.1로 할까요, 1.0으로 할까요?" 박시니어 씨가 대답했습니다.

"직접 정하지 마세요. 교차 검증으로 데이터가 알려주게 하세요."

**교차 검증(Cross-Validation)**은 데이터를 여러 부분으로 나눠서 모델을 평가하는 방법입니다. sklearn은 RidgeCV, LassoCV, ElasticNetCV라는 편리한 클래스를 제공합니다.

이 클래스들은 자동으로 여러 alpha 값을 시도하고, 가장 좋은 성능을 내는 값을 찾아줍니다. 수작업으로 파라미터를 조정하는 것보다 훨씬 신뢰할 수 있습니다.

다음 코드를 살펴봅시다.

from sklearn.linear_model import RidgeCV, LassoCV, ElasticNetCV
import numpy as np

# 탐색할 alpha 값들
alphas = np.logspace(-4, 4, 50)  # 0.0001 ~ 10000

# RidgeCV - 자동으로 최적 alpha 탐색
ridge_cv = RidgeCV(alphas=alphas, cv=5)
ridge_cv.fit(X_train, y_train)
print(f"Ridge 최적 alpha: {ridge_cv.alpha_:.4f}")
print(f"Ridge 테스트 점수: {ridge_cv.score(X_test, y_test):.4f}")

# LassoCV - 자동으로 최적 alpha 탐색
lasso_cv = LassoCV(alphas=alphas, cv=5, max_iter=10000)
lasso_cv.fit(X_train, y_train)
print(f"\nLasso 최적 alpha: {lasso_cv.alpha_:.4f}")
print(f"Lasso 테스트 점수: {lasso_cv.score(X_test, y_test):.4f}")

# ElasticNetCV - alpha와 l1_ratio 모두 탐색
elastic_cv = ElasticNetCV(alphas=alphas, l1_ratio=[0.1, 0.5, 0.9], cv=5)
elastic_cv.fit(X_train, y_train)
print(f"\nElasticNet 최적 alpha: {elastic_cv.alpha_:.4f}")
print(f"ElasticNet 최적 l1_ratio: {elastic_cv.l1_ratio_:.2f}")

교차 검증이란 정확히 무엇일까요? 박시니어 씨가 비유로 설명을 시작했습니다.

"시험 공부를 할 때 기출문제로 연습하잖아요. 그런데 기출문제만 풀다 보면 그 문제에만 익숙해질 수 있어요.

그래서 똑똑한 학생들은 기출문제를 여러 세트로 나눠서, 한 세트로 공부하고 다른 세트로 테스트해봅니다. 교차 검증도 같은 원리예요." 구체적으로 K-폴드 교차 검증은 이렇게 작동합니다.

데이터를 K개의 부분(폴드)으로 나눕니다. 코드에서 cv=5라면 5개로 나눈 것입니다.

첫 번째 반복에서는 1번 폴드를 테스트용으로 남기고 나머지 4개 폴드로 학습합니다. 두 번째 반복에서는 2번 폴드를 테스트용으로 사용합니다.

이렇게 5번 반복하면 모든 데이터가 한 번씩 테스트에 사용됩니다. 최종 점수는 5번의 평균입니다.

왜 교차 검증이 중요할까요? 단순히 데이터를 한 번만 나눠서 평가하면, 우연히 쉬운 테스트 데이터를 골랐을 수도 있습니다.

교차 검증은 여러 번 평가하기 때문에 더 신뢰할 수 있는 결과를 얻을 수 있습니다. 코드를 자세히 살펴보겠습니다.

먼저 alphas 변수를 보세요. np.logspace(-4, 4, 50)은 0.0001부터 10000까지 로그 스케일로 50개의 값을 생성합니다.

alpha는 보통 로그 스케일로 탐색합니다. 0.1과 0.2의 차이보다 0.001과 0.01의 차이가 더 중요하기 때문입니다.

RidgeCV는 주어진 모든 alpha 값에 대해 교차 검증을 수행하고, 가장 좋은 alpha를 찾습니다. 학습이 끝나면 alpha_ 속성에 최적 값이 저장됩니다.

LassoCV도 마찬가지입니다. 다만 max_iter 파라미터가 추가되었습니다.

Lasso는 최적화에 반복 알고리즘을 사용하는데, 기본값으로는 수렴하지 않을 수 있어서 넉넉하게 설정합니다. ElasticNetCV는 alpha뿐만 아니라 l1_ratio도 함께 탐색합니다.

두 파라미터의 모든 조합을 시도해서 최적의 조합을 찾습니다. 결과에서 alpha_와 l1_ratio_ 속성으로 최적 값을 확인할 수 있습니다.

실무에서의 활용법을 알아봅시다. 프로젝트를 시작할 때, 먼저 세 가지 CV 모델을 모두 돌려보세요.

각각의 최적 파라미터와 테스트 점수를 비교하면, 어떤 방법이 이 데이터에 가장 적합한지 객관적으로 판단할 수 있습니다. 김개발 씨가 감탄했습니다.

"이렇게 하면 제 감으로 정하는 것보다 훨씬 좋겠네요!" 박시니어 씨가 덧붙였습니다. "맞아요.

데이터 과학에서는 항상 데이터가 답을 알려주게 해야 해요. 우리의 직관은 종종 틀리니까요."

실전 팁

💡 - alpha 탐색 범위는 넓게 시작하고, 최적값 근처에서 좁혀가세요

  • cv 값은 보통 5나 10을 사용합니다. 데이터가 적으면 더 큰 값을 사용하세요

7. 실무 프로젝트 적용 예제

이론 공부를 마친 김개발 씨는 드디어 실제 프로젝트에 적용해보기로 했습니다. 회사에서 받은 주택 가격 예측 데이터를 가지고 Ridge, Lasso, ElasticNet을 모두 적용해보기로 했습니다.

박시니어 씨가 옆에서 지켜보며 조언해주기로 했습니다.

실무에서는 단순히 모델을 적용하는 것으로 끝나지 않습니다. 데이터 전처리, 모델 선택, 성능 평가, 해석까지 전체 파이프라인을 구축해야 합니다.

특히 정규화 모델을 사용할 때는 특성 스케일링이 필수입니다. 스케일이 다른 특성이 있으면 정규화가 제대로 작동하지 않기 때문입니다.

다음 코드를 살펴봅시다.

from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import RidgeCV, LassoCV
import numpy as np

# 파이프라인 구성: 스케일링 + 정규화 모델
ridge_pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('model', RidgeCV(alphas=np.logspace(-4, 4, 50), cv=5))
])

lasso_pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('model', LassoCV(alphas=np.logspace(-4, 4, 50), cv=5))
])

# 학습 및 평가
ridge_pipe.fit(X_train, y_train)
lasso_pipe.fit(X_train, y_train)

print(f"Ridge 테스트 점수: {ridge_pipe.score(X_test, y_test):.4f}")
print(f"Lasso 테스트 점수: {lasso_pipe.score(X_test, y_test):.4f}")

# 최적 파라미터 확인
print(f"\nRidge 최적 alpha: {ridge_pipe.named_steps['model'].alpha_:.4f}")
print(f"Lasso 최적 alpha: {lasso_pipe.named_steps['model'].alpha_:.4f}")

김개발 씨가 첫 번째로 배운 것은 스케일링의 중요성이었습니다. 박시니어 씨가 물었습니다.

"주택 가격 데이터에 면적과 방 개수가 있다고 해봐요. 면적은 100500 정도고, 방 개수는 15 정도예요.

이 상태로 정규화를 적용하면 어떻게 될까요?" 정규화는 계수의 크기에 페널티를 부여합니다. 그런데 면적의 계수와 방 개수의 계수는 스케일이 완전히 다릅니다.

면적 1 증가는 가격에 조금 영향을 주지만, 방 1개 증가는 큰 영향을 줍니다. 스케일이 다르면 정규화가 불공평하게 적용됩니다.

StandardScaler는 이 문제를 해결합니다. 모든 특성을 평균 0, 표준편차 1로 변환합니다.

이렇게 하면 모든 특성이 비슷한 스케일을 가지게 되고, 정규화가 공평하게 적용됩니다. 다음으로 배운 것은 Pipeline의 활용입니다.

스케일링과 모델 학습을 따로 하면 실수하기 쉽습니다. 특히 테스트 데이터에도 학습 데이터의 스케일링 파라미터를 적용해야 하는데, 이것을 잊어버리는 경우가 많습니다.

Pipeline은 이 모든 과정을 하나로 묶어줍니다. 코드에서 Pipeline의 구조를 보세요.

첫 번째 단계는 StandardScaler로 스케일링을 수행합니다. 두 번째 단계는 실제 모델입니다.

fit을 호출하면 두 단계가 순서대로 실행됩니다. predict나 score를 호출해도 마찬가지입니다.

실무에서 자주 겪는 실수가 있습니다. 김개발 씨가 물었습니다.

"테스트 데이터도 따로 스케일링해야 하나요?" 박시니어 씨가 중요한 점을 짚어주었습니다. "테스트 데이터는 학습 데이터의 평균과 표준편차로 스케일링해야 해요.

테스트 데이터의 통계치를 사용하면 안 됩니다. Pipeline을 사용하면 이런 실수를 방지할 수 있어요." 모델 선택에 대한 조언도 있었습니다.

결과를 보면 Ridge와 Lasso의 테스트 점수가 나옵니다. 점수 차이가 작다면, 해석이 필요한지에 따라 선택하면 됩니다.

Lasso는 어떤 특성이 중요한지 알려주므로 비즈니스 인사이트를 얻기 좋습니다. Ridge는 예측 성능이 목표일 때 안정적인 선택입니다.

김개발 씨가 정리했습니다. "스케일링, 파이프라인, 그리고 목적에 맞는 모델 선택.

이 세 가지가 핵심이군요!"

실전 팁

💡 - Pipeline을 사용하면 스케일링 실수를 방지할 수 있습니다

  • 모델 해석이 필요하면 Lasso, 순수 예측 성능이면 Ridge를 우선 고려하세요
  • named_steps로 파이프라인 내부 모델의 속성에 접근할 수 있습니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#Ridge#Lasso#Regularization#MachineLearning#Data Science

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.