问题重述与分析
问题重述
最终的黄金点比赛会进行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 对战。之后细节的完善是队友完成的。感觉队友思维很活跃,可以适时提出想法,同时也有很强的代码能力。