본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 06. 10. 08:16

경마 AI 개발 기록 #17: LightGBM의 rank_xendcg와 사투 - 기울기 폭발 방지를 위한 타겟 설계

요약

경마 예측 모델의 목적 함수를 이진 분류에서 랭킹 학습(LTR)으로 전환하는 과정에서 발생한 LightGBM의 기울기 폭발 문제를 다룹니다. rank_xendcg 사용 시 발생하는 수치적 불안정성을 해결하기 위해 타겟 레이블을 정규화하는 설계 방안을 제시합니다.

핵심 포인트

  • 이진 분류를 넘어 경주 내 상대적 서열을 예측하기 위해 랭킹 학습 도입
  • 연속값 레이블 처리가 가능한 rank_xendcg 목적 함수 채택
  • 레이블 값의 제곱으로 인해 발생하는 기울기 폭발(Gradient Explosion) 문제 식별
  • 타겟 정규화를 통해 수치적 안정성 확보 및 학습 정상화

1. 개요

지난번(제16화)에서는 데이터 누수(data leak)를 배제한 환경에서 동적 특징량(dynamic feature)을 도입함으로써 아웃사이더마(穴馬, 이변의 말) 식별 능력(KS 통계량 0.50)을 확보하는 데 성공했습니다. 하지만 아웃사이더 감지(이진 분류)만으로는 경주 전체 기대값을 최대화할 수 있는 '적절한 순위 지정'을 수행하기에는 불충분합니다.

제17화에서는 모델의 목적 함수를 분류(classification)에서 랭킹 학습(Learning to Rank: LTR)으로 전환하여, 경주 내 모든 출전마의 상대적인 서열을 예측하는 시도에 대해 기술합니다. 그 과정에서 직면했던 LightGBM의 rank_xendcg에서의 '기울기 폭발'(gradient explosion)이라는 수학적 과제와, 그 해결책으로서 타겟 설계(target design)에 대해 설명합니다.

2. 구현 내용

마권 전략, 특히 기대값에 기반한 운용을 하려면 각 말이 1착이 될 확률뿐만 아니라, 경주 내에서의 실력 서열을 정확히 파악해야 합니다. 이에 모델의 objective를 이진 분류의 binary에서 랭킹 학습용 rank_xendcg로 변경했습니다.

2-1. 왜 rank_xendcg 인가

LightGBM에는 랭킹 학습용으로 lambdarankrank_xendcg 두 가지 주요 목적 함수가 준비되어 있습니다.

  • lambdarank: 타겟 레이블로 '정수(관련도)'를 요구합니다. `
  • rank_xendcg: 타겟 레이블로 '연속값(부동소수점)'을 받아들일 수 있습니다.

본 프로젝트에서는 착순 그 자체뿐만 아니라, 주파 시간 편차(performance score)에 기반한 미세한 실력 차이를 레이블에 반영하기 위해 연속값을 다룰 수 있는 rank_xendcg를 채택했습니다.

2-2. 타겟 레이블 설계

각 경주(Group) 내에서의 상대적인 평가를 학습시키기 위해, 다음과 같은 형식으로 타겟(정답값)을 정의했습니다.

# model_trainer.py 내부의 타겟 생성 로직 (개념)
def create_ranking_target(df, alpha):
# 착순을 반전시켜 상위일수록 높은 값을 갖도록 변환
...

3. 직면한 문제

rank_xendcg를 도입하고 초기 설정으로 학습을 시작하자마자 심각한 수치적 불안정성에 직면했습니다.

3-1. 천문학적인 RMSE와 학습 정지

학습 로그를 확인해보니, 통상적으로는 0.1~1.0 정도에 머물러야 할 rmse (모니터링용 지표)가 1.85965e+13 (18조 초과)라는 비정상적인 수치를 기록하고 있었습니다. 동시에, feature_importance 값도 1.798997e+32라는 부동소수점의 한계에 가까운 값을 출력했습니다.

이 상태에서는 모델이 유효한 정보를 전혀 학습할 수 없었고, 스피어만 상관계수는 0.0000 (완전한 무상관)이 되었습니다.

3-2. 기울기 폭발의 원인 특정

원인은 LightGBM의 랭킹 학습에서의 '이득(Gain)' 계산식에 있었습니다.

rank_xendcglambdarank는 내부적으로 각 레이블 값
만약 타겟 레이블
예를 들어,

4. 해결 접근법

이 문제를 해결하기 위해서는 모델에 전달하는 '관련도(relation)'의 스케일을 수학적으로 안정된 범위에 수렴시킬 필요가 있었습니다.

4-1. 타겟 정규화

먼저, 타겟 레이블을 마필 수와 관계없이 일정한 범위에 수렴시키기 위해, 마필 수로 나누는 정규화를 도입했습니다.

# 개정된 타겟 설계
df['target'] = (df['num_horses_in_race'] + 1 - df['rank']) / df['num_horses_in_race']

이로써, 타겟은

4-2. 모니터링 지표 변경

rank_xendcg 사용 시 metric='ndcg'를 지정하면, 내부적으로 타겟을 정수로 캐스팅하려 하여 정보 손실이 발생하거나 타입 에러를 일으킬 수 있습니다.

이를 회피하기 위해, 수렴 모니터링에는 metric='rmse'를 사용하는 것으로 결정했습니다. 랭킹 학습에서 rmse 자체의 값에 큰 의미는 없지만, '값이 감소하고 있는지'를 확인할 지표로는 충분히 기능합니다.

5. 최종적인 해결책

실험 exp018

에서, Optuna를 사용하여 수치적으로 가장 안정적이면서도 식별능(스피어만 상관계수)이 최대화되는 target_alpha의 범위를 탐색했습니다.

5-1. 선형 관계 타겟 구현

최종적으로 다음 선형 관계 타겟과 하이퍼파라미터 조합을 채택했습니다.

# model_trainer.py의 최종적인 구현 구성
# 1. target_alpha의 탐색 범위를 1.1 ~ 1.9로 제한 (기울기 폭발 방지)
target_alpha = trial.suggest_float('target_alpha', 1.1, 1.9)
...

5-2. 도입 결과

이 타겟 설계의 개선을 통해 수치적 불안정성은 완전히 해소되었습니다.

  • RMSE: 10조 초과 $
    ightarrow$ 0.3 ~ 0.5 (정상값)
  • 스피어만 상관계수: 0.00 $
    ightarrow$ 0.4021

저조했던 예측 성능이 극적으로 회복되었고, 레이스 내 모든 말의 순위를 높은 정확도로 예측할 수 있는 '무기'가 완성되었습니다.

6. 배운 점

목적함수의 수학적 배경 이해

'LTR(랭킹 학습)'은 정확도가 높다는 표면적인 정보만으로 도입하면, 내부적인 이득 계산(

타겟 설계의 민감성

이진 분류(0 또는 1)와는 달리, 랭킹 학습이나 회귀에서의 타겟 '스케일'은 학습의 성패를 가르는 결정적인 요소입니다. 특히 지수 함수를 포함하는 목적함수의 경우, 정규화나 스케일링(이번의 target_alpha 제한)
은 단순한 튜닝이 아니라 '전제 조건'이 됩니다.

상수 입력 경고에 대한 주시

스피어만 상관계수가 0.0000이 되었을 때 발생한 ConstantInputWarning
(입력이 상수라는 경고)는, 모델이 기울기 폭발로 인해 모든 샘플에 대해 같은 값(또는 NaN)을 출력하고 있음을 보여주는 중요한 신호였습니다. 에러가 나지 않는 '조용한 실패'야말로 경고 로그에 해결의 힌트가 숨겨져 있습니다.

7. 다음 편 예고

랭킹 학습 도입으로 순위 예측 정확도는 비약적으로 향상되었습니다. 하지만, 여기서 또 다른 과제가 부상합니다. 그것은 모델이 업데이트될 때마다 예측값의 절대값이 하락하는 '스코어 디플레이션'과, 이로 인해 고정된 구매 기준 임계값이 기능하지 못하게 되는 문제입니다.

다음 편에서는 모델 출력 특성의 변화를 인정하고, 상대적인 평가로 구매 기준을 정하는 전략으로 방향을 틀겠습니다.

Discussion

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0