1편 : https://taksw222.tistory.com/235
지난번 1편에서는 간단한 EDA 등을 진행하였습니다. 이번에는 그러면 예측 시도를 하겠습니다.
문제의 간략화 및 정확한 정의
우선 1:1 대결에서 두 플레이어간의 실력차가 클 경우 상수, 하수의 플레이 패턴이 달라질 것입니다. 따라서 레이팅 격차가 큰 경기들에 대해서는 정확한 예측을 방해할 수도 있어서 데이터에서 제외하겠습니다.
다음, chess.com에서는 모드별, 시간제한에 따라서 레이팅이 모두 다르게 산출됩니다. 즉 여러 시간 모드가 혼재되어 있으면 정확한 등급을 산정하기 어려울 것입니다. 또한 제한시간이 다르다면 당연히 고민의 깊이도 달라질 것이기에 정확한 등급 산출에 어려움이 있을 것입니다.
https://www.youtube.com/watch?v=rs5QPKqKIpg
이런 천상계급의 매치업에서는 1분 제한시간으로도 체스를 잘 두겠지만, 당연히 제한시간이 긴 체스 경기들과는 퀄리티 차이가 나겠죠. 아마추어 랭크라면 더더욱요. 따라서 모드를 하나로 한정하겠습니다.
문제 재정의 결과
블리츠 모드 제한시간 300초 경기를 대상으로, 흑백의 레이팅을 예측한다. 단 흑과 백의 레이팅 구간대는 동일하다.
* 레이팅 구간 분류는 1편 참조
약 7000개의 경기 결과를 얻게 됩니다. 또 추가로 고려할 사항은 다음과 같습니다.
체스의 엔드게임은 어느 정도 패턴이 있습니다. 메이트 패턴은 따로 공부해야 할 정도고요. 그거 외에도 어느정도 기물의 수가 줄어들면 형세 판단이 쉽게 됩니다. 즉 이미 어느정도 중반전까지로 실력 측정의 "각"은 나온다는 것입니다. 물론 엔드게임을 못해서 이 사람의 실제 레이팅이 낮을 수 있겠지만, 모든 수를 다 보기가 어렵습니다. 실제로 전처리 전, 6만건 정도의 체스 경기의 수의 분포를 확인해보면 다음과 같습니다.
보시다시피 흑백 번갈아가며 100번, 즉 "50수"를 넘어가는 경우가 드뭅니다. 따라서 흑백 번갈아 가며 70번 정도를 보면 절반 정도 이상의 경기에서 100%를 본 것이고 대부분의 경기에는 60~70% 정도는 본 것이므로 레이팅 판별에 문제가 없다고 판단하겠습니다. 모든 로그를 다 보기에는 리소스 문제도 있어서 적당히 자르는것도 필요할 것입니다.
평가 지표의 설정
예측 모델을 만들 것인데 평가는 어떻게 해야할까요. 분류문제니까 marco-f1이라도 가져가야 할까요?
하지만 한번 생각해봅시다. 에를들어 레벨 5 정도인 유저를 4나 6으로 생각하는 것과, 2나 8로 생각하는 것, 이 두가지를 같은 정도의 오류라고 볼 수 있을까요? 단순한 분류 오차 지표들로는 이 차이를 논하는 것이 곤란할 것입니다. 비록 분류 문제지만, 이 문제에서는 오차를 크게 분류한 것에 대해 페널티를 주기 위한 지표를 쓸 것입니다.
MAE를 계산하면 제가 만든 모델이 평균 몇 등급 정도를 틀리고 있는지를 알 수 있게 될 것입니다. 이를 지표로 하여 예측 모델을 정말 만들어봅시다.
그럼, 대체 예측은 어떻게 해야할까?
수를 보고 등급을 맞히는 것이 아니라면..? 사실 체스 판에서 둘 수 있는 수들은 한정되어 있습니다. 한정된 패턴 내에서 유사한 패턴을 보이다면 비슷한 등급이지 않을까? 생각할 수 있습니다... 그렇다면?
네, 이 문제는 자연어 처리의 방법론으로 도전이 가능합니다.! 상상도 못할 정도는 아니지만, 기존의 다른 도구를 가져다가 쓸 수 있습니다! 여기서는 체스판에서 움직일 수 있는 수가 어휘 목록이 됩니다. 그리고 각 수를 벡터화 시켜서 예측모델을 만들어 볼 수 있겠네요.
가장 쉬운 방법부터
가장 쉬운 생각은 비슷한 등급이면 특정 패턴에 같은 대응을 보일 것이라고 가정, 빈도수로 예측을 해보겠습니다.
빈도수로 단어 벡터화를 해야 한다? CounterVectorizer!
결과는 어떨까요?
평균 오차는 거의 2등급 정도입니다.! 너무 오차가 크네요, 좋은 예측을 해주지 못하고 있는 것으로 보입니다. 무엇을 놓친 걸까요?
수읽기를 반영하는 방법
체스는 수읽기 게임입니다. 나의 수에 따라 상대가 어떤 수를 두면 그 다음에 나는 어떻게 할지, 최소 나-너-나 로 연결되는 수 계산이 있어야 유의미한 게임이 될 것입니다. 상대의 대응을 예측하여 이에 대응하는 것이 중요하므로 단순히 수 하나 하나만 세서는 "대응"을 고려할 수 없습니다 .즉 연달아서 나온 수들의 묶음을 세야 합니다. "이웃한 것들을 묶는 법"이 NLP에 있었습니다... N-gram 입니다! N-gram을 적용해봅시다.
이럴수가, 모델 개선이 이뤄지지 않았습니다! 모델 최적화를 한다고 해도 유의미한 결과를 줄 거 같지는 않습니다. 무엇이 문제였을까요?
사실 단순히 CountVectorizer만 하면 "그 수를 언제 두었는가?"라던가, "진짜 유사도"를 알기는 어렵습니다. 게다가 행렬이 너무 sparse합니다. 실제로 사이즈를 재보면, 거의 몇만단위 * 7000 정도의 행렬이 나옵니다. 그렇다면 유사도를 계산해줘야 겠죠?
유사도 계산의 시도
앞에서 말한 것처럼 CountVectorizer한 행렬이 너무 크면 실 결과를 확인하기 어려울 것입니다. 따라서 N-gram을 3만 보는 것으로 줄이는 대신 유사도를 계산할 것입니다.
CountVectorizer 된 행렬을 기반으로 하나의 경기와 train set에 있는 경기들의 유사도를 계산하여 최대 10개의 경기를 선정합니다. 이 때 내적값이 0이 넘어가는 것들만 가져와서 자체 커트라인을 잡았습니다. 굳이 너무 유사하지 않은 경기를 억지로 넣을 필요는 없으니까요. 예측이 잘 될 리도 없고요.
내적값이 0보다 큰 경기가 없을 경우 평균레벨인 6을, 아닐 경우는 선정된 최대 10개의 경기의 평균 레벨을 산출하겠습니다.
문제는 이렇게 설계하니 N-gram 3으로 줄여도 계산시간이 너무 오래걸립니다. 또 여전히 수의 순서에 대해서는 고려하지 않은 점이 부족합니다. 그래도 어느정도 결과를 확인하기 위해 test date의 맨 앞 20개의 데이터로 예측 결과를 확인해 본 결과 오차 평균이 1.48등급 정도로 어느정도 상향은 이루었지만, 조금 더 줄여보고 싶습니다. 다른 대안들은 없을까요?
수의 의미를 반영하다, Word2Vec
의미를 반영하는 단어 벡터화인 Word2Vec을 사용하면 좀 더 좋은, 벡터화가 가능할까요?
e4와 가장 유사한 수로 d4를 골랐습니다. 그 뒤의 수가 조금 의아하지만, Nf3도 보이고요. 오프닝에 주로 선택되는 수들이 많이 보입니다. e4의 대표 대응수인 e5도 보입니다. 확실히 맥락을 적극적으로 반영할 수 있는 Word2Vec이 유의미한 벡터화를 보이고 있습니다.
캐슬링의 경우도 퀸사이드 캐슬링의 가장 유사한 수를 킹사이드로 해석해주고 있습니다. 유사한 수나 맥락을 어느정도 파악하고 있는 것으로 보입니다.
문제는...
Word2Vec을 사용한 순간, 이제 딥러닝의 방법론으로 사용하는 것이 가장 적절할 것입니다. 아직 솔직하게 저는 딥러닝 방법론쪽의 사용이 익숙하지 않아 현재 이 이후의 실제 모델링에서 고전하고 있습니다. RNN이나 LSTM에 대해 조금 더 명백한 이해를 가지게 되고 모델 코드 및 결과를 보여드릴 수 있을 때 다시 찾아와 최종 완성이 될 것 같습니다. 현재로서는 여기까지로 하고, 방법론들을 차근차근 공부하기로 결정했습니다.
'Archive > Playground' 카테고리의 다른 글
[Playground] 이직 예측 모델 만들기 (2) (1) | 2024.02.16 |
---|---|
[Playground] 이직 예측 모델 만들기 (1) (1) | 2024.02.14 |
[Playground] 너의 레이팅이 보여 (1) 도입, 데이터 탐색 (1) | 2024.01.26 |