matthiasm@0
|
1 #include "SparseHMM.h"
|
matthiasm@0
|
2 #include <vector>
|
matthiasm@0
|
3 #include <cstdio>
|
matthiasm@0
|
4 #include <iostream>
|
matthiasm@0
|
5
|
matthiasm@0
|
6 using std::vector;
|
matthiasm@0
|
7 using std::pair;
|
matthiasm@0
|
8
|
matthiasm@0
|
9 const vector<double>
|
matthiasm@0
|
10 SparseHMM::calculateObsProb(const vector<pair<double, double> > data)
|
matthiasm@0
|
11 {
|
matthiasm@0
|
12 // dummy (virtual?) implementation to be overloaded
|
matthiasm@0
|
13 return(vector<double>());
|
matthiasm@0
|
14 }
|
matthiasm@0
|
15
|
matthiasm@0
|
16 const std::vector<int>
|
matthiasm@0
|
17 SparseHMM::decodeViterbi(std::vector<vector<double> > obsProb,
|
matthiasm@0
|
18 vector<double> *scale)
|
matthiasm@0
|
19 {
|
matthiasm@0
|
20 size_t nState = init.size();
|
matthiasm@0
|
21 size_t nFrame = obsProb.size();
|
matthiasm@0
|
22
|
matthiasm@0
|
23 // check for consistency
|
matthiasm@0
|
24 size_t nTrans = transProb.size();
|
matthiasm@0
|
25
|
matthiasm@0
|
26 // declaring variables
|
matthiasm@0
|
27 std::vector<double> delta = std::vector<double>(nState);
|
matthiasm@0
|
28 std::vector<double> oldDelta = std::vector<double>(nState);
|
matthiasm@0
|
29 vector<vector<int> > psi; // "matrix" of remembered indices of the best transitions
|
matthiasm@0
|
30 vector<int> path = vector<int>(nFrame, nState-1); // the final output path (current assignment arbitrary, makes sense only for Chordino, where nChord-1 is the "no chord" label)
|
matthiasm@0
|
31
|
matthiasm@0
|
32 double deltasum = 0;
|
matthiasm@0
|
33
|
matthiasm@0
|
34 // initialise first frame
|
matthiasm@0
|
35 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
36 {
|
matthiasm@0
|
37 oldDelta[iState] = init[iState] * obsProb[0][iState];
|
matthiasm@0
|
38 // std::cerr << iState << " ----- " << init[iState] << std::endl;
|
matthiasm@0
|
39 deltasum += oldDelta[iState];
|
matthiasm@0
|
40 }
|
matthiasm@0
|
41
|
matthiasm@0
|
42 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
43 {
|
matthiasm@0
|
44 oldDelta[iState] /= deltasum; // normalise (scale)
|
matthiasm@0
|
45 // std::cerr << oldDelta[iState] << std::endl;
|
matthiasm@0
|
46 }
|
matthiasm@0
|
47
|
matthiasm@0
|
48 scale->push_back(1.0/deltasum);
|
matthiasm@0
|
49 psi.push_back(vector<int>(nState,0));
|
matthiasm@0
|
50
|
matthiasm@0
|
51 // rest of forward step
|
matthiasm@0
|
52 for (size_t iFrame = 1; iFrame < nFrame; ++iFrame)
|
matthiasm@0
|
53 {
|
matthiasm@0
|
54 deltasum = 0;
|
matthiasm@0
|
55 psi.push_back(vector<int>(nState,0));
|
matthiasm@0
|
56
|
matthiasm@0
|
57 // calculate best previous state for every current state
|
matthiasm@0
|
58 size_t fromState;
|
matthiasm@0
|
59 size_t toState;
|
matthiasm@0
|
60 double currentTransProb;
|
matthiasm@0
|
61 double currentValue;
|
matthiasm@0
|
62
|
matthiasm@0
|
63 // this is the "sparse" loop
|
matthiasm@0
|
64 for (size_t iTrans = 0; iTrans < nTrans; ++iTrans)
|
matthiasm@0
|
65 {
|
matthiasm@0
|
66 fromState = from[iTrans];
|
matthiasm@0
|
67 toState = to[iTrans];
|
matthiasm@0
|
68 currentTransProb = transProb[iTrans];
|
matthiasm@0
|
69
|
matthiasm@0
|
70 currentValue = oldDelta[fromState] * currentTransProb;
|
matthiasm@0
|
71 if (currentValue > delta[toState])
|
matthiasm@0
|
72 {
|
matthiasm@0
|
73 delta[toState] = currentValue; // will be multiplied by the right obs later!
|
matthiasm@0
|
74 psi[iFrame][toState] = fromState;
|
matthiasm@0
|
75 }
|
matthiasm@0
|
76 }
|
matthiasm@0
|
77
|
matthiasm@0
|
78 for (size_t jState = 0; jState < nState; ++jState)
|
matthiasm@0
|
79 {
|
matthiasm@0
|
80 delta[jState] *= obsProb[iFrame][jState];
|
matthiasm@0
|
81 deltasum += delta[jState];
|
matthiasm@0
|
82 }
|
matthiasm@0
|
83
|
matthiasm@0
|
84 if (deltasum > 0)
|
matthiasm@0
|
85 {
|
matthiasm@0
|
86 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
87 {
|
matthiasm@0
|
88 oldDelta[iState] = delta[iState] / deltasum; // normalise (scale)
|
matthiasm@0
|
89 delta[iState] = 0;
|
matthiasm@0
|
90 }
|
matthiasm@0
|
91 scale->push_back(1.0/deltasum);
|
matthiasm@0
|
92 } else
|
matthiasm@0
|
93 {
|
matthiasm@0
|
94 std::cerr << "WARNING: Viterbi has been fed some zero probabilities, at least they become zero in combination with the model." << std::endl;
|
matthiasm@0
|
95 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
96 {
|
matthiasm@0
|
97 oldDelta[iState] = 1.0/nState;
|
matthiasm@0
|
98 delta[iState] = 0;
|
matthiasm@0
|
99 }
|
matthiasm@0
|
100 scale->push_back(1.0);
|
matthiasm@0
|
101 }
|
matthiasm@0
|
102 }
|
matthiasm@0
|
103
|
matthiasm@0
|
104 // initialise backward step
|
matthiasm@0
|
105 double bestValue = 0;
|
matthiasm@0
|
106 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
107 {
|
matthiasm@0
|
108 double currentValue = oldDelta[iState];
|
matthiasm@0
|
109 if (currentValue > bestValue)
|
matthiasm@0
|
110 {
|
matthiasm@0
|
111 bestValue = currentValue;
|
matthiasm@0
|
112 path[nFrame-1] = iState;
|
matthiasm@0
|
113 }
|
matthiasm@0
|
114 }
|
matthiasm@0
|
115
|
matthiasm@0
|
116 // rest of backward step
|
matthiasm@0
|
117 for (int iFrame = nFrame-2; iFrame != -1; --iFrame)
|
matthiasm@0
|
118 {
|
matthiasm@0
|
119 path[iFrame] = psi[iFrame+1][path[iFrame+1]];
|
matthiasm@0
|
120 }
|
matthiasm@0
|
121
|
matthiasm@0
|
122 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
123 {
|
matthiasm@0
|
124 // std::cerr << psi[2][iState] << std::endl;
|
matthiasm@0
|
125 }
|
matthiasm@0
|
126
|
matthiasm@0
|
127 return path;
|
matthiasm@0
|
128 }
|