动态手势的隐马尔可夫模型训练?

2023-12-08

我知道有很多与隐马尔可夫模型相关的材料,我也阅读了与该主题相关的所有问题和答案。我了解它的工作原理以及如何训练它,但是我无法解决在尝试训练它进行简单的动态手势时遇到的以下问题。

我在用OpenCV 的 HMM 实现我已经研究过之前提出的问题和答案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 

在此序列中,您可以看到向左滑动和向右滑动手势的模式。

为了训练隐马尔可夫模型,我使用以下值初始化它,然后调用训练函数来获取输出:

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 在你的模型中意味着什么?在我看来,在您的数据中,两种状态都没有直接转换,它总是返回到状态 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 0 1 1 2 2 3 3 4 4 0 0 0 0 0
  • 4 4 3 3 2 2 1 1 0 0 0 0 0 0 0 0 0
  • 4 4 4 3 3 3 2 2 2 2 2 1 1 1 1 1 1

作为基本规则:

我建议仅使用 openCVafter您已在 Matlab/octave 中进行了概念验证。这有两个原因。首先,您确切地知道自己想要做什么以及它是如何工作的,并且不要浪费时间用“低”级语言(与 matlab 相比)来实现和调试您的理论。在openCV中调试算法确实非常耗时。

其次,当你知道你的东西按预期工作后,如果你实现它并遇到错误(openCV 或 C++、python),你知道这不是你的理论,不是你的实现,而是框架。我已经遇到过两次雇佣计算机科学家直接从论文中实现的情况(在被告知不要这样做之后),花费了 80% 的剩余时间来调试算法,但没有取得任何成功,结果却发现:他们没有真正了解理论或 openCV 的某些子模块有一个小错误,导致结果退化。

您提到的链接使用 matlab 中的 HMM 工具箱。尝试在那里实现并理解你的问题,这确实值得花时间。您不仅可以验证每个步骤的正确性,还可以在拥有工作模型后将中间矩阵与 openCV 代码一起使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态手势的隐马尔可夫模型训练? 的相关文章

随机推荐