好的,所以我使用与 DeepMind 的 Atari 算法相同的想法创建了一个神经网络 Q-learner(除了我提供原始数据而不是图片(还))。
神经网络构建:
9 个输入(0 表示空白点,1 表示“X”,-1 表示“O”)
1 个具有 9-50 个神经元的隐藏层(尝试不同大小,激活函数 sigmoid)
9 个输出(每个动作 1 个,输出 Q 值,激活函数 sigmoid)
- MSE 损失函数
- 亚当反向传播
由于梯度检查和大量测试,我 100% 确信网络是正确构建的。
Q 参数:
- -1 输掉比赛的奖励
- 如果尝试移动到已经占据的位置,则 -1 奖励(例如,X 已经在玩家 O 尝试放置“O”的位置)
- 0 抽奖奖励
- 0 奖励移动,不会导致终止状态
- +1 获胜游戏奖励
- 下一个状态(在 s,a,r,s' 中)是您自己和对手移动之后的状态。例如,空棋盘和玩家 X 先转牌并将“X”放在左上角。然后玩家O把“O”放在右上角。那么 s,a,r,s' 将是 s = [0,0,0,0,0,0,0,0,0], a = 0, r = 0, s' = [1,0,- 1,0,0,0,0,0,0]
问题
如果我在移动到已经占据的位置时给予 -1 奖励,我所有的 Q 值都会归零。如果我不这样做,网络就不会知道它不应该移动到已经被占用的地方,并且似乎学习任意 Q 值。我的错误似乎也没有缩小。
无效的解决方案
我试图将奖励更改为 (0, 0.5, 1) 和 (0, 1) 但它仍然没有学习。
我试图将状态显示为 0 表示空,0.5 表示 O,1 表示 X,但没有奏效。
我试图在移动后立即给出下一个状态,但它没有帮助。
我试过用 Adam 和 vanilla back prop,但结果还是一样。
- 我已经尝试过重放内存和随机梯度下降的批次,但仍然相同
- 将 sigmoid 更改为 ReLU 但没有帮助。
- 各种现在想不起来的事
GitHub 中的项目:https ://github.com/Dopet/tic-tac-toe (对于丑陋的代码很抱歉,主要是由于所有这些代码重构,这应该很容易测试以查看算法是否有效)
要点:
- TicTac 类具有游戏本身(使用抽象 Game 类的模板方法模式制作)
- NeuralNetwork 类将一些数据记录到当前目录中名为 MyLogFile.log 的文件中
- Block 和 Combo 类仅用于创建获胜情况
- jblas-1.2.4.jar 包含 DoubleMatrix 库