马尔可夫决策过程:价值迭代,它是如何运作的?

时间:2011-12-01 06:35:48

标签: algorithm language-agnostic artificial-intelligence markov

我最近一直在阅读很多关于Markov Decision Processes (using value iteration)的内容,但我根本无法理解他们。我在互联网/书籍上找到了很多资源,但他们都使用的数学公式对我的能力来说过于复杂。

由于这是我上大学的第一年,我发现网上提供的解释和公式使用的概念/术语对我来说太复杂了,他们认为读者知道某些事情我和# 39;我根本就没听说过。

我想在2D网格上使用它(填充墙壁(无法实现),硬币(可取)和移动的敌人(必须不惜一切代价避免))。整个目标是收集所有硬币而不触及敌人,我想使用马尔可夫决策过程( MDP )为主要玩家创建AI。以下是它的部分外观(请注意,与游戏相关的方面并非如此。我只是想了解 MDP ):

enter image description here

根据我的理解, MDP 的粗略简化是他们可以创建一个网格,该网格保持我们需要去的方向(#34;箭头"指出我们需要去的地方,从网格上的某个位置开始)以达到某些目标并避开某些障碍。具体到我的情况,这意味着它允许玩家知道去哪个方向收集硬币并避开敌人。

现在,使用 MDP 术语,这意味着它会创建一个状态集合(网格),其中包含某些策略(要采取的操作 - >向上,向下,向右,向左)对于某个状态(网格上的位置)。这些政策由"实用程序"每个州的价值,这些价值本身是通过评估在短期和长期内有多少益处来计算的。

这是对的吗?还是我完全走错了路?

我至少想知道以下等式中的变量代表我的情况:

U_{i+1}(s) \longleftarrow R(s) + \gamma \max \sum\limits_{s'} T(s,a,s') U_i (s') \,.

(摘自书"人工智能 - 现代方法"来自Russell& Norvig)

我知道s将是网格中所有方块的列表,a将是一个特定的操作(上/下/右/左),但其余的呢?< / p>

如何实施奖励和效用函数?

如果有人知道一个显示伪代码的简单链接,以非常缓慢的方式实现与我的情况相似的基本版本,那将是非常好的,因为我甚至不知道从哪里开始。< / p>

感谢您宝贵的时间。

(注意:随意添加/删除标签或在评论中告诉我是否应提供有关此类内容的更多详细信息。)

4 个答案:

答案 0 :(得分:36)

是的,数学符号可以使它看起来比它复杂得多。真的,这是一个非常简单的想法。我已经实现了value iteration demo applet,您可以使用它来获得更好的主意。

基本上,假设你有一个带有机器人的2D网格。机器人可以尝试移动北,南,东,西(这些是动作a),但是,因为它的左轮是滑的,当它试图向北移动时,只有.9概率它最终会在广场上在它的北边,虽然它有一个概率,它最终会在它的西边(相似的其他3个动作)。这些概率由T()函数捕获。即,T(s,A,s')将如下所示:

s    A      s'     T    //x=0,y=0 is at the top-left of the screen
x,y  North  x,y+1  .9   //we do move north
x,y  North  x-1,y  .1   //wheels slipped, so we move West
x,y  East   x+1,y  .9
x,y  East   x,y-1  .1
x,y  South  x,y+1  .9
x,y  South  x-1,y  .1 
x,y  West   x-1,y  .9
x,y  West   x,y+1  .1 

然后,您将所有状态的奖励设置为0,但目标状态设置为100,即您希望机器人到达的位置。

值迭代的作用是通过向目标状态赋予100的效用而向所有其他状态赋予0。然后在第一次迭代中,这100个实用程序从目标分配回一步,因此所有可以一步到达目标状态的状态(紧邻它的所有4个方格)将获得一些效用。也就是说,他们将得到一个效用等于从该状态我们可以达到所述目标的概率。然后我们继续迭代,在每个步骤中,我们将实用程序从目标移开1步。

在上面的示例中,假设您从R(5,5)= 100开始,并且对于所有其他状态,R(。)= 0。所以目标是达到5,5。

在第一次迭代中我们设置了

R(5,6)= gamma *(。9 * 100)+ gamma *(。1 * 100)

因为在5,6如果你去北方有一个.9的概率最终在5,5,而如果你去西方有一个.1概率最终在5,5。

类似于(5,4),(4,5),(6,5)。

在第一次重复迭代迭代后,所有其他状态仍为U = 0。

答案 1 :(得分:5)

我建议您使用Q-learning进行实施。

也许你可以使用我写的这篇文章作为灵感。这是Q-learning demo with Java source code。这个演示是一个包含6个字段的地图,AI了解每个州应该从哪里获得奖励。

  

Q-learning是一种让人工智能通过给予奖励或惩罚来学习的技巧。

     

此示例显示用于路径查找的Q学习。机器人会从任何州了解它应该去哪里。

     

机器人在一个随机的地方开始,它在探索区域的同时记录得分,每当它到达目标时,我们重复一个新的随机开始。经过足够的重复后,得分值将是静止的(收敛)。

     

在此示例中,动作结果是确定性的(转移概率为1),动作选择是随机的。通过Q学习算法Q(s,a)计算得分值   图像显示了状态(A,B,C,D,E,F),来自状态的可能行为和给出的奖励。

     

q-learn1

     

结果Q *(s,a)
  q-learn2

     

政策Π*(s)
  q-learn3

     

Qlearning.java

import java.text.DecimalFormat;
import java.util.Random;

/**
 * @author Kunuk Nykjaer
 */
public class Qlearning {
    final DecimalFormat df = new DecimalFormat("#.##");

    // path finding
    final double alpha = 0.1;
    final double gamma = 0.9;


// states A,B,C,D,E,F
// e.g. from A we can go to B or D
// from C we can only go to C
// C is goal state, reward 100 when B->C or F->C
//
// _______
// |A|B|C|
// |_____|
// |D|E|F|
// |_____|
//

    final int stateA = 0;
    final int stateB = 1;
    final int stateC = 2;
    final int stateD = 3;
    final int stateE = 4;
    final int stateF = 5;

    final int statesCount = 6;
    final int[] states = new int[]{stateA,stateB,stateC,stateD,stateE,stateF};

    // http://en.wikipedia.org/wiki/Q-learning
    // http://people.revoledu.com/kardi/tutorial/ReinforcementLearning/Q-Learning.htm

    // Q(s,a)= Q(s,a) + alpha * (R(s,a) + gamma * Max(next state, all actions) - Q(s,a))

    int[][] R = new int[statesCount][statesCount]; // reward lookup
    double[][] Q = new double[statesCount][statesCount]; // Q learning

    int[] actionsFromA = new int[] { stateB, stateD };
    int[] actionsFromB = new int[] { stateA, stateC, stateE };
    int[] actionsFromC = new int[] { stateC };
    int[] actionsFromD = new int[] { stateA, stateE };
    int[] actionsFromE = new int[] { stateB, stateD, stateF };
    int[] actionsFromF = new int[] { stateC, stateE };
    int[][] actions = new int[][] { actionsFromA, actionsFromB, actionsFromC,
            actionsFromD, actionsFromE, actionsFromF };

    String[] stateNames = new String[] { "A", "B", "C", "D", "E", "F" };

    public Qlearning() {
        init();
    }

    public void init() {       
        R[stateB][stateC] = 100; // from b to c
        R[stateF][stateC] = 100; // from f to c    
    }

    public static void main(String[] args) {
        long BEGIN = System.currentTimeMillis();

        Qlearning obj = new Qlearning();

        obj.run();
        obj.printResult();
        obj.showPolicy();

        long END = System.currentTimeMillis();
        System.out.println("Time: " + (END - BEGIN) / 1000.0 + " sec.");
    }

    void run() {
        /*
         1. Set parameter , and environment reward matrix R
         2. Initialize matrix Q as zero matrix
         3. For each episode: Select random initial state
            Do while not reach goal state o
                Select one among all possible actions for the current state o
                Using this possible action, consider to go to the next state o
                Get maximum Q value of this next state based on all possible actions o
                Compute o Set the next state as the current state
         */

        // For each episode
        Random rand = new Random();
        for (int i = 0; i < 1000; i++) { // train episodes
            // Select random initial state
            int state = rand.nextInt(statesCount);
            while (state != stateC) // goal state
            {
                // Select one among all possible actions for the current state
                int[] actionsFromState = actions[state];

                // Selection strategy is random in this example
                int index = rand.nextInt(actionsFromState.length);
                int action = actionsFromState[index];

                // Action outcome is set to deterministic in this example
                // Transition probability is 1
                int nextState = action; // data structure

                // Using this possible action, consider to go to the next state
                double q = Q(state, action);
                double maxQ = maxQ(nextState);
                int r = R(state, action);

                double value = q + alpha * (r + gamma * maxQ - q);
                setQ(state, action, value);

                // Set the next state as the current state
                state = nextState;
            }
        }
    }

    double maxQ(int s) {
        int[] actionsFromState = actions[s];
        double maxValue = Double.MIN_VALUE;
        for (int i = 0; i < actionsFromState.length; i++) {
            int nextState = actionsFromState[i];
            double value = Q[s][nextState];

            if (value > maxValue)
                maxValue = value;
        }
        return maxValue;
    }

    // get policy from state
    int policy(int state) {
        int[] actionsFromState = actions[state];
        double maxValue = Double.MIN_VALUE;
        int policyGotoState = state; // default goto self if not found
        for (int i = 0; i < actionsFromState.length; i++) {
            int nextState = actionsFromState[i];
            double value = Q[state][nextState];

            if (value > maxValue) {
                maxValue = value;
                policyGotoState = nextState;
            }
        }
        return policyGotoState;
    }

    double Q(int s, int a) {
        return Q[s][a];
    }

    void setQ(int s, int a, double value) {
        Q[s][a] = value;
    }

    int R(int s, int a) {
        return R[s][a];
    }

    void printResult() {
        System.out.println("Print result");
        for (int i = 0; i < Q.length; i++) {
            System.out.print("out from " + stateNames[i] + ":  ");
            for (int j = 0; j < Q[i].length; j++) {
                System.out.print(df.format(Q[i][j]) + " ");
            }
            System.out.println();
        }
    }

    // policy is maxQ(states)
    void showPolicy() {
        System.out.println("\nshowPolicy");
        for (int i = 0; i < states.length; i++) {
            int from = states[i];
            int to =  policy(from);
            System.out.println("from "+stateNames[from]+" goto "+stateNames[to]);
        }          
    }
}
     

打印结果

     
out from A:  0 90 0 72,9 0 0
out from B:  81 0 100 0 81 0
out from C:  0 0 0 0 0 0
out from D:  81 0 0 0 81 0
out from E:  0 90 0 72,9 0 90
out from F:  0 0 100 0 81 0

showPolicy
from a goto B
from b goto C
from c goto C
from d goto A
from e goto B
from f goto C
Time: 0.025 sec.

答案 2 :(得分:4)

不是一个完整的答案,而是一个澄清的评论。

状态 单个单元格。状态包含所有相关单元格的每个单元格中的信息。这意味着一个状态元素包含哪些单元格是实体而哪些单元格是空的信息;哪些包含怪物;硬币在哪里;玩家在哪里。

也许您可以将每个单元格中的地图用作其状态的内容。这确实忽略了怪物和玩家的移动,这可能也非常重要。

详细信息取决于您希望如何对问题进行建模(确定属于哪种状态以及采用哪种形式)。

然后策略将每个状态映射到左,右,跳等动作

首先,您必须先了解MDP所表达的问题,然后再考虑价值迭代等算法的工作原理。

答案 3 :(得分:2)

我知道这是一篇相当古老的帖子,但我在寻找与MDP相关的问题时遇到过它,我确实想要注意(对于那里的人们)还有一些关于你何时陈述什么&#34; s& #34;和&#34; a&#34;是

我觉得你绝对正确,这是你的[上,下,左,右]列表。

然而,对于它来说,它确实是网格中的位置和s&#39;是你可以去的地方。 这意味着你选择一个州,然后你选择一个特定的s&#39;并通过所有可以带你到那个sprime的行动,你用它来弄清楚那些价值观。 (从中挑出最大值)。最后你去找下一个s&#39;当你已经筋疲力尽所有s&#39;然后你会找到你刚刚搜索完毕的最大值。

假设您在角落中选择了一个网格单元格,您只能有两种状态可以移动到(假设左下角),具体取决于您选择的方式&#34; name&#34;在这种情况下,我们可以假设一个状态是一个x,y坐标,所以你当前的状态s是1,1而你的s&#39; (或s prime)列表是x + 1,y和x,y + 1(在这个例子中没有对角线)(超过所有s&#39的求和部分)

你也没有将它列在你的等式中,但是最大值是a或者给你最大值的动作,所以首先你选择s&#39;这会给你最大值,然后你选择行动(至少这是我对算法的理解)。

所以,如果你有

x,y+1 left = 10 
x,y+1 right = 5 

x+1,y left = 3
x+1,y right 2

您将选择x,y + 1作为您的s&#39;,但之后您需要选择一个最大化的动作,在这种情况下为x,y + 1。我不确定在找到最大数量和找到状态之间是否存在细微差别,然后是最大数量,但也许有一天某人可能会为我澄清这一点。

如果你的动作是确定性的(意思是如果你说前进,你可以100%确定地前进),那么你有一个动作很容易,但是如果它们是非确定性的,那你就说80那么你应该考虑可以让你到达的其他行动。这是何塞在上面提到的滑轮的背景。

我不想贬低别人所说的内容,只是为了提供一些额外的信息。