← На главную Воспоминания

Как я учил нейросеть в дудл джамп играть (Попытка 1)

Недавно пришла ко мне одна идея. Что если попробовать обучить нейросеть использовать класификацию чтобы научить ее играть в дудл джамп. Идея была такая: поиграть в игру самому, делая скриншоты игры и называя скриншот также как и нажатая в данный момент клавиша. Для простоты обошелся клавишами Влево, Вправа и ничего не нажимать. Далее нагенерировал много таких картинок используя браузер и плейрайт, загрузил в конволюш нейронную сеть, сделал модельку и сделал такой же метод для плейрайта чтобы он нажимал то что предсказывает модель.

Далее я приведу код. Кроме данные, получилось 2 файла: main.py и train.ipynb

чтобы код сработал нужно установить playwright и fastai

pip install playwright fastai

main.py

import uuid
from playwright.sync_api import sync_playwright
from fastai.vision.all import *

def train():
    with sync_playwright() as p:
        browser = p.webkit.launch(headless=False)
        page = browser.new_page(viewport=None)
        page.goto("https://doodlejumporiginal.com/")
        page.evaluate("""
document.addEventListener('keyup', e => {
    document.pressed = null
    console.log(e)
})

document.addEventListener('keyup', e => {
    document.pressed = e.key
})
                      """)
        loc = page.locator("canvas")
        while True:
            button = page.evaluate("document.pressed")
            loc.screenshot(
                path="./screenshots/"+ str(button) + "_"+ str(uuid.uuid4()) +".png",
                caret="initial",
                scale="css",
                animations="allow",
                quality=3,
                type="jpeg", 
            )

def make_label(x): return (x.split("_"))[0] 

def play():
    learn_inf = load_learner('model.pkl', cpu=True)
    with sync_playwright() as p:
        browser = p.webkit.launch(headless=False)
        page = browser.new_page(viewport=None)
        page.goto("https://doodlejumporiginal.com/")
        loc = page.locator("canvas")
        key = "Backquote"
        while True:
            scr = "./screenshotsVal/"+ str(uuid.uuid4()) +".png"
            loc.screenshot(
                path=scr,
                caret="initial",
                scale="css",
                animations="allow",
                quality=3,
                type="jpeg", 
            )
            key = learn_inf.predict(scr)
            key = key[0]
            print(key)
            if(key == "None"):
                key = "Backquote"
            key = key + "+"
            page.keyboard.press(key*200 + "Backquote")


play()
# or train() to generate screenshots for training

train - генерировал скриншоты для последующего обучения модели play - играл в дудл джамп. Нужно нажать на плей в открывшемся браузере чтобы игра началась

Последовательность такая:

Ноутбук для обучения выглядел так:

train.ipynb

from fastai.vision.all import *

# prepare data
def make_label(x): return (x.split("_"))[0] 

dls = ImageDataLoaders.from_name_func('.',
        get_image_files("screenshots"), valid_pct=0.2, seed=42,
        label_func=make_label,
        item_tfms=Resize(192)
    )

dls.train.show_batch(max_n=4, nrows=1, unique=True)

# fine tune model
learn = vision_learner(dls, resnet18, metrics=error_rate)
learn.fine_tune(3)

# export model
learn.export('model.pkl')

# see confusion matrix
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()

Запустив игру, найлучший результат который получился это чуть больше трех тысяч очков, что довольно плохо.

Какие выводы я вынес

Нейросеть классифицировала текущих ход, однако это не лучший следующий ход. В какой-то момент она поняла что если дудл носом повернут вправо, то это Правая категория, если влево, то Левая. И начал прыгать только вправо или только влево. Следующим шагом можно будет подумать, какую класификацию или метрику придумать чтобы она означала лучший следующий ход. Также нужно придумать как указать сколько раз нажимать влево или право. Одиночное нажатие сдвигает дудла на пару пикселей. По умолчанию я захордкодил 200 нажатий

Видео игры