Q-learning在简化Blackjack模拟中出现‘R has length zero’错误求助
解决Blackjack Q-learning中的"R has length zero"错误
我帮你排查了这段R代码,出现R has length zero错误的核心原因有几个,咱们一步步来修复:
1. getRowMax函数缺少返回值
你写的getRowMax函数遍历数组找最大值,但最后没有把找到的最大值返回!这会导致调用它的时候返回NULL,在Q-learning的更新公式里,NULL和数值进行运算就会触发长度为0的错误。
修复后的函数应该加上返回语句:
getRowMax = function(tab){ temp = tab[1] for(i in 2:length(tab)){ if(tab[i] > temp){ temp = tab[i] } } return(temp) # 新增返回最大值的语句 }
2. Q-learning更新公式的运算符错误
原代码里的Q值更新公式把加号写成了乘号,正确的Q-learning公式是:Q(s,a) = Q(s,a) + α * (R + γ * maxQ(s',a') - Q(s,a))
你写成了simResults[i,3] * discount * getRowMax(...),这会导致奖励计算完全错误,同时也会引发数值运算的异常。
修正后的更新代码:
Qvalues[st, a] = Qvalues[st, a] + alpha * ( simResults[i,3] + discount * getRowMax(Qvalues[stPlusOne, ]) - Qvalues[st, a] )
3. 状态索引越界问题
R的矩阵索引从1开始,但你的simResults里存在状态值为0的情况(比如第一次模拟的初始状态cs第四列是0),访问Qvalues[0, a]会返回NULL,进而引发错误。我们需要把所有状态值加1,确保索引从1开始:
在Q-learning循环里修改st和stPlusOne的取值:
st = simResults[i, 4] + 1 # 状态+1,避免0索引 a = simResults[i, 2] stPlusOne = simResults[i, 1] + 1 # 下一个状态同样+1
同时,因为状态值最大可能到21(玩家手牌不爆的情况),Qvalues设置30行是足够的,不用调整行数。
其他潜在优化点
- 你的
simulation函数里玩家的决策是随机的(用runif生成动作),后续可以改成根据Qvalues选择最优动作,这样才能真正学习到最优策略 - 可以添加对玩家手牌爆牌(score>21)的判断,避免无效状态的产生
把这些修改应用到代码里,就能解决R has length zero的错误,Q-learning也能正常运行了。
内容的提问来源于stack exchange,提问作者Lucien Ledune
相关产品推荐
相关产品推荐

