gradescent.c

来自「General Hidden Markov Model Library 一个通用」· C语言 代码 · 共 556 行 · 第 1/2 页

C
556
字号
/*********************************************************************************       This file is part of the General Hidden Markov Model Library,*       GHMM version 0.8_beta1, see http://ghmm.org**       Filename: ghmm/ghmm/gradescent.c*       Authors:  Janne Grunau, Alexander Riemer**       Copyright (C) 1998-2004 Alexander Schliep*       Copyright (C) 1998-2001 ZAIK/ZPR, Universitaet zu Koeln*       Copyright (C) 2002-2004 Max-Planck-Institut fuer Molekulare Genetik,*                               Berlin**       Contact: schliep@ghmm.org**       This library is free software; you can redistribute it and/or*       modify it under the terms of the GNU Library General Public*       License as published by the Free Software Foundation; either*       version 2 of the License, or (at your option) any later version.**       This library is distributed in the hope that it will be useful,*       but WITHOUT ANY WARRANTY; without even the implied warranty of*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU*       Library General Public License for more details.**       You should have received a copy of the GNU Library General Public*       License along with this library; if not, write to the Free*       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA***       This file is version $Revision: 1713 $*                       from $Date: 2006-10-16 16:06:28 +0200 (Mon, 16 Oct 2006) $*             last change by $Author: grunau $.********************************************************************************/#ifdef HAVE_CONFIG_H#  include "../config.h"#endif#include <stdio.h>#include <stdlib.h>#include <math.h>#include "ghmm.h"#include "mes.h"#include "mprintf.h"#include "matrix.h"#include "model.h"#include "foba.h"#include "gradescent.h"#include "ghmm_internals.h"static double compute_performance (ghmm_dmodel * mo, ghmm_dseq * sq);/*----------------------------------------------------------------------------*/static void gradient_descent_gfree (double **matrix_b, double *matrix_a,                             double *matrix_pi, int N){#define CUR_PROC "gradient_descent_gfree"  int i;  if (matrix_b)    for (i = 0; i < N; i++) {      m_free (matrix_b[i]);    }  m_free (matrix_b);  m_free (matrix_a);  m_free (matrix_pi);#undef CUR_PROC}/*----------------------------------------------------------------------------*//** allocates memory for m and n matrices: */static int gradient_descent_galloc (double ***matrix_b, double **matrix_a,                             double **matrix_pi, ghmm_dmodel * mo){#define CUR_PROC "gradient_descent_galloc"  int i;  /* first allocate memory for matrix_b */  ARRAY_MALLOC (*matrix_b, mo->N);  for (i = 0; i < mo->N; i++)    ARRAY_CALLOC ((*matrix_b)[i], ghmm_ipow (mo, mo->M, mo->order[i] + 1));  /* matrix_a(i,j) = matrix_a[i*mo->N+j] */  ARRAY_CALLOC (*matrix_a, mo->N * mo->N);  /* allocate memory for matrix_pi */  ARRAY_CALLOC (*matrix_pi, mo->N);  return 0;STOP:     /* Label STOP from ARRAY_[CM]ALLOC */  gradient_descent_gfree (*matrix_b, *matrix_a, *matrix_pi, mo->N);  return -1;#undef CUR_PROC}/*----------------------------------------------------------------------------*//**   computes matrices of n and m variables (expected values for how often a   certain parameter from A or B is used)   computes Baum-Welch variables implicit    @return                 0/-1 success/error   @param mo:              pointer to a ghmm_dmodel   @param alpha:           matrix of forward variables   @param backward:        matrix of backward variables   @param scale:           scaling vector from forward-backward-algorithm   @param seq:             sequence in internal representation   @param seq_len:         length of sequence   @param matrix_b:        matrix for parameters from B (n_b or m_b)   @param matrix_a:        matrix for parameters from A (n_a or m_a)   @param vec_pi:          vector for parameters in PI (n_pi or m_pi) */int ghmm_dmodel_label_gradient_expectations (ghmm_dmodel* mo, double **alpha,                                     double **beta, double *scale, int *seq,                                     int seq_len, double **matrix_b,                                     double *matrix_a, double *vec_pi){#define CUR_PROC "ghmm_dmodel_label_gradient_expectations"  int h, i, j, t;  int size, j_id, e_index;  double gamma, xi;  double foba_sum;  /* initialise matrices with zeros */  for (i = 0; i < mo->N; i++) {    for (j = 0; j < mo->N; j++)      matrix_a[i * mo->N + j] = 0;    size = ghmm_ipow (mo, mo->M, mo->order[i] + 1);    for (h = 0; h < size; h++)      matrix_b[i][h] = 0;  }  for (t = 0; t < seq_len; t++) {    /* sum products of forward and backward variables over all states: */    foba_sum = 0.0;    for (i = 0; i < mo->N; i++)      foba_sum += alpha[t][i] * beta[t][i];    if (GHMM_EPS_PREC > fabs (foba_sum)) {      printf        ("gradescent_compute_expect: foba_sum (%g) smaller as EPS_PREC (%g). t = %d.\n",         foba_sum, GHMM_EPS_PREC, t);      return -1;    }    for (i = 0; i < mo->N; i++) {      /* compute gamma implicit */      gamma = alpha[t][i] * beta[t][i] / foba_sum;      /* n_pi is easiest: n_pi(i) = gamma(0,i) */      if (0 == t)        vec_pi[i] = gamma;      /* n_b(i,c) = sum[t, hist(t)=c | gamma(t,i)] / sum[t | gamma(t,i)] */      e_index = get_emission_index (mo, i, seq[t], t);      if (-1 != e_index)        matrix_b[i][e_index] += gamma;    }    /* updating history, xi needs the right e_index for the next state */    update_emission_history (mo, seq[t]);    for (i = 0; i < mo->N; i++) {      /* n_a(i,j) = sum[t=0..T-2 | xi(t,i,j)] / sum[t=0..T-2 | gamma(t,i)] */      /* compute xi only till the state before the last */      for (j = 0; (j < mo->s[i].out_states) && (t < seq_len - 1); j++) {        j_id = mo->s[i].out_id[j];        /* compute xi implicit */	xi = 0;        e_index = get_emission_index (mo, j_id, seq[t + 1], t + 1);        if (e_index != -1)          xi = alpha[t][i] * beta[t + 1][j_id] * mo->s[i].out_a[j]            * mo->s[j_id].b[e_index] / (scale[t + 1] * foba_sum);        matrix_a[i * mo->N + j_id] += xi;      }    }  }  return 0;#undef CUR_PROC}/*----------------------------------------------------------------------------*/static double compute_performance (ghmm_dmodel * mo, ghmm_dseq * sq){#define CUR_PROC "compute_performance"  int k, seq_len, success = 1;  /* log P[O | lambda, labeling] as computed by the forward algorithm */  double log_p;  /* sum over log P (calculated by forward_label) for all sequences     used to compute the performance of the training */  double log_p_sum = 0.0;  /* loop over all sequences */  for (k = 0; k < sq->seq_number && success; k++) {    success = 0;    seq_len = sq->seq_len[k];    if (-1 !=        ghmm_dmodel_label_logp (mo, sq->seq[k], sq->state_labels[k], seq_len,                         &log_p)) {      success = 1;      log_p_sum += log_p;      if (-1 != ghmm_dmodel_logp (mo, sq->seq[k], seq_len, &log_p))        log_p_sum -= log_p;      else {        printf ("ghmm_dmodel_logp error in sequence %d, length: %d\n", k,                seq_len);        success = 0;      }    }    else      printf ("ghmm_dl_logp error in sequence %d, length: %d\n", k,              seq_len);  }  /* return log_p_sum in success or +1.0 a probality of 0.0 on error */  if (success)    return log_p_sum;  else    return 1.0;#undef CUR_PROC}/*----------------------------------------------------------------------------*//**   Trains the model with a set of annotated sequences using gradient descent.   Model must not have silent states. (one iteration)   @return            0/-1 success/error   @param mo:         pointer to a ghmm_dmodel   @param sq:         struct of annotated sequences   @param eta:        training parameter for gradient descent */static int gradient_descent_onestep (ghmm_dmodel * mo, ghmm_dseq * sq, double eta){#define CUR_PROC "gradient_descent_onestep"  int g, h, i, j, k;  int seq_len, j_id, hist, size;  /* expected usage of model parameters (A and B entries) */  double *m_pi, *n_pi, *m_a, *n_a;  double **m_b, **n_b;  /* forward & backward variables w/ their scaling vector */  double **alpha, **beta, *scale;  /* variables to store values associated with the algorithm */  double pi_sum, a_row_sum, b_block_sum, gradient;  /* log P[O | lambda, labeling] as computed by the forward algorithm */  double log_p;  /* allocate memory for the parameters used for reestimation */  if (-1 == gradient_descent_galloc (&m_b, &m_a, &m_pi, mo))    return -1;  if (-1 == gradient_descent_galloc (&n_b, &n_a, &n_pi, mo))

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?