Прогнозируемый результат - NaN на карточной игре RL DQN - PullRequest
0 голосов
/ 08 октября 2019

Я пытаюсь создать учебный проект для популярной португальской карточной игры. У меня работает среда. Код может выполняться самостоятельно, за n раундов, используя случайные выборки.

Для быстрого объяснения игра похожа на Hearts. В нем 4 игрока в 2 командах. У каждого игрока по 10 карт, играя по возможности, пока не осталось карт. Каждый трюк зарабатывает очки, после 10 трюков команда с более чем 60 очками выигрывает раунд.

Во-первых, у меня были некоторые сомнения относительно того, как «кодировать» карты / колоду. Я передаю модели карты на столе, карты на руках и уже играли в карты. Я однозначно закодировал колоду, 4 масти, 10 цифр / цифр. Я также должен включить козырь (взят с начала раунда). Таким образом, в качестве примера 1 карта выглядит следующим образом: [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], где первые четыре числа соответствуют масти, ипоследняя является козырной (булевой), а остальная - какая карта (2, 3, 4, 5, 6, j, q, k, 7, a). Я передаю колоду для каждой руки, стола, сыгранной, так что 40 * 3, 15 фишек для каждой (1800 фишек при сглаживании). Возможно, это не лучший подход, если кто-то мог бы посоветовать это было бы здорово.

С этими данными я устанавливаю 1 игрока в качестве агента ИИ. Когда наступает очередь ИИ, состояние - это карты в руке, карты на столе, игральные карты. Для следующего состояния я прохожу трюк с данными того же типа. Награда от этого трюка является совокупной величиной (максимум 120 баллов). Когда я запускаю код, потеря выводит значение вначале, как в первый раз, затем отображает NaN. Так что прогнозы выходят также как NaN (у меня есть 10 выходов, по 1 на каждую карту в руке. Также есть некоторые сомнения по этому поводу, потому что они начинаются с 10 карт, но по ходу игры и разыгрывания карт это число переходит кноль.)

Вот код для обучения:

async expReplay() {
    console.debug('Training...')
    const minibatch = await this.memory.concat().sort(() => .5 - Math.random()).slice(0, this.batchSize)

    for (let i = 0; i < minibatch.length - 1; i++) {
        let [state, action, reward, next_state, done] = minibatch[i]

        state = await tf.concat(state).flatten().reshape([1, this.stateSize])
        next_state = await tf.concat(next_state).flatten().reshape([1, this.stateSize])
        let target = reward

        if (!done) {
            let predictNext = await this.model.predict(next_state)
            target = reward + this.gamma * predictNext.argMax().dataSync()[0]
        }
        let target_f = await this.model.predict(state).dataSync()

        target_f[action] = target
        target_f = await tf.tensor2d(target_f, [1, this.actionSize])
        await this.model.fit(state, target_f, {
            epochs: 1,
            verbose: 1,
            callbacks: {
                onEpochEnd: (epoch, logs) => {
                    process.stdout.write(`${logs.loss} ${logs.acc}                             \r`)
                }
            }
        })

        await state.dispose()
        await next_state.dispose()
        await target_f.dispose()
    }
    if (this.epsilon > this.epsilonMin) {
        this.epsilon *= this.epsilonDecay
    }
    return 'Training... stop!'
}

Этот цикл, который я использовал ранее, на DQN также для трейдера Биткойн, я экспериментировал, и он работал нормально,Так что я предполагаю, что мои данные где-то не так. Я зарегистрировал состояние и next_state для проверки на NaN, но не обнаружил ...

Если вам нужна дополнительная информация, пожалуйста, спросите!

...