特征向量:跟踪框位置相对轨迹中心的比值,角度,速度。
马尔科夫模型:
State Sequence, q1 q2 ...... qT
t个状态之间的转移可见,则这个时间序列的概率是πq1 × aq1q2 × ...... × aqT-1qT
隐马尔科夫模型:
状态不可见(隐藏),只能从观察值推测出,所以由观察值推测该时刻的状态有个观察值概率b.
πq1 × bq1( o1 ) × aq1q2 × bq2( o2 ) × ...... × aqT-1qT × bqT( oT ),
三个问题:
1。评价问题——前向后向算法
计算所有可能路径的概率。
前向:计算时向前运用结合律,意义??
2。解码问题
计算所有可能路径中概率最大的一条路径
3。学习问题
給定一個觀察序列o1 o2 ...... oT,更新ABΠ使得Evaluation Problem算得的機率盡量大。
程序:
解码问题:
double CHMM::Decode(vector<double*>& seq, vector<int>& state) { // Viterbi int size = (int)seq.size(); double* lastLogP = new double[m_stateNum]; double* currLogP = new double[m_stateNum]; int** path = new int*[size]; int i,j,t; // Init path[0] = new int[m_stateNum]; for ( i = 0; i < m_stateNum; i++) { currLogP[i] = LogProb(m_stateInit[i]) + LogProb(m_stateModel[i]->GetProbability(seq[0])); path[0][i] = -1; } // Recursion for ( t = 1; t < size; t++) //对每一个观测,求属于每个状态的当前最大累加概率 { path[t] = new int[m_stateNum]; double* temp = lastLogP; lastLogP = currLogP; currLogP = temp; for ( i = 0; i < m_stateNum; i++) { currLogP[i] = -1e308; // Searching the max for last state. for ( j = 0; j < m_stateNum; j++) { double l = lastLogP[j] + LogProb(m_stateTran[j][i]); if (l > currLogP[i]) { currLogP[i] = l; path[t][i] = j; } } currLogP[i] += LogProb(m_stateModel[i]->GetProbability(seq[t])); } } // Termination int finalState = 0; double prob = -1e308; for ( i = 0; i < m_stateNum; i++) { if (currLogP[i] > prob) { prob = currLogP[i]; finalState = i; } } // Decode state.push_back(finalState); for ( t = size - 2; t >=0; t--) { int stateIndex = path[t+1][state.back()]; state.push_back(stateIndex); } // Reverse the state list reverse(state.begin(), state.end()); // Clean up delete[] lastLogP; delete[] currLogP; for ( i = 0; i < size; i++) { delete[] path[i]; } delete[] path; prob = exp(prob / size); return prob; }
训练问题:
init:把所有样本的每个序列的特征值平均分给每个状态,然后用混合高斯模型表征每个状态。
train:先用decode解码,得到该序列一条概率最大的路径,对路径上所有出现的状态转移进行累积,最后两个状态之间的转移数除以该状态转移到其它所有状态移总数,得到的比值即为状态转移概率和初始状态概率。迭代直到误差小于0.001
/* SampleFile: <size><dim><seq_size><seq_data>...<seq_size>...*/ void CHMM::Init(const char* sampleFileName) { //--- Debug ---// //DumpSampleFile(sampleFileName); // Check the sample file ifstream sampleFile(sampleFileName, ios_base::binary); assert(sampleFile); int i,j; int size = 0; int dim = 0; sampleFile.read((char*)&size, sizeof(int)); //读样本数 sampleFile.read((char*)&dim, sizeof(int)); //读取特征维数 assert(size >= 3); assert(dim == m_stateModel[0]->GetDimNum()); //这里为从左到右型,第一个状态的初始概率为0.5, 其他状态的初始概率之和为0.5, //每个状态到自身的转移概率为0.5, 到下一个状态的转移概率为0.5. //此处的初始化主要是对混合高斯模型进行初始化 for ( i = 0; i < m_stateNum; i++) { // The initial probabilities if(i == 0) m_stateInit[i] = 0.5; else m_stateInit[i] = 0.5 / float(m_stateNum-1); // The transition probabilities for ( j = 0; j <= m_stateNum; j++) { if((i == j)||( j == i+1)) m_stateTran[i][j] = 0.5; } } vector<double*> *gaussseq; gaussseq= new vector<double*>[m_stateNum]; for ( i = 0; i < size; i++)//处理每个样本产生的特征序列 { int seq_size = 0; sampleFile.read((char*)&seq_size, sizeof(int)); //序列的长度 double r = float(seq_size)/float(m_stateNum); //每个状态有r个dim维的特征向量 for ( j = 0; j < seq_size; j++) { double* x = new double[dim]; sampleFile.read((char*)x, sizeof(double) * dim); //把特征序列平均分配给每个状态 gaussseq[int(j/r)].push_back(x); } } char** stateFileName = new char*[m_stateNum]; ofstream* stateFile = new ofstream[m_stateNum]; int* stateDataSize = new int[m_stateNum]; for ( i = 0; i < m_stateNum; i++) { stateFileName[i] = new char[20]; ostrstream str(stateFileName[i], 20); str << "chmm_s" << i << ".tmp" << '