00001 #include "LeftToRightHMM.h"
00002
00003 LeftToRightHMM::LeftToRightHMM(size_t nStates, size_t alphabetSize) :
00004 m_nStates(nStates),
00005 m_transitionProps(nStates, nStates),
00006 m_outputProps(nStates, alphabetSize),
00007 m_trelis(1,1)
00008 {
00009
00010 size_t i, j;
00011 for (i = 0; i < nStates; ++i) {
00012 for (j = i; j < nStates; ++j) {
00013 m_transitionProps[i][j] = 1.0 / static_cast<double>(nStates - i);
00014 }
00015 for (j = 0; j < alphabetSize; ++j) {
00016 m_outputProps[i][j] = 1 / static_cast<double>(alphabetSize);
00017 }
00018 }
00019 }
00020
00021 double LeftToRightHMM::evaluate(Observation &obs)
00022 {
00023 forwardTrelis(obs);
00024 return m_trelis[obs.size()][m_nStates-1];
00025 }
00026
00027 void LeftToRightHMM::train(Observation &obs, size_t maxIterations)
00028 {
00029 Matrix<double> alpha(obs.size() + 1, m_nStates, 0);
00030 Matrix<double> beta(obs.size() + 1, m_nStates, 0);
00031
00032 std::vector<Matrix<double> > xi;
00033 for (size_t i = 0; i < obs.size(); ++i) {
00034 xi.push_back(Matrix<double>(m_nStates, m_nStates, 0));
00035 }
00036
00037 for (size_t iteration = 0; iteration < maxIterations; ++iteration) {
00038 calcXi(obs, alpha, beta, xi);
00039 adjustParameters(obs, xi);
00040 }
00041 }
00042
00043 void LeftToRightHMM::calcXi(Observation &obs,
00044 Matrix<double> &alpha,
00045 Matrix<double> &beta,
00046 std::vector<Matrix<double> > &xi)
00047 {
00048 Observation::iterator it;
00049 size_t t, i, j;
00050 double obsPropability = evaluate(obs);
00051
00052 alpha = m_trelis;
00053 backwardTrelis(obs);
00054 beta = m_trelis;
00055 for (t = 0, it = obs.begin(); t < obs.size() && it != obs.end(); ++t, ++it) {
00056 for (i = 0; i < m_nStates; ++i) {
00057 for (j = 0; j < m_nStates; ++j) {
00058 xi[t][i][j] = alpha[t][i]
00059 * m_transitionProps[i][j]
00060 * m_outputProps[j][*it]
00061 * beta[t+1][j]
00062 / obsPropability;
00063 }
00064 }
00065 }
00066 }
00067
00068 void LeftToRightHMM::adjustParameters(Observation &obs,
00069 std::vector<Matrix<double> > &xi)
00070 {
00071 Observation::iterator it;
00072 size_t t, i, j, k;
00073 double divident, divisor;
00074
00075 for (i = 0; i < m_nStates; ++i) {
00076 for (j = 0; j < m_nStates; ++j) {
00077 divident = divisor = 0;
00078 for (t = 0; t < obs.size(); ++t) {
00079 divident += xi[t][i][j];
00080 for (k = 0; k < m_nStates; ++k) {
00081 divisor += xi[t][i][k];
00082 }
00083 m_transitionProps[i][j] = divident / divisor;
00084 }
00085 }
00086 }
00087
00088
00089 for (j = 0; j < m_nStates; ++j) {
00090 for (k = 0; k < m_outputProps.getM(); ++k) {
00091 divident = divisor = 0;
00092 for (i = 0; i < m_nStates; ++i) {
00093 for (t = 0; t < obs.size(); ++t) {
00094 if (obs[t] == static_cast<int>(k))
00095 divident += xi[t][i][j];
00096 divisor += xi[t][i][j];
00097 }
00098 }
00099 m_outputProps[j][k] = divident / divisor;
00100 }
00101 }
00102 }
00103
00104 Matrix<double> &LeftToRightHMM::forwardTrelis(Observation &obs)
00105 {
00106 m_trelis = Matrix<double>(obs.size() + 1, m_nStates, 0);
00107
00108 m_trelis[0][0] = 1;
00109
00110
00111 Observation::iterator it;
00112 size_t t = 1, j, i;
00113 for (it = obs.begin(); t <= obs.size() && it != obs.end(); ++it, ++t) {
00114 for (j = 0; j < m_nStates; ++j) {
00115 for (i = 0; i < m_nStates; ++i) {
00116 m_trelis[t][j] += m_trelis[t-1][i] * m_transitionProps[i][j];
00117 }
00118 m_trelis[t][j] *= m_outputProps[j][*it];
00119 }
00120 }
00121 return m_trelis;
00122 }
00123
00124 Matrix<double>& LeftToRightHMM::backwardTrelis(Observation &obs)
00125 {
00126 m_trelis = Matrix<double>(obs.size()+1, m_nStates, 0);
00127
00128 m_trelis[m_nStates-1][obs.size()] = 1;
00129
00130
00131 Observation::reverse_iterator it;
00132 size_t t = obs.size()-1, i, j;
00133 for (it = obs.rbegin(); t >= 0 && it != obs.rend(); ++it, --t) {
00134 for (i = 0; i < m_nStates; ++i) {
00135 for (j = 0; j < m_nStates; ++j) {
00136 m_trelis[t][i] += m_trelis[t+1][j] * m_transitionProps[i][j]
00137 * m_outputProps[j][*it];
00138 }
00139 }
00140 }
00141 return m_trelis;
00142 }
00143