Почему сокращение альфа/бета не влияет на мой алгоритм MiniMax?

Во-первых, я прошу прощения за немного неправильный заголовок, я просто не хотел, чтобы он состоял из 30 слов. Сокращение альфа/бета, которое я реализовал, значительно уменьшило количество оценок, когда я применил его к своей игре TicTacToe, убедитесь сами ниже.

Каждая пара значений оценки измеряется с тем же состоянием игры, что и ввод.

Обрезка или отсутствие обрезки

Проблема возникает, когда я хочу реализовать обрезку шашек, играющих в нейронную сеть, над которой я работал. Что было целью всего этого с самого начала, я просто на скорую руку запустил игру TicTacToe, чтобы поэкспериментировать с MiniMax + Alpha/Beta, поскольку я никогда раньше не имел дело с этими алгоритмами.

Вот такой же эксперимент с NN.

checkers minimax evalsшашки минимакс с обрезкой оценок

Теперь о коде (один из шашек, дайте мне знать, если вы хотите взглянуть на версию TicTacToe, хотя они почти идентичны).

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

Небольшое примечание, чтобы сделать код более понятным.

Доска — это объект, который отслеживает фигуры, доступные ходы, какой сейчас ход, была ли игра выиграна/ничья и т. д.

Move — это объект, который содержит всю информацию, относящуюся к ходам. Когда я создаю клон в качестве первой строки метода, я просто создаю клон данной доски, и конструктор применяет к ней заданный ход.

private double miniMax(Board b, Move m, int depth) {

и

private double alphaBeta(Board b, Move m, int depth, double alpha, double beta) {

начало обоих методов:

Testboard clone = new Testboard(b, m);
    // Making a clone of the board in order to
    // avoid making changes to the original one

    if (clone.isGameOver()) {

        if (clone.getLoser() == null) 
            // It's a draw, evaluation = 0
            return 0;   

        if (clone.getLoser() == Color.BLACK)
            // White (Max) won, evaluation = 1
            return 1;

        // Black (Min) won, evaluation = -1
        return -1;  
    } 

    if (depth == 0) 
        // Reached the end of the search, returning current Evaluation of the board
        return getEvaluation(clone);

Очередное продолжение MiniMax:

    // If it's not game over
    if (clone.getTurn() == Color.WHITE) {

        // It's white's turn (Maxing player)
        double max = -1;
        for (Move move : clone.getMoves()) {
            // For each children node (available moves)
            // Their minimax value is calculated
            double score = miniMax(clone, move, depth-1);
            // Only the highest score is stored
            if (score > max)
                max = score;
        }
        // And is returned
        return max;
    } 

    // It's black's turn (Min player)
    double min = 1;
    for (Move move : clone.getMoves()) {
        // For each children node (available moves)
        // Their minimax value is calculated
        double score = miniMax(clone, move, depth-1);
        // Only the lowest score is stored
        if (score < min)
            min = score;
    }
    // And is returned
    return min;
}

MiniMax с продолжением обрезки Alpha/Beta:

    // If it's not game over
    if (clone.getTurn() == Color.WHITE) {

        // It's white's turn (Maxing player)
        for (Move move : clone.getMoves()) {

            // For each children node (available moves)
            // Their minimax value is calculated                
            double score = alphaBeta(clone, move, depth-1, alpha, beta);

            if (score > alpha)
                // If this score is greater than alpha
                // It is assigned to alpha as the new highest score
                alpha = score;
            if (alpha >= beta)
                // The cycle is interrupted early if the value of alpha equals or is greater than beta
                break;
        }
        // The alpha value is returned
        return alpha;
    } 

    // It's black's turn (Min player)
    for (Move move : clone.getMoves()) {

        // For each children node (available moves)
        // Their minimax value is calculated            
        double score = alphaBeta(clone, move, depth-1, alpha, beta);

        if (score < beta)
            // If this score is lower than beta
            // It is assigned to beta as the new lowest score
            beta = score;
        if (alpha >= beta)
            // The cycle is interrupted early if the value of alpha equals or is greater than beta
            break;
    }
    // The beta value is returned
    return beta;
}

Я честно застрял, и я не уверен, что я мог бы сделать, чтобы попытаться выяснить, что происходит. Я пробовал MiniMax+A/B на нескольких разных, даже случайно сгенерированных нейронных сетях, но я никогда не видел улучшения, когда дело доходит до количества сделанных оценок. Я надеюсь, что кто-то здесь сможет пролить свет на эту ситуацию, спасибо!


person Daniel    schedule 23.03.2017    source источник
comment
Одной из причин может быть порядок перемещения, хотя я сомневаюсь, что он единственный. Если вы попробуете сначала сделать хорошие ходы, будет сокращено намного больше.   -  person maraca    schedule 24.03.2017
comment
@maraca Привет, спасибо за ответ. Ходы упорядочены случайным образом, я провел много экспериментов, и каждый раз количество оценок минимакса с альфа/бета или без них точно такое же. В коде должна быть более важная ошибка. То, что вы предлагаете, иногда может привести к тому, что количество оценок будет одинаковым, но я чувствую, что это не всегда так.   -  person Daniel    schedule 24.03.2017
comment
Какова ваша глубина оценки? Какова ваша стационарная функция оценки для измерения качества доски? Шашки могут быть глубокими; крестики-нолики, не очень. Ваша функция оценки для шашек, по сути, дает 0 на всех досках; и, следовательно, обрезка не происходит.   -  person tucuxi    schedule 24.03.2017
comment
Кажется, что вы оцениваете только выигрыши и проигрыши, никакой реальной функции оценки. Таким образом, если в глубине, которую вы вычисляете, нет выигрыша или проигрыша, вы будете смотреть на все ходы, потому что каждый лист — это ничья (с точки зрения вашей функции оценки).   -  person maraca    schedule 24.03.2017
comment
@tucuxi Привет! Я думаю, вы могли пропустить часть кода, в которой я возвращаю оценку платы, если глубина = 0, проверьте последние несколько строк первого фрагмента кода. Моя функция оценки на данный момент представляет собой просто случайную нейронную сеть, моя цель сейчас — сократить количество выполняемых оценок, прежде чем я начну ее действительно обучать. Я использую глубину 4 на скриншотах выше.   -  person Daniel    schedule 24.03.2017
comment
@maraca Я не уверен, как вы оба говорите одно и то же, проверьте последнюю строку в первом фрагменте кода, я возвращаю текущую оценку доски, если глубина = 0. Подробнее читайте мой комментарий в ответ к тукукси.   -  person Daniel    schedule 24.03.2017
comment
Мы говорим примерно об одном и том же. Если доска всегда оценивается как 0 или случайное число, вам, вероятно, придется смотреть на все ходы. Вы можете попробовать только разницу в шашках в качестве функции оценки и +100 и -100 в качестве выигрыша / проигрыша, и вы сможете обрезать.   -  person maraca    schedule 24.03.2017
comment
@maraca Я не говорю, что вы ошибаетесь, но я абсолютно не понимаю, насколько случайные оценки (детерминированно случайные, сеть не обучена, но всегда будет давать один и тот же ответ при одном и том же вводе) доски лучше или хуже когда дело доходит до того, сколько оценок должен выполнить алгоритм. Я почти уверен, что если бы вы посмотрели на последние, скажем, 100 листовых узлов и их фактическую реальную оценку, они выглядели бы более или менее случайными. И, во всяком случае, я запускал программу много раз, и она никогда не пропускала ни одной оценки, может быть, миллион+, должно быть что-то еще, верно?   -  person Daniel    schedule 24.03.2017
comment
@maraca Я пробовал что-то похожее на то, что вы предложили, и вы правы, сейчас происходит некоторая обрезка. Большое спасибо, если вы хотите напечатать ответ, я приму его.   -  person Daniel    schedule 24.03.2017


Ответы (1)


Спасибо @maraca за то, что помогли мне понять это, я собираюсь ответить сам, поскольку он ответил только комментарием.

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

Я использовал еще не обученную нейронную сеть, которая, по сути, просто выдавала случайные значения, это заставило MiniMax + A / B пройти через все узлы, поскольку не было согласованности с ответами, что, как оказалось, необходимо для обрезки. .

person Daniel    schedule 24.03.2017