3

隠れマルコフ モデルに関連する多くの資料があることを知っており、このトピックに関連するすべての質問と回答も読みました。それがどのように機能し、どのようにトレーニングできるかは理解していますが、単純な動的ジェスチャー用にトレーニングしようとすると、次の問題を解決できません。

OpenCV の HMM 実装を使用しています。 以前に寄せられた質問を調べて、ここで回答しました。これは、マルコフモデルを理解して使用するのに本当に役立ちました。

私は合計 2 つの動的ジェスチャを持っていますが、どちらも対称的です (左にスワイプし、右にスワイプ)。合計 5 つの観察があり、そのうち 4 つはジェスチャの異なる段階であり、5 つ目はこれらの段階が発生していないときの観察です。

左にスワイプするジェスチャは、次の観察で構成されます: 1->2->3->4 (左にスワイプ状態をトリガーする必要があります) 同様に、右にスワイプするジェスチャは、次の観察で構成されます: 4->3->2->1

私は25のシーケンスを持っています。Baum-Welch アルゴリズムを使用して隠れマルコフ モデルをトレーニングするために使用されるシーケンスごとに 20 個の観測値を取得しています。

入力シーケンスは次のとおりです。

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

このモデルを認識プログラムで使用しても、結果が得られません。ジェスチャの 1 つが検出されない限り、システムを NULL 状態のままにしたい。トランジションとエミッションのマトリックスでは、これら両方のジェスチャの推測値を示しました。

私が何を間違っていると思いますか?ポインタやヘルプはありますか?

最後に、これを行うために使用しているコードを次に示します (誰かが見たい場合)

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 は、他のコードから得た観察結果を読み取るために使用されます。

4

1 に答える 1

3

モデルで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

原則として:

Matlab / octaveで概念実証を行ったでのみ、openCVを使用することをお勧めします。これには2つの理由があります。まず第一に、あなたはあなたが何をしたいのか、そしてそれがどのように機能するのかを正確に知っています、そしてあなたの理論を「低」レベルの言語で実装してデバッグするのにあなたの時間を無駄にしないでください(matlabと比較して)。openCVでのアルゴリズムのデバッグは本当に時間がかかります。

次に、自分のものが期待どおりに機能することを知った後、それを実装してバグ(openCVまたはC ++、python)に遭遇した場合、それは理論ではなく、実装ではなく、フレームワークであることがわかります。私はすでに2回、論文から直接実装されたコンピューター科学者を雇いました(そうしないように言われた後)、残りの時間の80%を費やしてアルゴリズムをデバッグしましたが、成功せずにそれを見つけました:彼らはしませんでした理論を実際に取得するか、openCVの一部のサブモジュールにわずかなバグがあり、結果が劣化しました。

あなたが言及したリンクは、matlabのHMMツールボックスを使用しています。そこで問題を実装して理解してみてください。時間を費やす価値はあります。各ステップが正しいかどうかを検証できるだけでなく、作業モデルを作成した後、openCVコードで反復行列を使用できます。

于 2012-08-22T12:36:54.707 に答える