
경마 AI 개발 기록 #25 예측 공간의 '통치'와 통합: 멀티 모델 포트폴리오로의 각성
요약
경마 예측을 위한 멀티 모델 아키텍처 설계와 통합 전략을 다룹니다. 모델별 특징량 공간(feature space)을 격리하여 데이터 오염을 방지하고, Optuna를 활용한 통합 스코어 최적화 및 확장 가능한 포트폴리오 프레임워크 구축 과정을 기록합니다.
핵심 포인트
- ModelConfig 도입을 통한 선언적 아키텍처 구현
- 모델별 특징량 공간 격리로 데이터 오염 및 ROI 급락 방지
- Optuna를 이용한 랭킹 및 TOP3 모델 간 통합 스코어 최적화
- BetType 클래스를 통한 새로운 마권 종류의 확장성 확보
개요
전 화(제24화)에서는 단승식 특화의 한계를 타파하기 위해 **복승식 전용 모델(TOP3 모델)**을 도입하고, 모델 간의 특징량 공간(feature space)을 논리적으로 분리하는 시도에 대해 다루었습니다. 하지만 임시방편적인 분리만으로는 모델이 늘어날 때마다 '데이터 오염'이나 '파이프라인의 불일치'가 발생하는 취약함이 드러났습니다.
제25화에서는 이러한 과제를 근본적으로 해결하기 위한 아키텍처 쇄신과, 여러 모델을 최적으로 조합하는 멀티 모델 통합 전략에 대해 상세히 설명합니다. 단순한 예측 정밀도 향상을 넘어, 시스템 전체를 '투자 포트폴리오'로서 기능하게 하기 위한 확장 가능한 프레임워크 확립을 향한 경로를 기록합니다.
구현 내용
1. 「예측 공간의 통치」: ModelConfig와 feature_spaces 도입
각 모델이 자신의 특징량 공간, 하이퍼파라미터(hyperparameter), 그리고 평가 방침을 스스로 관리하는 '선언적 아키텍처(declarative architecture)'로 이행했습니다.
- ModelConfig / EvalConfig: 각 모델의 역할(role: "output", "filter" 등)과 주요 메트릭(primary_metric)을 캡슐화했습니다.
- feature_spaces 딕셔너리: 단일한 글로벌
feature_fingerprint를 폐지.model_trainer.py내에 각 모델 전용 열(column) 세트를 정의하는feature_spaces를 도입했습니다. - 교정 데이터의 물리적 격리:
calib_history의 구조를X_ranking,X_anauma,X_top3와 같이 모델별로 분리. 랭킹 모델의 입력이 다른 모델 전용의 NaN 열에 의해 오염되는 것을 물리적으로 차단했습니다.
2. 멀티 모델 통합 스코어 설계
랭킹 모델의 '실력 예측'과 TOP3 모델의 '복승권 진입 기대치'를 융합하기 위해, 다음과 같은 통합 스코어를 정의했습니다.
여기서, Optuna를 사용하여 0.3 ~ 0.8 범위에서 최적화됩니다.
3. 확장 가능한 포트폴리오 프레임워크 확립
장래의 마권 종류(마련, 삼연복 등) 추가에 '정의 추가만으로' 대응할 수 있도록 betting_logic.py를 쇄신했습니다.
- BetType 데이터 클래스: 각 마권 종류의 적중 판정 로직과 배당률 참조 열을 캡슐화.
- PortfolioResult 데이터 클래스: 마권 종류별 손익을 통일된 포맷으로 집계 및 영속화하는 메커니즘을 구축했습니다.
직면한 문제
1. 특징량 공간의 「NaN 오염」과 ROI의 급락
리팩터링(refactoring) 과정에서 TOP3 전용 열(jockey_place_rate 등)이 단승식 교정기의 입력에 혼입되었습니다. 교정된 승률(calibrated_prob_win)의 계산이 왜곡되어, 단승식 ROI가 85.17%에서 67.38%로 약 20포인트 급락하는 사태에 직면했습니다.
2. 시뮬레이션 엔진의 인덱스 불일치
simulation_engine.py 내의 prepare_features에서의 정렬 처리로 인해, 예측값과 결과 데이터프레임(dataframe)의 인덱스가 괴리되었습니다. 평가 지표가 NaN화 되어, 2026년의 포워드 테스트(forward test)가 일시적으로 계산 불능 상태가 되었습니다.
3. 동적 로드 시의 캐시 불일치
SimulationEngine에 의한 실험 모듈의 동적 로드 시, Jupyter의 커널 캐시로 인해 오래된 get_feature_columns가 참조되어, 새로 설치한 특징량이 무시되는 버그가 발생했습니다.
해결 접근 방식
1. 아키텍처 변경의 단계적 적용
대규모 변경으로 인한 디버깅의 복잡화를 피하기 위해, 다음과 같이 3단계로 나누어 적용했습니다.
ModelConfig도입 및 모델별 공간 확립calib_history의 구조 변경- 추론 파이프라인으로부터
X_full인자 폐지 및 카테고리 처리의 영구적 해결
2. 인덱스에 의존하지 않는 머지(merge) 전략
파이프라인의 모든 대입 처리를 "인덱스에 의존하지 않고, 복합 키(race_id + horse_number)로 머지한다"는 merge 기반으로 쇄신했습니다.
3. 동적 로드 캐시의 철저한 배제
importlib.invalidate_caches()와 sys.modules...
master_analyzer.ipynb를 수정하여 명시적인 삭제를 세트로 실시하도록 했습니다. 실험 환경 전환 시 오래된 정의가 남지 않도록 안전책을 마련했습니다.
최종적인 해결책
최종 시스템 구성
- 특징량 관리 (Feature Management):
ModelConfig.trained_features에 기반한 자기 관리형 공간. - 추론 기반 (Inference Infrastructure):
score_integrator.py를 통한 모델 특성에 따른 동적인 스코어 통합. - 포트폴리오 (Portfolio):
BetType사전을 통한 마권 종류 확장 프레임워크.
개선된 구체적인 수치
| 지표 | 개선 전 | 개선 후 | 평가 |
|---|---|---|---|
| 전체 ROI | 67.38% | 80.49% | 멀티 모델화 후, 80%대로 회복 ✅ |
| In-Race Spearman | 0.2527 | 0.3687 | 리크 (Leak) 대책 후 최고치 경신 ✅ |
| Top-1 Hit Rate | 20.24% | 22.91% | 식별 능력의 대폭 향상 ✅ |
| prob_top3 AUC | 0.7213 | 0.7233 | 이전 수준을 유지 ✅ |
배운 점
예측 공간에서의 「통치 (Governance)」의 중요성
제4화에서 도입한 feature_fingerprint는 단일 모델 시대의 「열 어긋남 (Column Shift)」을 방지하는 철벽의 가드레일이었습니다. 하지만 시스템이 다두 구매 (Multi-bet)를 수행하는 멀티 모델로 진화했을 때, 「모든 모델에 동일한 데이터를 보여준다」는 초기 설계 사상은 그 역할을 다했습니다. **모델마다 「보여줘야 할 정보」를 엄격하게 제한하는 것 (Governance)**이야말로, 앙상블 효과를 최대화하고 시스템의 수익성을 사수하기 위한 생명선임을 통감했습니다.
통합 스코어라는 「엣지 (Edge)」
실력 모델과 TOP3 모델은 각각 서로 다른 정보를 포착하고 있습니다. 이들을 가중 평균한 통합 스코어가 단일 모델을 압도하는 Spearman 상관관계 (+0.11 향상)를 기록했다는 사실은, 단순한 알고리즘 개선을 넘어선 「전략적 통합」의 위력을 증명했습니다.
차회 예고
특징량 공간의 분리와 포트폴리오 기반의 확립을 통해, 다음 수를 위한 준비가 완료되었습니다. 다음 회차에서는 복병마 검지 (anauma)와 짝을 이루는, 인기마의 침몰을 사전에 감지하는 필터 모델의 도입으로 이어집니다.
제26화, 「범주 모델 (凡走モデル) 신설: 인기마의 사각지대를 찌르는 필터 전략」.
기댓값 운용의 정밀도는 드디어 「공격」과 「방어」라는 두 바퀴를 모두 갖추게 됩니다.
Discussion

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