저는 일년에 한두번씩 데이트를 하러 가거나 친구들끼리 놀기위해 경마장을 가곤합니다.
(걱정 마세요~ 현금 3~5만원 정도 들고가서 놀이공원 입장료라고 생각하고 즐깁니다. 과도한 금액은 가정을 파괴합니다.)
경마장을 가보신분들은 알겠지만 경마장에 들어갈 때 필수로 구매해야 하는것이 존재합니다.
바로 경마지이죠.
경마지에는 그날의 경기별로 엄청나게 많은 데이터가 적혀있습니다.
정말 세세하죠.
훈련사의 훈련평부터 해당 말의 과거기록은 당연하고, 몸무게 변화량, 과거경기의 상태 등등 정말 나열할 수 없을 만큼 많은 정보가 있습니다.
또 재미난것이 잘 달리던 말들은 다음번에도 대부분 잘 달리더라구요.
동물의 세계에서 서열이 존재하는것인지..
서로 경주를 했던 말들이 또 만나서 경주를 하면 그전에 이겼던말이 높은확률로 또 이기곤합니다.
(물론 항상 그렇진 않습니다. 그러니까 도박이겠죠)
그래서 경마장에 가보면 엄청난 학구열을 가진 아저씨와 아줌마들이 경마지를 두세개씩 들고 자신만의 분석을 해가며 엄청난 공부를 하는 풍경을 보게됩니다.
(정말 학구열이라는 표현이 맞을 정도로 엄청난 집중력으로 싸인팬으로 공부를 하고있습니다.)
과거 저는 데이터는 충분하니 데이터만 잘 모으면 통계학적으로 접근이 가능하지 않을까? 라는 생각을 하였고
'언젠가 시간이 나면 만들어봐야지~' 라는 생각을 한 채 시간이 꽤나 흘렀습니다.
그렇게 기억에서 잊혀질쯤...
2025 설연휴는 정말 길고 긴 휴가였습니다.
딱히 가는곳도 없고 집안에만 있기 적적하여 집중하여 경마 예측프로그램을 만들어 보았습니다.
(매일매일 15시간씩 개발 한것같아요. 오랜만에 너무 재밌어서..)
과거에 저는 ai나 딥러닝, 머신러닝같은 기술이 보편화되지 않았기에 통계학적으로 접근을 하려 했다면,
딥러닝을 공부할겸 딥러닝으로 학습을 시켜보자라는 결론이 나왔고, 먼저 마사회의 API를 모두 살펴보았습니다.
마사회 API는 상당히 많은 정보를 얻을 수 있습니다.
다만 문제가 조금 있었습니다.
겹치는 레거시 API들이 상당히 많이 존재하고
같은 값을 표현는 여러개의 키값이 존재 하거나
하나의 키의 데이터 형식이 다르거나
키값이 무엇을 의미하는지 설명이 잘 안되있다거나
(예를들어 등수는 숫자 1, 혹은 '01' 로 문자열, 특수문자 ① 등등 으로 하나의 키값에 존재합니다..)
꽤나 많은 작업을 거쳐야 이 데이터를 쓸 수 있겠다는 결론이 납니다.
같은 업을 하는 사람으로써 이해는 합니다...
왜냐하면 마사회 API는 놀랍게도 1985년 자료부터 값을 가져올 수 있습니다.
(제가 태어나기 전 부터 데이터를 저장해두었다는 사실에 얼마나 고생했을지 눈에 선합니다. 처음에는 수기로 작성했겠죠?)
저 많은 데이터를 처음부터 데이터 타입을 잘 맞추고 설계를 했다면, 문제가 없었겠지만 엄청 오래된 시스템의 마이그레이션은 상상 초월의 억압을 주곤하죠.
해당 데이터베이스를 거친 얼마나 많은 개발자가 있었을까요.
(그래도 너무 오래됐거나 사용을 안하거나 중복이되는 API들은 관리를 좀 해줬으면 좋겠습니다.)
데이터를 보다보니 너무 과거 데이터는 신뢰성이 좀 떨어지겠다는 느낌이 들었습니다.
그래서 2000년 데이터 부터 사용하자는 결론을 가지고 전처리를 하기 시작했습니다.
말정보, 기수정보, 경기정보, 경기출전마, 경기결과, 말무게정보, 주로별결과정보, 날씨정보, 말의진료정보 등등 10가지 이상의 마사회의 API를 사용하였습니다.
(워낙 API형식도 다르고, 특정 데이터가 없을때도 있고, 여러가지 결측값이 많이 있어서 이 작업만 이틀은 걸린것 같습니다.)
약 80만개의 데이터의 기본적인 전처리를 마쳤습니다.
이제 할 일은 학습을 어떻게 시킬꺼며, 어떤 데이터를 가지고 학습을 시킬까에 대한 고민이 있었습니다.
처음에는 몇가지 논문을 봤습니다.
의외로 경마에 대해 머신러닝이나 통계학적 접근을 하는 논문들이 꽤나 있더군요.
상당히 재밌게 읽었지만 딥러닝에 대한 정보는 찾을 수 가 없었습니다.
저만의 기준으로 중요한 정보라고 생각하는
말의 평균속도 (경기거리/시간), 처음 200m 주파 시간, 마지막 200m~결승선 주파시간, 경기거리, 말의승률, 기수의승률, 말의중량, 부담중량, 말의 성별 등등 꽤나 많은 파라미터를 가지고 학습을 시켜보았습니다.
학습 방법 및 각종 사용한 방법론은 글로 작성하기에 너무 길 수 있으니 이 후 시간이 되면 작성해보도록 해보겠습니다.
학습데이터는 2000~2024년도의 데이터로 학습을 하였습니다.
모델을 검증하기 위해서 2025년도의 데이터를 사용할 예정이었기 때문에 2025년의 데이터도 학습을 시켰을 시 과적합의 문제가 생길 수 도 있다고 판단하였기 때문입니다.
아무래도 데이터베이스에 값을 저장해두었기 때문에 너무 많은양의 데이터를 가져오느라 매번 학습시에 너무 오래걸려서 따로 캐싱 시스템을 만들어서 학습시간을 단축을 시켰습니다.
(그래도 오래걸리더군요..제 아내에게 rtx5090을 사달라고 땡깡을 부려야할 것 같습니다.)
그리하여 2025년 1월 경기들로 대한 예측을 해보았는데..
3등안에 들어갈말 3마리를 고르는 예측율이 60%~65%가 넘게 나오는겁니다.
(3등안에 들어갈 말 3마리를 고른 이유는 경마의 승부는 단승-1등말맞추기, 연승-3등안에들어오는말 하나 맞추기, 삼복승-3등안에들어오는말 3마리맞추기 처럼 대부분 3등안쪽을 맞추는 도박이기 때문입니다.)
처음에는 '와 파라미터를 제대로 잡았나? 이렇게 예측율이 높다고?' 라고 생각했습니다.
그런데 아무리 생각해도 조금 이상했습니다. 너무 예측율이 높았기 때문이죠.
그러다 문제를 찾았습니다.
그 중 하나는
1. 예측대상의 각 종 값은 최근 6개월 경기의 평균으로 잡고있었다.
2. 하필 거기에 예측할 경기의 값도 포함되었다.
3. 과거기록이 없는 신마는 예측할 경기의 값만 평균으로 잡힌다.
4. 사실상 실제경기랑 같은 결과가 나오게 된다.
예측 파라미터설정을 잘못 잡은것이었죠.
이외에도 여러가지 부분을 잡아서 최대한 객관적으로 잡아두고 다시 검증을 했습니다.
바로 33~38%대로 예측율이 떨어졌습니다.
한 경기에 말이 9~14마리 정도 출전을 하니 랜덤으로 골랐다면 약 20%~30% 사이의 값을 보일 수 있습니다.
그것보다는 높으니 어느정도 괜찮은 학습이 되었다고 볼 수 있습니다.
다만 여기서 만족하고 싶지가 않았습니다.
목표는 45%대의 예측율이었습니다.
그래서 경주의 결과와 예측가중치를 따로 살펴보니, 이상하게 실제 전문가들은 높게 쳐준말이 예측치가 너무 낮게 나오는 현상이 있었습니다.
아내와 함께 해당 값을 연구하기 시작했습니다.
아내와 계속 연구를 하며 결국 모델 학습시 사용했던 말의 중량, 말의 중량 증감값(직전경기대비 플러스 마이너스) 등의 말의 무게에 대한 값이 영향을 주고 있다는 결론이 났습니다.
평균속도 -> 높으면좋음
말의 승률 -> 높으면 좋음
말의 부담중량(안장, 기수의 무게등) -> 낮으면 좋음
같은 파라미터는 확실하게 방향성이 있는 수치이지만
말의 중량 -> 높은게 좋은가? 낮은게 좋은가?
말의 무게 증감량 -> 직전경기대비 살이 찐게좋은건가? 마른게좋은건가? 변화가 없는게 좋은건가?
처럼 방향성이 없기 때문이죠.
(물론 어느정도 중간값이 좋다라고 스코어링을 잡고 가는 방법도 있을듯합니다.)
그렇게 여러가지 파라미터에서 방향성이 확실한 파라미터만 남겨두고, 애매한 파라미터(말의나이, 날씨, 습기, 주로상태 등등)는 모두 정리하고 학습을 진행하였습니다. 거기에 조금더 확실한 방향성을 가진 파라미터는 조금 더 추가하여 학습을 진행하였습니다.
그렇게 학습 후 예측을 하니 현재는 원했던 45%~47%의 예측율에 가까워진 상황입니다.
그 이후 어느정도 모델을 잡아서 빠르게 웹으로 볼 수 있는 사이트를 만들었습니다.
모델을 선택하고 특정 날짜를 선택하면, 예측된 값과 실제 경기의 결과를 표현하게 만들었습니다.
예측내에 분홍색은 3등안에 들어온 말, 파란색은 5등내에 들어온말 그외 여러 정보를 더 넣을 예정입니다.
날씨가 풀리면 아내와 함께 경마장에 가서 제가 학습시킨 모델을 통해서 1000원 2000원씩 소액으로 즐기러 가봐야겠습니다.
오랜만에 너무 재미있게 진행한 프로젝트였습니다.
조금 더 예측율을 올리기위해 가끔 시간이 될 때 프로젝트를 열어 파라미터 조정도 하고 재미를 봐야겠습니다.
ps. 경마는 도박입니다. 소액으로 가끔 즐기세요