第一次结对编程作业

问题重述与分析

问题重述

最终的黄金点比赛会进行10000轮。每轮比赛中共有 $N$ 位玩家参与,每个玩家要在 5s 内提交两个数,系统会将所有数作平均并乘0.618得到一个黄金点。提交数字最接近黄金点的玩家得 N 分,距离最远的 -2 分,其余玩家得分不变。目标是让累计得分尽量高。

问题分析

我们认为策略驱动模型更适合这个任务,而不是数据驱动。即根据历史数据从若干个给定策略中挑选一个作为回答,而不是直接去回归黄金点。比起直接回归策略,策略驱动的方法 action 空间更小,学习起来要简单一些。而至于用于策略选择的模型,我们尝试采用了 DQN(虽然两人都没怎么接触过,但这不失为一次学习的机会)。

Bot 算法设计

算法描述

我们的 Bot 是基于老师给的 RLDemo 修改的。

Action 空间 RLDemo 中给定了 8 个 action,其中前七个都是根据固定策略生成两个相同的数。我们觉得这样做有些“浪费”,因为若可以提交两个数,提交两个不同的数要更保险一些。我们便将前七个策略两两组合,再加上第八个策略,构成了一个大小为 C(7, 2) + 1 = 22 的 Action 空间。

State 我们简单地采用前十个黄金点组成的 10 维向量作为 State。

我们设计了一个简单的三层网络作为 DQN 的模型

class DQN(nn.Module):

    def __init__(self, state_size, action_size, mid_dim=128):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(state_size, mid_dim),
            nn.ReLU(inplace=True),
            nn.Linear(mid_dim, mid_dim),
            nn.ReLU(inplace=True),
            nn.Linear(mid_dim, action_size)
        )

    def forward(self, x):
        return self.net(x)

一个 DQN 实例 model 即对应着 Q-learning 中的 Q-Table。model(state)[action_id] 即可得到状态为 state,策略为 action_id 的 Q 值。

我们采用在线的方式训练模型。在前期数据量不足时,我们使用随机选取 Action 的策略;当数据量丰富后,我们以一定的概率决定应该采用 DQN 还是随机选取策略。若使用 DQN,我们会先从历史数据中选取一个 batch 对 DQN 做一次训练,再 eval DQN 得到预测的策略。

流程图

动机

其实我们并没有特别明确的动机,一方面我们需要一个较大的策略空间,另一方面我们需要一个不算太简单的策略选择机制。以上的模型是我们尝试的结果。

结果分析

在比赛前我们将我们的 Bot 和若干非深度策略的 Bot (固定策略,RLDemo 等) 放在一起比赛。在比赛时我们发现一个现象,即当我们的 Bot 使用深度策略时,总是倾向于连续选择同一个策略。但从得分来看,1000轮下来我们可以比其他 Bot 领先一大截,就没有做进一步的修改。

正式比赛时,在第一轮中我们取得了第三名的成绩。这其实是超出了我们的预期的,毕竟之前我们只是战胜了策略简单的 Bot。这也导致我们在第一轮结束后没有做进一步的改进。但第二次的结果就不太如意了,我们位列倒数第一,看起来经过一夜的改进对手的策略都增强了许多。

其实事后想想,全连接的模型还是不太适合这个游戏。当房间里的 Bot 都以一定的策略行动时,黄金点不能说是毫无规律。因此采用 RNN 可能会更好。当然,我们所选的 Action 空间的合理性也有待商榷。

我们 Action 的选择其实是和可提交的数耦合的,因此若增加可提交的数字,我们就得重新设计 Action 空间。

对伙伴的评价

我的合作伙伴是涂涵越。其实在比赛之前我们两人都有很多工作要做,而我则在比赛期间回了学校一趟。我们只是用了一个下午商量了一下并做了一个简单的 Demo,稍微测试了一下便去和固定策略的 Bot 对战。之后细节的完善是队友完成的。感觉队友思维很活跃,可以适时提出想法,同时也有很强的代码能力。

posted @ 2019-09-21 15:00  hsfzxjy  阅读(139)  评论(1编辑  收藏  举报