当前位置:首页|资讯

复习笔记 Day126 用DDQN解决一个简单的购买问题

作者:间宫_卓司发布时间:2024-08-15

这段时间没怎么更新专栏,倒不是什么事情都没做,只是觉得做的东西都没什么意思,加上强化学习确实很玄学(或者说我的知识水平有限),很多运行出来的结果我都没办法合理解释,所以没什么更新的动力。

从上周开始我打算试试看使用强化学习去解决2020年数学建模比赛的B题,于是我遇到的第一个问题就是去描述水以及食物的购买。我的想法是每次在智能体决定买水或者食物时,在调用一个专门的智能体来判断要买多少水和食物,最终返回的奖励为整局游戏的收益。这样的话,如果动作空间直接采用连续的,那最后就要取整,而且还要编写掩码函数来判断状态是否违背了约束条件,实现起来比较麻烦,而且这个方案听起来就很不靠谱。如果动作空间直接采用离散的话,那就有上万个动作,就更不现实了。

最终,我打算通过把上万个动作拆成若干步只有几个动作的决策过程,具体的实现类似于:选取初始状态为(x,y)=(0,0),动作0:(x,y)保持不变,结算收益,动作1:(x,y)变为(x+1,y),(单步的)奖励为0,如果使用动作后超过了约束条件,则尽量使得状态符合约束条件并结算,动作2:(x,y)变为(x,y+1),描述和1类似,然后算法选择任意一个DQN方法,这里我选择的是DDQN。

为了验证这个方案是可行的,我打算先测试一些简单的例子,于是我先定义了如下环境:假设水的价格/重量为5/3,食物的价格/重量为10/2,资金为10000,负重上限为1200,最终的收益为

f%5Cleft(%20x%2Cy%20%5Cright)%20%3D10000-%5Cleft%7C%20x-150%20%5Cright%7C-%5Cleft%7C%20y-200%20%5Cright%7C

输入为当前水的数量以及食物的数量

输出动作为

动作1:买20箱水

动作2:买10箱水

动作3:买5箱水

动作4:买1箱水

动作5:买20箱食物

动作6:买10箱食物

动作7:买5箱食物

动作8:买1箱食物

动作9:买50箱水

动作10:买50箱食物

动作11:结算

如果购买后超过了约束条件,就按最大的算并结束游戏,除了结算以外,其他的动作收益均为0。

可是最后结果是糟糕的,智能体总会在不断增加试探次数后,忽然陷入什么都不买的摆烂状态,如下图所示

我对这个结果感到很困惑,于是决定先考虑一个简单的情况,可是这个简单的情况仍然出现了这种现象,我调了好久的参数结果都是一样的,于是我上了知乎提问:

https://www.zhihu.com/question/664217058

f%5Cleft(%20x%2Cy%20%5Cright)%20%3D-%5Cleft%7C%20x-150%20%5Cright%7C-%5Cleft%7C%20y-200%20%5Cright%7C,虽然不知道是不是这个奖励函数有助于智能体把游戏继续下去,探索未知的状态这种原因,总之这次这个简单的情况确实可以求得最优了。

可是我同样的修改上面的目标函数后并限制了最大的步数后,智能体在训练结束后总会选择一个很差的解(比如连续五次买一箱水然后结算)或者干脆像之前一样摆烂。

%5Cfrac%7Bx%5E2%2By%5E2%7D%7B2500%7D,我希望通过这种方式让智能体优先选取变动较大的动作。为了避免后者,我加大了buffer_size

这样修改后,运行结果类似于下图

虽然步数还是在不断上升,忽然摆烂的情况仍然存在,但是因为buffer_size的增加,智能体仍然可以从之前的情况去学习,不至于一摆到底。

最后,因为迭代的结果不是很稳定,所以我改写了xuance自带的DDQN_Agent类,在训练固定的步数后就进行测试以记录最佳的成绩,如下图所示

一开始我以为训练的大幅度波动是ε贪心策略随机选取动作导致的,从测试结果看来就算动作选取是固定的,迭代仍然存在很严重的波动。

f%5Cleft(%20x%2Cy%20%5Cright)%20%3D-%5Cleft%7C%20x-150%20%5Cright%7C-%5Cleft%7C%20y-200%20%5Cright%7C,而是选取了f%5Cleft(%20x%2Cy%20%5Cright)%20%3D-%5Cleft%7C%20x-173%20%5Cright%7C-%5Cleft%7C%20y-217%20%5Cright%7C,这样智能体就必须采取+50以外的动作才能达到最优,选取初始状态为(0,0),最后智能体返回的状态为(174,215),我认为这已经是一个相对可以接受的结果了。即使不选择(0,0)作为初始状态,而是选取比较小的状态作为初始状态,智能体最后也能返回一个相对可以接受的结果,所以我认为虽然训练的波动大的离谱,但这个训练还算是成功的。

代码不复杂,如果有人希望复现可以使用我贴在下面的代码

实现购买模型的代码:

在训练固定的步数后就进行测试以记录最佳的成绩DDQN:

看起来很长,然而只是照抄了xuance的源码,然后自己做了一些小改动

训练的代码:

其中配置文件BestRecordTest.yaml如下

使用这段代码,在我的电脑(i7,RTX4070)上运行大概半个小时就可以完成训练

通过下面的代码进行测试:



Copyright © 2024 aigcdaily.cn  北京智识时代科技有限公司  版权所有  京ICP备2023006237号-1