421. Rock, Paper, Scissors | rock-paper-scissors
感谢大家带来了一场有趣且激动人心的比赛,我从大家的讨论和 Notebooks 中学到了很多。
我的智能体包含一组策略,每个策略都有2个反制策略,并使用 n-gram 树来跟踪比赛中的历史模式。我并没有使用复杂的智能体来构建超级智能体,而是专注于极其简单的策略,例如在 n-gram 加上一些旋转之后,根据我上一次的操作来决定当前的行动。关于在每个步骤中选择哪种策略,随着时间的推移我发现,对智能体进行微小的、渐进的修改所带来的收益,往往不如尝试大量截然不同的实验——虽然很多实验无疾而终,但总有一些会成功。由于本次比赛的各种方法之间存在许多共性,我想重点介绍两个我认为在我的智能体中效果很好的概念。
使用策略自身的 n-gram 搜索来搜索其记录。 这就是代码中 "FollowupTree" 类所做的事情。例如,如果某个策略最近三次预测都错了,我们不只是统计失败的次数,而是查看它在过去出现 1 次、2 次和 3 次预测错误后的表现如何。对于胜负的其他模式也是如此。
多窗口计数。 由于许多智能体可能会使用某种“衰减”或滚动窗口,我尝试通过检查整个滚动窗口计数的集合来找到那个窗口。在代码中,我称之为“权重方案”,它们是使用加权平均返回分数的滚动窗口集合。既然我们可以将“策略”视为动作选择以及命中和未命中的记录,我们就可以使用权重方案将一组策略转换为新的策略集合(下图旨在展示其转换方式)。
当我们把这个技术层层叠加时,智能体似乎能更好地规避检测,并能动态地针对不同的独特对手策略进行打击。但这同时也更容易受到更多随机波动的影响,导致偶尔输掉比赛。

“训练”
我创建了一个 "json_agent",利用历史回合数据来与我的智能体对战。在多窗口计数中,我会向智能体添加一个非常大的窗口集合,使其速度太慢而无法参加实际比赛,然后统计哪些窗口在每场比赛中记录最好。之后我在实际比赛中使用这些窗口。

我学到了很多,并期待在“Hungry Geese”比赛中学习更多。希望在那里也能见到你!