蒙特卡洛树搜索不起作用

我目前正在为棋盘游戏Hex编写人工智能。我希望使用蒙特卡洛树搜索来实现这一点,并且已经尝试过实现它。然而,人工智能做出了令人难以置信的愚蠢(随机)移动,我无法弄清楚为什么它不起作用。

import java.util.ArrayList;import java.util.Random;/** * Created by Robin on 18.03.2017. */public class TreeNode {    private static final Random random = new Random();    private static final double epsion=10e-5;    protected double nvisits;    protected double totValue;    protected int move=-1;    private HexBoard board;    protected ArrayList<TreeNode>children ;    public TreeNode(HexBoard board){        this.board =board;    }    //Copy-Constructor    public TreeNode(TreeNode treeNode){        this.nvisits=treeNode.nvisits;        this.totValue=treeNode.totValue;        this.move=treeNode.move;        this.board = new HexBoard(treeNode.board);    }    public void update(double value){        totValue+=value*board.color;        nvisits++;    }    public void expand(){        assert(children==null);        children = new ArrayList<>(121-board.moveCount);        for(int i=0;i<121;i++){            if(board.board[i]!=HexBoard.EMPTY)                continue;                TreeNode newNode = new TreeNode(board);                newNode.move =i;                children.add(newNode);        }    }    public void calculateIteration(){        ArrayList<TreeNode>visited = new ArrayList<>();        TreeNode current =this;        visited.add(current);        while(!current.isLeafNode()){            current =current.select();            board.makeMove(current.move);            visited.add(current);        }        //Found a leaf node        double value;        if(current.board.getWinner()==0){            current.expand();            TreeNode newNode =current.select();            value =playOut(newNode.board);        }else{            value =current.board.getWinner();        }        //update all the nodes        for(int i=1;i<visited.size();i++){            visited.get(i).update(value);            board.undoMove(visited.get(i).move);        }        visited.get(0).update(value);    }    public static int playOut(HexBoard board){        int winner=0;        if(board.moveCount==121) {            winner=board.getWinner();            return winner;        }        //Checking-Movecount vs actual stones on the board        final double left =121-board.moveCount;        double probibility =1/left;        double summe =0;        double p =random.nextDouble();        int randomMove =0;        for(int i=0;i<121;i++){            if(board.board[i]!=HexBoard.EMPTY)                continue;            summe+=probibility;            if(p<=summe && probibility!=0) {                randomMove = i;                break;            }        }        board.makeMove(randomMove);        winner =playOut(board);        board.undoMove(randomMove);        return winner;    }    public TreeNode select(){        TreeNode bestNode=null;        double bestValue =-10000000;        for(TreeNode node : children){            double uctvalue =(node.nvisits==0)?100000:(node.totValue/(node.nvisits)+Math.sqrt((Math.log(this.nvisits))/(2*node.nvisits)));            uctvalue+=epsion*random.nextDouble();            if(uctvalue>bestValue){                bestValue=uctvalue;                bestNode =node;            }        }        return bestNode;        ///    }    public boolean isLeafNode(){        return (children==null);    }}

我在calculateIteration()方法中的实现是否正确?

我知道这可能不是一个很吸引人的问题,但我会很感激任何帮助。


回答:

原帖作者在评论中添加了额外信息。这些额外信息的重要部分是makeMove()方法被实现为检查下一个要玩的玩家(以确保对棋盘的更新是正确的)。

鉴于这些信息,原帖作者在select()方法中的实现是不正确的,因为它在计算UCT分数时没有考虑到下一个要移动的玩家。UCT分数由“利用”部分(第一个分数,计算所有先前模拟的平均分数)和“探索”部分(平方根下的部分,对于相对于其父节点访问较少的节点会增加)组成。当对手下一步可以移动时,这个方程的利用部分应该被否定。如果不这样做,人工智能将基本上假设对手愿意主动帮助人工智能,而不是假设对手会为自己争取胜利。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注