
Projekt:Chess Style Classifier – czy algorytm rozpozna mistrza po stylu gry?
Narzędzia: Python, scikit-learn, Stockfish, python-chess, Supabase (PostgreSQL), GitHub Actions, GitHub Pages, JavaScript (chessboard.js, Chart.js)
Opis: Projekt ML sprawdzający, czy algorytm potrafi rozpoznać arcymistrza po stylu gry. Model analizuje partie z Chess.com przy użyciu Stockfisha i wyznacza prawdopodobieństwo przynależności każdego ruchu do konkretnego gracza.
Cel: Klasyfikacja stylu gry przy użyciu uczenia maszynowego
Dane: Chess.com API – partie Magnus Carlsen i Hikaru Nakamura
Repozytorium:
Zobacz na GitHub
Wprowadzenie
Interesowało mnie, czy styl gry szachowej da się zmierzyć – nie intuicyjnie, ale liczbowo. Magnus Carlsen i Hikaru Nakamura to gracze o bardzo różnych podejściach do partii: jeden znany z pozycyjnej precyzji, drugi ze spektakularnego stylu i agresywnego tempa. Pytanie brzmiało: czy Random Forest wytrenowany na ich partiach będzie w stanie to uchwycić?
Dane
Partie pobieram automatycznie z publicznego API Chess.com – miesięczne archiwa dla obu graczy. Każda partia to PGN (Portable Game Notation), z którego wyciągałam cechy opisujące zachowanie gracza: długość partii, liczbę bić i szachów, typ roszady, kategorię czasową (bullet / blitz / rapid), kod otwarcia ECO.
Dane trafiają do bazy Supabase (PostgreSQL) i są odświeżane automatycznie co tydzień przez GitHub Actions.
Proces
1) Cechy heurystyczne (52% dokładności)
- Pierwsza wersja klasyfikatora pracowała wyłącznie na cechach wyciągniętych z PGN. Wynik 52% to niemal rzut monetą model nie miał czym się różnicować.
2) Analiza silnikiem szachowym
- Kluczową decyzją było dodanie analizy Stockfishem. Dla każdej partii i każdego ruchu gracza silnik oblicza:
- ACPL (Average Centipawn Loss) – miara precyzji
- odsetek najlepszych ruchów (best move rate)
- wskaźniki niedokładności, błędów i poważnych błędów
- wskaźnik ofiar – ruch, który oddaje materiał, ale jest oceniany przez silnik jako dobry
- Te cechy są z natury znacznie bardziej informacyjne niż sama struktura parti
3) Klasyfikator
- Random Forest na 21 cechach. Dokładność wzrosła do ~70%. Model trenuje się na nowo przy każdym cotygodniowym uruchomieniu workflowu.
4) Prawdopodobieństwa ruch po ruchu
- Zamiast klasyfikować całą partię, klasyfikuję każdy ruch z narastającymi statystykami. Wynik to sekwencja prawdopodobieństw zapisana jako JSONB w bazie – jeden wiersz na partię zamiast jednego wiersza na ruch.
Wyniki
Frontend pokazuje:
- karty statystyk obu graczy
- wykres radarowy porównujący style
- odtwarzacz partii z szachownicą
- animowany pasek prawdopodobieństwa zmieniający się z każdym ruchem
Strona ładuje dane bezpośrednio z Supabase przez klienta JS.
Wyzwania
- Największym wyzwaniem nie była budowa modelu, tylko zarządzanie czasem analizy silnikiem. Stockfish analizuje pozycję przed i po każdym ruchu — dla 1000 partii to kilkadziesiąt minut pracy. Rozwiązaniem było obliczanie inkrementalne: każdy nowy tydzień analizuje tylko nowe partie.
- Drugi problem to rozmiar bazy (plan darmowy Supabase ma limit 500 MB) — rozwiązany przez limitowanie liczby przechowywanych partii na gracza i usuwanie najstarszych przy przekroczeniu progu.
Strona ładuje dane bezpośrednio z Supabase przez klienta JS.
Refleksja
- 70% dokładności przy dwóch graczach to wynik skromny, ale uczciwy – model naprawdę się uczy, nie zapamiętuje. Gdyby dodać więcej graczy o wyraźnie różnych stylach, klasyfikacja prawdopodobnie by się poprawiła. Na razie projekt odpowiada na pytanie, które zadałam: tak, styl gry da się zmierzyć. Przynajmniej częściowo.
Ciasteczko do kawy?