我们使用HMM(隐马尔可夫模型)来在一个有风且传感器损坏的迷宫中定位机器人。如果他尝试朝某个方向移动,他会以高概率成功移动,并有低概率意外地向两侧移动。如果他的移动会使他越过障碍物,他会弹回到原来的位置。
从任何给定的位置,他可以向四个方向感知。如果某个方向有障碍物,他会以高确定性注意到它,而在没有障碍物时,他会以低确定性看到障碍物。
我们有一个概率地图,显示机器人在迷宫中可能存在的所有位置,因为他知道迷宫的布局。最初,所有位置的概率是均匀分布的。
我已经完成了运动和感知方面的任务,并且得到了正确的结果,但我在平滑(后向算法)上遇到了困难。
假设机器人执行以下一系列动作:感知、移动、感知、移动、感知。这为我们的HMM模型提供了3个状态。假设到目前为止,每一步的结果都是正确的。
我遇到了很多麻烦,无法执行平滑(后向算法),因为有四个条件概率(每个方向一个)。
假设SP代表平滑概率,BP代表后向概率
假设Sk代表一个状态,Zk代表该状态的观测。我的问题在于如何构建我的后向方程,因为每个Zk仅适用于单一方向。
我知道平滑的算法是:SP(k)与BP(k+1) * P(Sk | Z1:k)成比例
其中BP(k+1)定义为:
如果(k == n)返回1,否则返回BP(k+1) * P(Zk+1|Sk+1) * P(Sk+1=s | Sk)的总和
这就是我遇到麻烦的地方。主要是在这个方程的条件概率部分。因为每个位置有四个不同的方向需要观察!换句话说,每个状态有四个不同的证据变量,而不是只有一个!我应该平均这些值吗?我应该为它们做一个单独的总和吗?我如何考虑在一个给定状态下的多个观测,并将其正确地压缩到这个只有一个条件概率的方程中?
这是我执行平滑的代码:
public static void Smoothing(List<int[]> observations) { int n = observations.Count; //n是证据序列的总长度 int k = n - 1; //k是我们试图平滑的状态。从n-1开始 for (; k >= 1; k--) { //平滑回第一个状态 for (int dir = 0; dir < 4; dir++) { //我们必须分别平滑每个方向 SmoothDirection(dir, observations, k, n); } Console.WriteLine($"Smoothing for k = {k}\n"); UpdateMapMotion(mapHistory[k]); PrintMap(); } } public static void SmoothDirection(int dir, List<int[]> observations, int k, int n) { var alphas = new double[ROWS, COLS]; var normalizer = 0.0; int row, col; foreach (var t in map) { if (t.isObstacle) continue; row = t.pos.y; col = t.pos.x; alphas[row, col] = mapHistory[k][row, col] * Backwards(k, n, t, dir, observations, moves[^(n - k)]); normalizer += alphas[row, col]; } UpdateHistory(k, alphas, normalizer); } public static void UpdateHistory(int index, double[,] alphas, double normalizer) { for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { mapHistory[index][r, c] = alphas[r, c] / normalizer; } } } public static double Backwards(int k, int n, Tile t, int dir, List<int[]> observations, int moveDir) { if (k == n) return 1; double p = 0; var nextStates = GetPossibleNextStates(t, moveDir); foreach (var s in nextStates) { p += Cond_Prob(s.hasObstacle[dir], observations[^(n - k)][dir] == 1) * Trans_Prob(t, s, moveDir) * Backwards(k+1, n, s, dir, observations, moves[^(n - k)]); } return p; } public static List<Tile> GetPossibleNextStates(Tile t, int direction) { var tiles = new List<Tile>(); //下一状态 var perpDirs = GetPerpendicularDir(direction); //垂直方向 //如果Tile t前方或侧面有障碍物,Tile t是可能的下一状态。 if (t.hasObstacle[direction] || t.hasObstacle[perpDirs[0]] || t.hasObstacle[perpDirs[1]]) tiles.Add(t); //如果Tile t前方没有障碍物,那么那个位置是可能的下一状态。 if (!t.hasObstacle[direction]) tiles.Add(GetTileAtPos(t.pos + directions[direction])); //如果Tile t的侧面没有障碍物,那么那些位置是可能的下一状态。 foreach (var dir in perpDirs) { if (!t.hasObstacle[dir]) tiles.Add(GetTileAtPos(t.pos + directions[dir])); } return tiles; }
简而言之:当每个状态有4个证据而不是1个时,如何在隐马尔可夫模型中执行平滑(后向算法)?
回答:
已解决!
实际上,这比我想象的要简单得多。
我实际上不需要在每个方向上分别进行每次迭代。
我只需要用Joint_Cond_Prob()函数替换Cond_Prob()函数,后者可以找到给定状态下所有方向观测的联合概率。
所以P(Zk|Sk)实际上是P(Zk1:Zk4|Sk),也就是P(Zk1|Sk)P(Zk2|Sk)P(Zk3|Sk)P(Zk4|Sk)