我知道有很多与隐马尔可夫模型相关的资料,我也阅读了与此主题相关的所有问题和答案。我理解它是如何工作的以及它是如何被训练的,但是当我尝试训练它以进行简单的动态手势时,我无法解决以下问题。
我正在使用HMM implementation for OpenCV 我查看过以前提出的问题并回答here。这对我理解和使用马尔可夫模型非常有帮助。
我总共有两个动态手势,它们都是对称的(向左滑动和向右滑动) 总共有5个观察结果,其中4个是手势中的不同阶段,第5个观察是在没有这些阶段发生时的观察结果。
向左滑动手势包括以下观察:1-> 2-> 3-> 4(应该触发向左滑动状态) 同样,向右滑动手势包括以下观察:4-> 3-> 2-> 1
我有25个序列。我对每个序列进行了20次观测,用于使用Baum-Welch算法训练隐马尔可夫模型。
以下是输入序列:
1 0 1 1 0 2 2 2 2 0 0 2 3 3 3 0 0 4 4 4
4 4 4 4 4 0 3 3 3 3 3 0 0 1 0 0 1 1 0 1
4 4 4 4 4 4 0 3 3 3 3 3 0 0 1 0 0 1 1 0
4 4 4 4 4 4 4 0 3 3 3 3 3 0 0 1 0 0 1 1
1 1 1 1 0 2 2 2 0 1 0 3 3 0 0 0 4 4 4 4
1 1 1 1 1 0 2 2 2 0 1 0 3 3 0 0 0 4 4 4
0 1 1 1 1 1 0 2 2 2 0 1 0 3 3 0 0 0 4 4
0 0 1 1 1 1 1 0 2 2 2 0 1 0 3 3 0 0 0 4
4 4 0 0 3 0 3 3 3 3 0 0 0 0 0 1 1 1 1 1
4 4 4 0 0 3 0 3 3 3 3 0 0 0 0 0 1 1 1 1
4 4 4 4 0 0 3 0 3 3 3 3 0 0 0 0 0 1 1 1
1 1 1 1 0 0 2 2 0 3 2 3 3 3 0 0 4 4 4 4
1 1 1 1 1 0 0 2 2 0 3 2 3 3 3 0 0 4 4 4
1 1 1 1 1 1 0 0 2 2 0 3 2 3 3 3 0 0 4 4
1 3 4 4 4 0 3 0 0 0 0 0 3 2 0 0 1 1 1 1
在此序列中,您可以看到向左滑动和向右滑动手势的模式。
为了训练隐藏的马尔可夫模型,我使用以下值初始化它,然后调用train函数来获取输出:
TRANS:
0.7 0.15 0.15
0.3 0.4 0.3
0.3 0.4 0.3
EMIS:
0.3 0.1 0.1 0.1 0.1
0.2 0.1 0.2 0.2 0.3
0.2 0.3 0.2 0.2 0.1
INIT:
0.6 0.2 0.2
训练结束后输出:
TRANS:
0.81611 0.0847926 0.0990979
0.398458 0.346433 0.255109
0.371391 0.35587 0.272739
EMIS:
0.534127 0.125568 0.0824495 0.200169 0.0576869
0.294653 0.0250053 0.0500311 0.200616 0.429694
0.238808 0.075001 0.0500019 0.130455 0.505733
INIT:
0.443984 0.391323 0.164693
在我的识别程序中使用此模型,我没有得到结果。 我希望系统保持在NULL状态,除非检测到其中一个手势。 在Transition和Emission矩阵中,我给出了这两种姿势的猜测值。
您认为我可能做错了什么?有什么指示或帮助吗?
最后这里是我用来做这个的代码(如果有人想看看)
double TRGUESSdata[] = {0.7, 0.15, 0.15,
0.3, 0.4, 0.3,
0.3, 0.4, 0.3};
cv::Mat TRGUESS = cv::Mat(3,3,CV_64F,TRGUESSdata).clone();
double EMITGUESSdata[] = {0.3, 0.1, 0.1, 0.1, 0.1,
0.2, 0.1, 0.2, 0.2, 0.3,
0.2, 0.3, 0.2, 0.2, 0.1};
cv::Mat EMITGUESS = cv::Mat(3,5,CV_64F,EMITGUESSdata).clone();
double INITGUESSdata[] = {0.6 , 0.2 , 0.2};
cv::Mat INITGUESS = cv::Mat(1,3,CV_64F,INITGUESSdata).clone();
std::cout << seq.rows << " " << seq.cols << std::endl;
int a = 0;
std::ifstream fin;
fin.open("observations.txt");
for(int y =0; y < seq.rows; y++)
{
for(int x = 0; x<seq.cols ; x++)
{
fin >> a;
seq.at<signed int>(y,x) = (signed int)a;
std::cout << a;
}
std::cout << std::endl;
}
hmm.printModel(TRGUESS,EMITGUESS,INITGUESS);
hmm.train(seq,1000,TRGUESS,EMITGUESS,INITGUESS);
hmm.printModel(TRGUESS,EMITGUESS,INITGUESS);
这里使用fin来读取我的其他代码中的观察结果。
答案 0 :(得分:3)
模型中的0意味着什么?在我看来,在您的数据中,两个状态都没有直接转换,它总是返回到状态0.在数据中尝试类似以下内容的状态转换序列。
作为一般规则:
我建议仅使用openCV >>在Matlab / octave中进行概念验证。这有两个原因。首先,您确切地知道您想要做什么以及它如何工作,并且不要浪费时间以“低级”语言实现和调试您的理论(与matlab相比)。 openCV中的调试算法非常耗时。
其次,当你知道你的东西按预期工作后,如果你实现它并遇到一个bug(openCV或C ++,python),你知道这不是你的理论,不是你的实现,它是框架。我已经两次使用计算机科学家从纸上直接实施(在被告知不要这样做之后),花费80%的剩余时间来调试算法而没有任何成功只发现:他们没有真的得到openCV的理论或一些子模块有一个小的错误,它会使他们的结果退化。
您提到的链接在matlab中使用了HMM工具箱。尝试在那里实施和理解你的问题,真的值得花时间。您不仅可以验证每个步骤的正确性,还可以在使用openCV代码后使用itermediate matrices。