c++ - 实现近似(基于特征)q学习的问题
问题描述
我是强化学习的新手。我最近了解了近似 q 学习或基于特征的 q 学习,其中您通过特征描述状态以节省空间。我试图在一个简单的网格游戏中实现这一点。在这里,代理应该学会不进入火坑(由 f 表示),而是尽可能多地吃掉点。这是使用的网格:
...A
.ff
.ff
...f
这里 A 表示代理的起始位置。现在,在实施时,我设置了两个功能。一个是 1/((到最近点的距离)^2),另一个是 (到火坑的距离) + 1。当代理进入火坑时,程序返回 -100 的奖励。如果它去到一个已经被访问过的非火坑位置(因此没有要吃的点),奖励是-50。如果它到达一个未访问的点,则奖励为 +500。在上面的网格中,无论初始权重是什么,程序都不会学习到正确的权重值。具体来说,在输出中,第一个训练会话的得分(它吃了多少个点)为 3,但对于所有其他训练会话,得分仅为 1,并且权重收敛到权重 1 的错误值 -125(到火坑的距离)和 25 权重 2(到未访问点的距离)。
我试图玩弄环境给予的奖励以及初始权重。这些都没有解决问题。这是整个程序的链接:https ://repl.it/repls/WrongCheeryInterface
这是主循环中发生的事情:
while(points != NUMPOINTS){
bool playerDied = false;
if(!start){
if(!atFirepit()){
r = 0;
if(visited[player.x][player.y] == 0){
points += 1;
r += 500;
}else{
r += -50;
}
}else{
playerDied = true;
r = -100;
}
}
//Update visited
visited[player.x][player.y] = 1;
if(!start){
//This is based off the q learning update formula
pairPoint qAndA = getMaxQAndAction();
double maxQValue = qAndA.q;
double sample = r;
if(!playerDied && points != NUMPOINTS)
sample = r + (gamma2 * maxQValue);
double diff = sample - qVal;
updateWeights(player, diff);
}
// checking end game condition
if(playerDied || points == NUMPOINTS) break;
pairPoint qAndA = getMaxQAndAction();
qVal = qAndA.q;
int bestAction = qAndA.a;
//update player and q value
player.x += dx[bestAction];
player.y += dy[bestAction];
start = false;
}
我希望这两个权重仍然是正的,但其中一个是负的(一个给火坑的距离)。
我还希望该程序能够学习加班,即进入火坑很糟糕,也很糟糕,但没有那么糟糕,去一个未被访问的点。
解决方案
可能不是您想听到的答案,但是:
您是否尝试在近似 Q学习之前实现更简单的表格 Q学习?在您的设置中,只需几个状态和动作,它就会完美地工作。如果您正在学习,我强烈建议您从更简单的案例开始,以便更好地理解/直觉强化学习的工作原理。
你知道使用逼近器而不是学习精确的 Q 函数的含义吗?在某些情况下,由于问题的复杂性(例如,当状态空间是连续的),您应该近似 Q 函数(或策略,取决于算法),但这可能会引入一些收敛问题。此外,在您的情况下,您正在尝试手动挑选一些特征,这通常需要对问题(即环境)和学习算法有深入的了解。
你了解超参数alpha和gamma的含义吗?您不能随意选择它们。有时它们对于获得预期结果至关重要,但并非总是如此,这在很大程度上取决于问题和学习算法。在您的情况下,看看您权重的收敛曲线,很明显您使用的alpha值太高了。正如您所指出的,在第一次训练后,您的体重保持不变。
因此,实用的建议:
在尝试更复杂的事情之前,请务必使用表格 Q 学习算法解决您的网格游戏。
尝试不同的alpha、gamma和奖励值。
深入了解近似 RL。一本非常好且易于阅读的书(从零知识开始)是经典的 Sutton 和 Barto 的书:Reinforcement Learning: An Introduction,您可以免费获得,并于 2018 年更新。
推荐阅读
- arrays - 为什么我的 Ruby 方法返回一个数组而不是字符串?
- bluedata - bdcsv.py 返回“日期时区 id '00:00' 未被识别”
- webpack - 错误:ENOENT:在无服务器项目中尝试在 lambda 函数内导入 ejs 文件时,没有这样的文件或目录
- javascript - 反应数组状态在渲染之前被清除
- ignite - 如何在缓存中找到最大的键
- java - 为什么导出为 jar 会改变我的 HBox?
- c# - 如何创建用于将 xml 数据转换为 oledb 目标的自定义 ssis 组件
- angular - Angular - 在 Edge 中无法下载文件
- swift - 如何找到按下了哪个按钮?
- java - JUnit assertFalse(false) 找不到 BooleanSupplier