动态手势的隐马尔可夫模型训练
Hidden Markov Model Training for Dynamic Gestures?
我知道有很多与隐马尔可夫模型相关的材料,我也阅读了与该主题相关的所有问题和答案。我了解它是如何工作的以及如何训练它,但是在尝试为简单的动态手势训练它时,我无法解决以下问题。
我正在使用HMM实现OpenCV我已经在这里研究了以前提出的问题和答案。这确实帮助我理解和使用马尔可夫模型。
我总共有两个动态手势,都是对称的(向左滑动和向右滑动)总共有 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
在此序列中,您可以看到向左轻扫和向右轻扫手势的模式。
为了训练隐藏马尔可夫模型,我使用以下值启动它,然后调用训练函数以获取输出:
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
在我的识别程序中使用此模型,我没有得到结果。我希望系统保持空状态,除非检测到其中一个手势。在转换和发射矩阵中,我给出了这两个手势的猜测值。
你认为我可能做错了什么?有什么指示或帮助吗?
最后,这是我用于执行此操作的代码(如果有人想看一下)
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。在数据中尝试类似以下内容的状态转换序列。
- 1 1
- 1 1 2 2 2 2 3 3 3 3 4 4 4 4 4
- 1 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 1
- 1 2 2 3 3 4 4 0 0 0 0 0 04
- 4 3 3 2 2 1 1 0 0 0 0 0 0 0 0 0 0 04 4
- 4 3 3 3 2 2 2 2 2 1 1 1 1 1
作为一般规则:
我建议只有在你在Matlab/octave中进行了概念验证之后才使用openCV。这有两个原因。首先,你确切地知道你想做什么以及它是如何工作的,不要浪费你的时间用"低级"语言(与matlab相比)实现和调试你的理论。在 openCV 中调试算法非常耗时。
其次,在你知道你的东西按预期工作之后,如果你实现它并遇到一个错误(openCV或C++,python),你知道这不是你的理论,不是你的实现,而是框架。我已经发生了两次雇用的计算机科学家直接从论文中实现(在被告知不要这样做之后),花费 80% 的剩余时间来调试算法而没有任何成功,只是发现:他们并没有真正理解理论或 openCV 的某些子模块有一个轻微的错误,这退化了他们的结果。
您提到的链接使用了 matlab 中的 HMM 工具箱。尝试在那里实施和理解您的问题,这真的值得花时间。您不仅可以验证每个步骤的正确性,还可以在拥有工作模型后将迭代矩阵与 openCV 代码一起使用。
- 如果包含映射的静态库与可执行文件和动态库链接,静态映射(变量)是否会被多次释放?
- 从 C 可执行文件加载动态库时收到错误C++"undefined symbol"
- 隐式可转换参数,但属于引用类型
- 调用函数一次用于动态链接库,一次从可执行文件调用函数
- 我可以隐式地创建一个琐碎的可复制类型吗
- 如果我在 Linux 上更改C++动态共享库,而我的可执行程序在其上使用,会发生什么
- C++具有公共 API 的动态库,可遮盖依赖库
- 英特尔并行工作室 2015 C++中的 2D 动态分配全局阵列
- 在动态加载的位置无关的可执行文件中分离错误
- C++模板的对象代码是否在可执行文件和动态库中重复?
- 隐马尔可夫模型-在C++中实现参数绑定
- C++中的隐马尔可夫模型
- 动态手势的隐马尔可夫模型训练
- 从仿真数据构建非常大的马尔可夫链的最佳/最快方法是什么?
- 了解我有多少内存可用于一个动态向量c++
- 使用多个连续观测变量的隐马尔可夫模型
- Netbeans/C++:将2个项目链接在一起(可执行文件/动态库)
- 在c++中使用隐马尔可夫模型计算和校正误码
- 一个C++实现的隐马尔可夫模型林安装错误
- 用图形界面在c++中实现离散马尔可夫链模拟