가상개경주 기록 예측 모델 입문
가상개경주를 오래 지켜본 이들은 금세 눈치챌 것이다. 같은 공급사, 같은 트랙 길이, 비슷한 배당 구간인데도 결승 기록이 미세하게 달라지고, 어느 시점부터 특정 트랩의 평균 기록이 0.03초쯤 짧아지는 구간이 생긴다. 실제 개의 컨디션 변화가 아니라 엔진 내부 확률 테이블과 난수 시퀀스의 미묘한 변동이 만든 현상이다. 이 글은 그런 환경에서 기록을 예측하는 모델을 처음 세우려는 사람을 위한 안내서다. 기본 전제, 데이터 구성, 모델링 아이디어, 평가와 운영까지 실제로 손을 더럽혀 본 사람의 관점으로 풀어 보겠다. 가상경마를 오래 다뤘거나 가상축구, 가상농구의 시장 데이터를 수집해 본 사람이라면 많은 부분이 익숙하게 느껴질 것이다. 다만 가상개경주는 결승 기록이라는 연속값이 핵심 타깃이라는 점이 다르고, 그 점이 설계의 절반을 좌우한다.
가상개경주 환경을 바로 이해하기
현실의 경주는 기온, 지면 상태, 출발 실패 같은 변수가 늘 문제다. 가상개경주는 다르다. 결과는 엔진이 만든 확률 구조와 난수에 의해 정해진다. 그게 끝이다. 외부 요인이라고 해봐야 공급사 버전 업, 결과 화면의 반올림 규칙, 배당 산출 로직 같은 시스템적 변화뿐이다. 그렇다고 예측이 쉬울까. 의외로 그렇지 않다. 이유는 세 가지다. 첫째, 공급사는 내부 확률을 공개하지 않는다. 둘째, 기록 출력에는 종종 절단과 반올림이 개입된다. 셋째, 고정돼 보이는 분포가 시간이 지나며 아주 느린 속도로 움직인다. 승률은 그대로인데 기록 분포만 0.01초 단위로 미끄러지듯 이동하는 경우가 대표적이다. 이 때문에 기록 예측은 확률 모델링, 신호 탐지, 로깅과 모니터링이 결합된 작업이 된다.
여기서 말하는 기록은 대부분 결승선 통과 시각, 그러니까 경주 시작 시각 대비 완주 시간이다. 섹션 타임이 공개되는 공급사도 일부 있지만 흔하지 않고, 구간 타임은 노이즈가 더 거칠다. 모델의 1차 목표는 완주 시간의 기대값과 분포를 추정하는 일이다. 부가 목표로 순위별 시간 차이, 상위권과 하위권의 간극 크기도 확보하면 활용도는 올라간다. 기록 예측이 왜 유용한지는 다음 장에서 설명한다.
기록 예측이 주는 이점
시장에선 순위 예측이 더 익숙하다. 그럼에도 시간을 직접 모델링하면 보너스가 많다. 첫째, 배당과 무관하게 엔진 상태를 감지할 수 있다. 승패는 배당과 강하게 결합돼 있지만, 시간은 그 결합이 느슨하다. 같은 암시 확률이라도 속도 패널티가 바뀌면 기록 분포가 먼저 흔들린다. 둘째, 몇몇 공급사에서는 동일 거리 레이스의 기록 분포 안정성이 높아, 기록 기반 이상치 탐지가 잘 먹힌다. 알파가 아주 작게라도 나온다. 셋째, 시뮬레이션 기반 전략의 핵심 입력으로 쓰기 좋다. 예를 들어 상위 두 마리의 도착 차이를 모의 생성해 특정 조합의 기대 손익을 빠르게 추정할 수 있다. 가상경마에서도 같은 이점이 확인된다.
가상축구와 가상농구에선 득점 수 예측을 하면서 포아송 계열 모델과 로그 링크를 다룬다. 가상개경주 시간 모델링은 그보다 연속값에 가깝고, 보통은 로그 정규나 감마 분포 가정이 어울린다. 배당을 로그 속도 패널티로 변환하는 방식은 세 종목을 관통하는 베이스라인으로 잘 작동한다.
범위를 정하고 실패를 줄이기
처음부터 모든 공급사, 모든 거리, 모든 트랩을 한꺼번에 다루면 금세 길을 잃는다. 거리를 하나 고르고, 같은 엔진 버전으로 보이는 기간만 묶어 시작하는 편이 낫다. 10만 건이 넘는 기록을 모을 수 있으면 훌륭하지만, 2만에서 3만 건 사이만 돼도 분포의 뼈대는 잡힌다. 핵심은 일관성이다. 스냅샷 주기, 저장 단위, 반올림 처리 규칙을 초기에 고정해 둬야 나중에 드리프트를 정확히 포착할 수 있다.
특히 반올림은 흔한 지뢰다. 예를 들어 내부 엔진은 밀리초 단위로 시간을 만들지만 화면에는 0.01초 단위로 반올림해 표기한다. 이때 0.005초 오차가 주기적으로 쌓이면서 특정 구간의 히스토그램이 톱니 모양이 된다. 모델이 이 패턴을 분포의 일부로 착각하면 재현 성능은 올라가는데 외삽 성능은 망가진다. 원시 표기 단위를 그대로 모델링하되, 평가할 때만 반올림 규칙을 적용해 점수를 계산하는 트릭이 유용하다.
데이터 수집, 저장, 그리고 필드 정의
필드 스키마는 지나치게 화려할 필요가 없다. 다만 다음 다섯 가지는 빠지면 뼈아프다.
레이스 ID, 시작 시각, 거리, 트랩 수 각 출전 개체의 표시명, 트랩 번호, 사전 배당과 확정 배당 완주 시간과 도착 순위, 동착 여부 표시 시간의 소수점 처리 규칙과 소스 문자열 엔진 버전으로 보이는 변화 포인트의 구분자 태그
이 스키마만 갖고도 80퍼센트의 작업은 가능하다. 그 외에 수집하면 좋은 값으로는 요일, 시각대, 레이스 간 간격, 공급사 서버 응답 지연, 화면 프레임 드롭 신호 등이 있다. 직접 겪은 일화로, 한 공급사는 매일 특정 시간대에만 평균 기록이 0.02초 늘어났다. 서버 부하로 내부 시뮬레이션 틱 레이트가 바뀐 듯했고, 한 달 후 패치가 나오며 현상이 사라졌다. 이 정도의 변화를 잡으려면 시각대와 응답 지연 같은 흔적이 도움이 된다.
저장은 시간 파티셔닝을 지키는 게 중요하다. 레이스 시작 시각 기준으로 하루 단위 파티션을 나누고, 엔진 버전 추정 태그를 세컨더리 키로 둔다. 버전 태그는 공식 정보가 아니라 지표 기반 휴리스틱이므로 가벼운 오차에 관대해야 한다. 태그를 기준으로 학습과 평가를 나누면 드리프트 감지가 쉬워진다.
타깃 정의의 선택지
기록을 그대로 회귀 타깃으로 삼을 수도 있고, 약간 변형해 사용할 수도 있다. 실무에서 자주 쓰는 방법은 세 가지다. 첫째, 로그 변환이다. 시간은 양수이고 꼬리가 두껍다. 로그를 취하면 감마나 로그 정규 가정이 잘 맞는다. 둘째, 표준화다. 같은 거리, 같은 트랩 수로 묶어 평균 0, 표준편차 1로 맞춘다. 공급사마다 절대적 시간대가 다르기 때문이다. 셋째, 순위 조건부 분포다. 예를 들어 1위가 된 경우의 시간 분포, 2위가 된 경우의 시간 분포를 따로 모델링하고, 사후에는 순위 확률과 합성한다. 표본이 충분하면 세 번째가 가장 높은 분리도를 보이는 편이다. 다만 동착이 많은 공급사에서는 합성 과정이 복잡해진다.
동착 처리는 미리 결정하자. 표시 시간이 같고 순위가 동착인 경우를 별도 클래스로 구분해도 되고, 소수점 단위 제한 탓에 생긴 표시 동착으로 보고 미세 잡음을 주입해 타임스탬프를 흩뜨릴 수도 있다. 후자를 쓰면 회귀 손실이 안정적이다.
베이스라인, 너무 과소평가하지 말기
기본선이 탄탄하면 이후 모델이 과하게 요동치지 않는다. 예측은 크게 두 층으로 쪼갠다. 첫째, 베이직한 분포. 거리별, 트랩별 평균과 분산을 구한다. 충분히 길게 모으면 이 값만으로도 MAE가 괜찮게 나온다. 둘째, 배당을 속도 패널티로 변환하는 층이다. 직관은 간단하다. 이길 확률이 높은 개가 평균적으로 더 빠르며, 그 차이는 로그 오즈와 거의 선형을 이룬다. 실무에선 다음 형태가 잘 맞는다.
log(time) = μ(distance, traps) + α logit(p_implied) + β(trap) + ε
여기서 p_implied는 배당으로부터 얻은 암시 확률이고, logit은 로그 오즈 변환이다. α와 β는 학습으로 얻는다. ε는 잔차다. 공급사에 따라 α가 음수로 작게 추정된다. 절대치가 클수록 승률과 기록의 결합이 강하다는 뜻이다. 데이터를 처음 대면할 때 α의 범위가 대략 -0.03에서 -0.12 사이로 나오면 특별히 이상한 게 없다.
특징 공학의 실전 목록
배당 외에 유용한 피처는 의외로 단순한 것들이다. 같은 거리로 묶인 레이스 인덱스, 요일과 시각대, 버전 태그, 트랩 번호와 트랩 절대 위치 효과, 이전 레이스와의 시간 간격, 같은 세션 안에서의 순서 등이 그렇다. 이들 가운데 특히 영향력이 큰 것은 세션 내 인덱스다. 세션 초반과 후반의 평균 기록이 0.01초 정도 벌어지는 경우가 있다. 공급사 측 시뮬레이션 초기화와 관련이 있어 보였고, 이 패턴은 버전이 바뀌면 사라졌다가 다시 나타나곤 했다.
한편, 이름 피처는 거의 쓸모가 없다. 개체의 이름은 실제 성능과 무관하고, 중복되는 이름 또는 숫자가 붙은 변형이 많다. 이름을 카테고리로 쓰는 순간 모델이 데이터베이스 특정 구간에 과적합한다. 차라리 이름을 해시해 노이즈 피처로 집어넣고 규제 강하게 두는 편이 낫다.
확률적 모델이 필요한 이유
점 추정만으로는 실제 운용에 애를 먹는다. 기록 예측의 성공은 오차 분포를 얼마나 잘 잡느냐에 달렸다. 평균을 맞추는 모델보다 분위수를 잘 맞추는 모델이 쓸모가 많다. 핀볼 손실을 사용해 10, 50, 90 분위수를 함께 학습하면 분포의 꼬리가 과도하게 얇아지는 문제를 줄일 수 있다. 그 다음 단계로는 감마 회귀나 로그 정규 회귀를 확률적 출력으로 쓰는 방법이 있다. 파라미터를 예측하고, 예측 분포에서 샘플링해 시뮬레이션에 투입한다. 상위권 두 마리의 격차 분포를 수천 번 생성하면 조합별 위험을 미리 체감할 수 있다.
계층적 베이지안 모델도 고려할 만하다. 거리와 트랩에 따른 기본 평균과 분산을 상위 계층으로 두고, 세션이나 버전 태그별로 약한 편향을 허용한다. 완전한 MCMC까지 가지 않아도 변분 추정으로 충분한 경우가 많다. 이렇게 하면 한동안 데이터가 적었던 신규 세션에서도 과한 추정을 피한다. 샘플당 계산 시간이 길어진다는 단점이 있지만, 주기적 오프라인 학습과 온라인 미세 보정으로 절충하면 운영이 가능하다.
검증, 이 부분에서 가장 많이 실수한다
교차검증을 무작위로 하면 수치가 과하게 좋게 나온다. 같은 세션, 같은 버전 안에서 난수 시퀀스가 겹치기 때문이다. 시간 순서 검증을 지키자. 과거로 학습하고 미래로 평가한다. 버전 태그 경계에서 끊어 평가 세트를 만든다. 표본이 작다면 롤링 윈도 방식을 쓴다. 지표는 세 가지를 추천한다. MAE와 RMSE로 점 예측 품질을 본다. 예측 분포가 있다면 CRPS로 전체 분포 적합도를 잰다. 마지막으로 칼리브레이션 플롯을 그려서 분위수 예측이 책정된 확률과 맞는지 확인한다. 50 분위수 예측이 실제로 50퍼센트의 빈도로 아래에 위치하는지 보는 방식이다.
또 하나의 흔한 실수는 반올림 후의 점수만 보는 것이다. 내부 연속값 기준 점수와, 화면 반올림 기준 점수를 나눠 계산하자. 두 값의 간극이 벌어지면 반올림 규칙 변동을 의심해 볼 만하다.
기록과 배당의 동학을 함께 보는 프레임
가상개경주 공급사 대부분은 결과 확률을 정하고, 그에 맞춰 배당을 책정한 뒤, 최종 결과를 난수로 뽑는다. 이 구조에서는 배당이 결과와 강하게 연동된다. 기록은 그보다 한 다리 멀다. 이 말은 배당으로부터 충분히 많은 정보를 뽑아낼 수 있지만, 배당만으로 설명되지 않는 잔차가 생길 수 있다는 뜻이다. 실무에서 유용한 절차는 다음과 같다.
레이스별로 배당에서 암시 확률을 만들고, 로그 오즈로 변환한다. 로그 시간에서 로그 오즈 효과를 제거한 잔차를 구한다. 잔차를 시간에 따라 그려 드리프트와 반복 패턴을 찾는다. 반복 패턴에 요일, 시각대, 세션 인덱스 같은 외생 피처를 회귀시켜 정태적 보정을 만든다. 보정 후 잔차의 분산이 줄었는지, 분위수 칼리브레이션이 개선됐는지 확인한다.
이 절차를 몇 달 돌리면, 배당이라는 거대한 신호 위에 얹힌 작은 편향을 구조적으로 설명하는 모델이 완성된다.
작은 예시로 감을 잡기
예를 들어 보자. 거리 480 m, 트랩 6개인 공급사 A의 8주 데이터를 모았다. 총 24,000개 레이스, 완주 시간 평균은 28.74초, 표준편차는 0.18초다. 베이스라인으로 로그 시간을 쓰고, 로그 오즈와 트랩 더미를 피처로 둔 선형 모델을 학습했다. 검증은 마지막 2주를 홀드아웃으로 삼았다. 결과는 MAE 0.042초. 같은 데이터에서 단순 평균만 쓰면 MAE가 0.058초 정도였다. 로그 오즈 계수 α는 -0.076으로 추정됐다.
여기에 세션 인덱스와 요일, 시각대 더미를 추가했고, 버전 태그 경계에서 계수를 분리했다. MAE는 0.039초로 내려갔다. 분포형 모델로 바꿔 로그 정규의 μ와 σ를 예측하자, 50 분위수 MAE가 0.038초, CRPS가 0.021로 나왔다. 분위수 칼리브레이션에서 10 분위수 예측이 실제로 9.7퍼센트를 커버했고, 90 분위수는 90.4퍼센트를 커버했다. 실전에서 이 정도의 적합도면 시뮬레이션 기반 전략의 입력으로는 충분하다.
다만 5주 차 이후 특정 요일 저녁 시간대에 평균이 0.015초 늘어나는 구간이 확인됐다. 같은 기간 승률 칼리브레이션은 멀쩡했기 때문에 엔진 틱 레이트 문제로 추정됐다. 이 시점에 버전 태그를 새로 붙이고, 학습 파이프라인에서 가중치를 시간 감쇠로 두었다. 변화 탐지 임계값은 일일 평균 잔차가 0.008초를 넘기면 경고하도록 설정했다. 이 단순한 임계값만으로도 패치 전후의 경계를 안정적으로 잡을 수 있었다.
실무 파이프라인, 최소한의 뼈대
기술 스택은 환경에 맞게 고르면 된다. 중요한 건 리듬이다. 하루 단위로 데이터가 쌓이고, 주 단위로 모델이 재학습되며, 실시간으로는 보정 계수만 조금씩 흔든다. 작은 팀에서 다음 다섯 단계만 갖춰도 충분히 돌아간다.
수집과 정규화: 레이스와 참가자, 배당, 결과, 시간을 수집해 공통 스키마에 적재한다. 반올림 규칙은 원문 문자열로 함께 저장한다. 탐지와 태깅: 잔차 기반 드리프트 감지로 버전 경계를 라벨링한다. 엔진 패치 추정 날짜를 메모로 남긴다. 학습과 검증: 시간 순서로 학습과 홀드아웃을 나누고, 로그 정규 회귀를 기본으로 μ와 σ를 예측한다. 배포와 모니터링: 예측 요약치와 칼리브레이션 리포트를 대시보드에 띄우고, 임계값을 넘기면 경고를 보낸다. 주기적 리셋: 한 달에 한 번은 전 기간을 다시 학습해 누적 드리프트를 흡수한다.
이 과정 대부분은 가상경마에도 그대로 이식된다. 다만 가상경마는 트랙 길이와 게이트 위치의 구조적 편향이 더 크기 때문에 트랩 번호 효과를 더 세밀하게 쪼개는 편이 좋다. 가상축구와 가상농구는 득점 생성 과정이 이산적이라 기록 대신 득점 수를 타깃으로 삼는다. 링크 함수와 손실만 바꾸면 파이프라인은 동일하다.
엣지 케이스, 예상보다 자주 만난다
동착이 잦은 공급사는 기록 예측이 유난히 어렵다. 반올림의 계단 효과 때문에 분산 추정이 커지기 때문이다. 표시 단위를 상향 샘플링해 노이즈를 주입하는 방식으로 부드럽게 만들 수 있다. 예를 들어 0.01초 단위라면, 표시 시간에 ±0.005초의 균등잡음을 더해 여러 샘플을 만든 뒤 분포를 적합한다. 이 기법은 칼리브레이션을 크게 해치지 않으면서 계단을 완화한다.
결측도 자주 나온다. 화면 렌더링 실패로 시간만 빠지는 경우, 순위만 남고 시간은 비는 경우가 있다. 이때 레이스 자체를 버리기보다, 동일 레이스 내에서 순위 조건부 분포로 시간을 보간하는 편이 안전하다. 비워두면 편향이 생길 확률이 높다. 물론 보간치에는 라벨을 붙여 학습에서 가중치를 낮게 둔다.
마지막으로 패치 전환기에는 단 몇 시간 사이에도 분포가 두 개 섞인 모양이 된다. 이런 날은 리플레이스먼트 샘플을 늘려야 한다. 즉, 그 시간대 레이스를 학습 세트에 넣지 않거나, 아예 별도 세션으로 분리해 다룬다. 경험상 패치 전후 6시간 정도를 격리하면 대부분의 혼탁이 정리된다.
작은 수학, 큰 차이
배당을 그대로 쓰기보다 수수료와 마진을 가상축구 https://soccerbettonawa.clickn.co.kr/ 걷어낸 암시 확률을 쓰면 모델이 한결 안정된다. 예를 들어 단승 배당이 bi일 때 단순 역수 합이 1을 넘는다. 이를 정규화해 pi = (1/bi) / Σj (1/bj)로 만든다. 그 다음 로지트를 취해 logit(pi) = log(pi) - log(1 - pi)를 피처로 쓴다. 기록의 로그와 이 값이 대체로 선형 관계를 이룬다. 굳이 복잡한 넌리니어 모델로 시작할 필요가 없는 이유다. 트리 모델이 당장은 점수를 올릴 수 있지만, 작은 드리프트에서 과하게 반응하는 경우를 자주 봤다.
대신 계수에 단조 제약을 거는 건 도움이 된다. P가 커질수록 기대 시간이 줄어들어야 한다는 제약은 물리적으로 타당하고, 오버피팅도 줄인다. 확률적 모델에서는 μ가 logit(p)에 대해 단조여야 한다는 제한을 가할 수 있다. 설치형 라이브러리를 쓰기 어렵다면, 피처를 등분위로 나눠 스플라인을 만들고 계수를 누적합 형태로 표현해 강제 단조를 구현할 수 있다.
현장에서 부딪힌 자잘한 팁
개발 환경이 허락한다면 소스 문자열을 그대로 저장하자. 숫자 필드만 저장해 두면 나중에 반올림 규칙이 바뀌었을 때 원복이 안 된다. 시간 파서의 버전도 로그로 남겨 두면 패치 감사가 쉬워진다. 시계열 대시보드에는 평균이나 표준편차 하나만 올리지 말고, 백분위수 선을 같이 그리자. 10, 50, 90 분위수 선은 드리프트의 방향과 모양을 직관적으로 보여 준다. 또 하나, 잔차의 자기상관을 주기적으로 본다. 1차 지연 자기상관이 양수로 커지면 아직 설명되지 않은 구조가 남아 있다는 신호다.
현업 팀에서는 경주 간 간격이 줄어드는 날에 모델 성능이 흔들리는 사례를 겪기도 한다. 공급사 운영 스케줄이 바뀐 날인데, 표면적 이유는 알 수 없어도 데이터에는 흔적이 남는다. 이럴 때는 간격 피처의 중요도가 올라간다. 반대로 간격을 피처에 넣지 않았는데도 갑자기 성능이 개선됐다면, 다른 피처가 간격을 우회적으로 흡수하고 있을 가능성이 있다. 피처 상관을 점검해 중복을 줄이는 게 낫다.
책임 있는 활용과 한계 인식
가상개경주, 가상경마, 가상축구, 가상농구 같은 가상 종목은 본질적으로 RNG 환경이다. 모델이 포착한 편향은 금방 사라질 수 있고, 특정 구간에서만 통한다. 특히 기록 예측은 수치가 단순해 보인다는 이유로 오해를 부르기 쉽다. 표면의 MAE가 0.04초로 낮아도, 실제 의사결정에서 의미 있는 차이가 아닐 수 있다. 실거래나 실시간 의사결정에 연결하기 전, 거래 비용과 슬리피지, 시장 노출 시간을 포함한 백테스트를 최소 수천 회 시뮬레이션해야 한다. 성과가 특정 시간대나 세션에만 집중돼 있다면 과최적화일 가능성이 높다.
그리고 무엇보다, 공급사의 룰 변경은 예고 없이 온다. 버전 태그 탐지는 사후적이다. 사전 경고 체계를 만들려면 잔차 분포의 이상 감지와 함께, 배당 분포 자체의 변화율도 모니터링해야 한다. 두 신호가 함께 흔들릴 때를 최우선 경고로 올려두면 대응 시간을 벌 수 있다. 결국 기록 예측은 한 번 만든 뒤 방치하는 모델이 아니라, 꾸준히 손을 대야 살아남는 모델이다.
마무리 관찰
가상개경주 기록 예측은 확률과 공학이 만나는 흥미로운 접점이다. 연속형 타깃을 배당과 엮어 다루는 감각을 익히면 다른 가상 종목으로의 확장도 빨라진다. 가상경마에서는 게이트 위치와 주로 타입이, 가상축구와 가상농구에서는 득점 생성의 이산성이 각각 추가로 등장하지만, 암시 확률을 물리량의 패널티로 바꾸고, 그에 대한 단조 제약을 두며, 시간 순서 검증을 지키는 원칙은 그대로 통한다. 무엇이 바뀌고 무엇이 고정돼 있는지, 작은 차이를 꾸준히 기록하는 팀이 결국 더 좋은 모델을 가진다. 처음에는 느리고 답답하겠지만, 3개월만 지나면 그래프가 말을 걸어 온다. 0.01초의 진동에서 의미를 읽어내는 일, 그게 이 일의 재미다.