2D 迷宫中的 HMM 定位,应用平滑(向后算法)的麻烦
HMM Localization in 2D maze, trouble applying smoothing (backward algorithm)
我们使用 HMM(隐马尔可夫模型)在传感器损坏的多风迷宫中定位机器人。如果他试图朝一个方向移动,他这样做的可能性很大,而意外走到任何一边的可能性很小。如果他的动作会让他越过障碍物,他会弹回原来的方格。
从任何给定的位置,他都可以感知所有四个方向。如果确定性高,他会注意到障碍物,而确定性低时 none 会看到障碍物。
我们有机器人可能在迷宫中所有可能位置的概率图,因为他知道迷宫的样子。最初它全部开始均匀分布。
我已经完成了这方面的运动和传感方面的工作,并且得到了正确的答案,但我仍然停留在平滑(向后算法)上。
假设机器人执行以下动作序列:感知、移动、感知、移动、感知。这为我们的 HMM 模型提供了 3 个状态。假设我到目前为止每一步的结果都是正确的。
鉴于有四个条件概率(每个方向一个),我在执行平滑(后向算法)时遇到了很多麻烦。
假设SP是平滑概率,BP是后向概率
假设Sk代表一个状态,Zk代表那个状态下的观察值。对我来说,问题是在每个 Zk 仅针对一个方向的情况下,弄清楚如何构建我的反向方程。
我知道平滑算法是:SP(k) 正比于 BP(k+1) * P(Sk | Z1:k)
其中 BP(k+1) 定义为:
if (k == n) return 1 else return 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 is Total length of evidence sequence
int k = n - 1; //k is the state we are trying to smooth. start with n-1
for (; k >= 1; k--) { //Smooth all the way back to the first state
for (int dir = 0; dir < 4; dir++) {
//We must smooth each direction separately
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>(); //Next States
var perpDirs = GetPerpendicularDir(direction); //Perpendicular Directions
//If obstacle in front of Tile t or on the sides, Tile t is a possible next state.
if (t.hasObstacle[direction] || t.hasObstacle[perpDirs[0]] || t.hasObstacle[perpDirs[1]])
tiles.Add(t);
//If there is no obstacle in front of Tile t, then that tile is a possible next state.
if (!t.hasObstacle[direction])
tiles.Add(GetTileAtPos(t.pos + directions[direction]));
//If there are no obstacles on the sides of Tile t, then those are possible next states.
foreach (var dir in perpDirs) {
if (!t.hasObstacle[dir])
tiles.Add(GetTileAtPos(t.pos + directions[dir]));
}
return tiles;
}
TL;DR:当每个状态有 4 个证据而不是只有 1 个证据时,我如何在隐马尔可夫模型中执行平滑(后向算法)?
已解决!
其实比想象中简单多了
我实际上不需要在每个方向上分别进行每次迭代。
我只需要将 Cond_Prob() 函数替换为 Joint_Cond_Prob() 即可找到给定状态下所有定向观测值的联合概率。
所以 P(Zk|Sk) 实际上是 P(Zk1:Zk4|Sk) 即 P(Zk1|Sk)P(Zk2|Sk)P(Zk3|Sk)P(Zk4|Sk)
我们使用 HMM(隐马尔可夫模型)在传感器损坏的多风迷宫中定位机器人。如果他试图朝一个方向移动,他这样做的可能性很大,而意外走到任何一边的可能性很小。如果他的动作会让他越过障碍物,他会弹回原来的方格。
从任何给定的位置,他都可以感知所有四个方向。如果确定性高,他会注意到障碍物,而确定性低时 none 会看到障碍物。
我们有机器人可能在迷宫中所有可能位置的概率图,因为他知道迷宫的样子。最初它全部开始均匀分布。
我已经完成了这方面的运动和传感方面的工作,并且得到了正确的答案,但我仍然停留在平滑(向后算法)上。
假设机器人执行以下动作序列:感知、移动、感知、移动、感知。这为我们的 HMM 模型提供了 3 个状态。假设我到目前为止每一步的结果都是正确的。
鉴于有四个条件概率(每个方向一个),我在执行平滑(后向算法)时遇到了很多麻烦。
假设SP是平滑概率,BP是后向概率
假设Sk代表一个状态,Zk代表那个状态下的观察值。对我来说,问题是在每个 Zk 仅针对一个方向的情况下,弄清楚如何构建我的反向方程。
我知道平滑算法是:SP(k) 正比于 BP(k+1) * P(Sk | Z1:k)
其中 BP(k+1) 定义为:
if (k == n) return 1 else return 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 is Total length of evidence sequence
int k = n - 1; //k is the state we are trying to smooth. start with n-1
for (; k >= 1; k--) { //Smooth all the way back to the first state
for (int dir = 0; dir < 4; dir++) {
//We must smooth each direction separately
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>(); //Next States
var perpDirs = GetPerpendicularDir(direction); //Perpendicular Directions
//If obstacle in front of Tile t or on the sides, Tile t is a possible next state.
if (t.hasObstacle[direction] || t.hasObstacle[perpDirs[0]] || t.hasObstacle[perpDirs[1]])
tiles.Add(t);
//If there is no obstacle in front of Tile t, then that tile is a possible next state.
if (!t.hasObstacle[direction])
tiles.Add(GetTileAtPos(t.pos + directions[direction]));
//If there are no obstacles on the sides of Tile t, then those are possible next states.
foreach (var dir in perpDirs) {
if (!t.hasObstacle[dir])
tiles.Add(GetTileAtPos(t.pos + directions[dir]));
}
return tiles;
}
TL;DR:当每个状态有 4 个证据而不是只有 1 个证据时,我如何在隐马尔可夫模型中执行平滑(后向算法)?
已解决!
其实比想象中简单多了
我实际上不需要在每个方向上分别进行每次迭代。
我只需要将 Cond_Prob() 函数替换为 Joint_Cond_Prob() 即可找到给定状态下所有定向观测值的联合概率。
所以 P(Zk|Sk) 实际上是 P(Zk1:Zk4|Sk) 即 P(Zk1|Sk)P(Zk2|Sk)P(Zk3|Sk)P(Zk4|Sk)