【人工智能】作业4: PacMan游戏 实验报告

作业4: PacMan游戏 实验报告

吴政亿 151220129 wuzy.nju@gmail.com
(南京大学 计算机科学与技术系, 南京 210093)

摘要:使用强化学习来自主玩Mr. PACMAN游戏。通过强化学习,得到Q值函数,并根据Q值函数进行决策。理解并深入研究使用的强化算法,并尝试修改程序来提高学习性能。其中,理解epsilon greedy策略与折扣累计奖赏的含义

关键词:强化学习、Q值函数、epsilon greedy、折扣累计奖赏

一、框架代码理解

1. 策略模型

策略模型用 Q-learning 模型表示。步骤如下:

1. 外循环模拟次数num_episodes(框架代码为10)
2. 内循环每次模拟最大步数num_steps(框架代码为SIMULATION_DEPTH=20)
3. 根据当前的state和q-table选择action(框架代码epsilon greedy探索概率为0.3)
4. 根据当前的state和action获得下一步的state和reward
5. 更新q-table: Q[s,a] = Q[s,a] + lr*(r + y*np.max(Q[s1,:]) - Q[s,a])

qleaning

缺点是 Q-learning 使用最佳 Q 值,它不关心遵循的实际策略,是一个脱离策略的学习算法。可以改为 SARSA 方法,在采取实际行动后再回传Q 值,当发生探索时 SARSA 是个依附策略。

sarsa

SARSA 的思想很简单,就是增加一个 A ,下一步的 A ,然后据此来估计 Q 值。

另外, Q-Leaning 可能会出现对 Q 值过度估计的问题, Double Q-leaning 可以解决这个问题,使用两个 Q 交替更新。

doubleqleaning

2. Agent

(1) SIMULATION_DEPTH

在框架代码中, SIMULATION_DEPTH 用来确定模拟的最大深度,防止时间消耗过多,但又能达到一个较高的精度。它初始化为20,代表每次策略评估时,折扣累计奖赏的迭代次数为20次。在 simulate 函数中,它尝试在当前局面下走 SIMULATION_DEPTH 步,然后计算最后状态的预测 Q 值与累计奖赏值。

(2) m_gamma

m_gamma 是折扣累计奖赏的参数 γ γ (收益衰减系数),对于 γ γ 折扣累计奖赏,计算公式为:

E[t=0+γtrt+1] E [ ∑ t = 0 + ∞ γ t r t + 1 ]

可见一直执行到最后,越往后奖赏权重越低,在框架代码中, m_gamma=0.99 m _ g a m m a = 0.99

(3) m_maxPoolSize

框架代码中, m_maxPoolSize=1000 m _ m a x P o o l S i z e = 1000 ,代表在应用 weka 强化学习中,限制最大的 data 数为1000.

m_dataset.randomize(m_rnd);
for (int i = 0; i < dataset.numInstances(); i++) {
    m_dataset.add(dataset.instance(i)); // add to the last
}
while (m_dataset.numInstances() > m_maxPoolSize) {
    m_dataset.delete(0);
}

在更新数据集时,如果数据集个数超过最大限制 data 数,就把最前面的 data 删掉。

3. QPolicy

对于getActiongetActionNoExplore 两个函数的区别,主要就在于是否应用epsilon greedy策略。首先先简要浅析二者代码==相同部分==。

int bestaction = 0;
for(int action=1; action<m_numActions; action++){
    if( Q[bestaction] < Q[action] ){
        bestaction = action;
    }
}

首先遍历Q值,得到其中最佳动作。

int sameactions =0;
for(int action=bestaction+1; action<m_numActions; action++){
    if(Q[bestaction] == Q[action]){
        sameactions++;
        if( m_rnd.nextDouble() < 1.0/(double)sameactions )
            bestaction = action;
    }
}

然后寻找所有与best action的Q值相同的动作。由于先前的遍历决定了这个best action一定是相同Q值动作序列的第一个,所以从best action的下一个开始遍历,如果发现Q值相同的动作,就以 1n 1 n 的概率替换掉先前的best action。其中 n n 为遍历中发现best action的数量。

接下来则是二者代码==不同部分==。

protected double m_epsilon=0.3;

...

if( m_rnd.nextDouble() < m_epsilon ){
    bestaction = m_rnd.nextInt(m_numActions);
}

getActionNoExploregetAction 多了一个 epsilon greedy 的步骤,可见,框架代码中设置了一个执行探索的概率 0.3 ,每次 action 他都会以 0.3 0.3 的概率执行探索操作(随机选择一个工作),以 0.7 0.7 的概率执行利用操作(选择一个得分最好的动作)。

epsilon greedy 基于一个概率 m_epsilon 来对探索和利用进行折中,相比之下, getActionNoExplore 更加容易陷入局部最优解里,而 getAction 相比之下多了一部分随机性,可以尽可能的实现最大化收益。对于 m_epsilon 的选择,当不确定性较大,例如概率分布较宽时,则需要更多的探索,此时需要较大的 m_epsilon;若不确定性较小,例如概率分布较集中时,则少量的尝试就可以很好地近似真实奖赏,此时需要的 m_epsilon 较小;并且在后期这个值下降可以令模型更快收敛得到相应最优解,例如令 m_epsilon=1/t m _ e p s i l o n = 1 / t

二、特征提取

在特征提取中,原有的许多位置都是无效的,我选择了

  1. NPC 到最近的幽灵的曼哈顿距离
  2. 各个幽灵的位置
  3. 蘑菇的位置
  4. 钻石的位置
  5. 水果的位置
  6. 各个幽灵的方位
public static double[] featureExtract(StateObservation obs) {
    double[] feature = new double[s_datasetHeader.numAttributes()];
    if (obs.getImmovablePositions() != null) {
        for (ArrayList<Observation> l : obs.getImmovablePositions()) {
            if (l.size() == 0)
                continue;
            // pellets
            else if (l.get(0).itype == 4) {
                feature[0] = nearestDir(obs, l);
            }
            // fruit
            else if (l.get(0).itype == 3) {
                feature[1] = nearestDir(obs, l);
            }
        }
    }
    // 4 ghosts
    ArrayList<Observation> allGhost = new ArrayList<>();
    if (obs.getPortalsPositions() != null) {
        for (ArrayList<Observation> l : obs.getPortalsPositions()) {
            allGhost.addAll(l);
        }
    }
    feature[2] = nearestDir(obs, allGhost);
    // isNearGhost
    feature[5] = isNearGhost(obs, allGhost) ? 1 : 0;
    // 4 powerpills
    if (obs.getResourcesPositions() != null) {
        for (ArrayList<Observation> l : obs.getResourcesPositions()) {
            feature[3] = nearestDir(obs, l);
        }
    }
    // 4 ghost direct
    Vector2d avatarPos = obs.getAvatarPosition();
    int i = 6;
    for (Observation o : allGhost) {
        double delta_x = o.position.x - avatarPos.x;
        double delta_y = o.position.y - avatarPos.y;
        double dist = o.position.dist(avatarPos);
        feature[i] = Math.acos(delta_x / dist) + (delta_y < 0 ? Math.PI : 0);
        i++;
    }

    return feature;
}

在提取了上述特征后,分数得到提升,但是仍然上下波动。

pig

三、强化学习参数调整

根据一系列可靠实验数据结果表明,当 m_epsilon 上调,并且相应降低 m_gamma 的比例会有着较为不错的效果。但是分数仍会上下波动,需要多次学习后才能稳定下来。

下面的分数均为大量重复实验后的平均分,默认关卡。

探索概率0.20.40.60.8
分数8090120130

可以发现随着探索概率上升,随有波动,但是更容易得到一个相对更优的解。因为该模型已知状态空间等信息,可以更为准确的得到当前局势情况,另外概率分布较宽。

SIMULATION_DEPTH102030
分数130110162

由于电脑性能,并未再继续增加 SIMULATION_DEPTH 大小,理论上随着 SIMULATION_DEPTH 则规模大,分数会有些许提高,得到这个结果也许是因为实验样本较少。

γ γ 0.20.40.60.80.90.99
分数14315516913812590

γ γ 代表未来局势分数对当前步骤的奖赏分数,可以发现分数先上升,然后在 0.6 附近达到峰值,随后再下降。

四、实验总结

在本次试验中,我意识到了特征提取与奖赏函数的重要性。同时调参的过程中也让我意识到了众多参数带来的影响,更加深刻的理解了强化学习的步骤与作用。

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值