📄 gmm.cpp
字号:
// GMM.cpp: implementation of the CGMM class.
//
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "GMM.h"
#define TAGNUM 15
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGMM::CGMM()
{
bLoaded = false;
}
CGMM::~CGMM()
{
FreeGMMSet();
}
//--------------------------------------------------------------
// Load GMM from the definition files
// RETURN VALUE:
// 0 : Fail
// 1 :
int CGMM::LoadGMMSet(char *fname)
{
char *cTags[TAGNUM] = {"BEGINHMM","ENDHMM","GCONST","MEAN","MIXTURE",
"NULLD","NUMMIXES","NUMSTATES","STATE","STREAM",
"STREAMINFO","SWEIGHTS","TRANSP","VARIANCE","VECSIZE"};
char ch,cbuf[100];
FILE *fp;
int ii,ij,ibuf;
int iCurStream=0 , iCurMixture=0;
double fdete;
bool bNUMMIXES = false;
if ((fp=fopen(fname,"r"))==NULL)
{
printf(" *** Error in opening \"%s\"! ::: CGMM::LoadGMMSet()\n",fname);
exit(-1);
}
while (!feof(fp))
{
ch=getc(fp);
switch (ch) {
case '~':
ch=getc(fp);
switch (ch) {
case 'o':
break;
case 'h':
fscanf(fp,"%s",inst.cname);
break;
default:
printf(" *** Unknown MICRO in \"%s\"! ::: CGMM::LoadGMMSet()\n",fname);
fclose(fp);return 0;
}
getc(fp);
break;
case '<':
ii = 0;
while ((cbuf[ii]=getc(fp))!='>' && ii<20) ii++;
cbuf[ii]=0;
if (ii>=20)
{
printf(" *** Too long TAG in \"%s\"! ::: CGMM::LoadGMMSet()\n",fname);
fclose(fp);return 0;
}
for (ii=0;ii<TAGNUM;ii++) // TAGNUM = 15
{
if (strcmp(cbuf,cTags[ii])==0)
break;
}
switch (ii) {
case 10: // <STREAMINFO>
fscanf(fp,"%d",&ibuf); // number of streams
inst.iStreamInfo = new int[ibuf+1]; // alloc mem
inst.iStreamInfo[0] = ibuf;
for (ii=0;ii<ibuf;ii++)
fscanf(fp,"%d",inst.iStreamInfo+ii+1);
inst.iNumMixtures = new int[inst.iStreamInfo[0]];
inst.dSWeights = new double[inst.iStreamInfo[0]];
inst.dDet = new double*[inst.iStreamInfo[0]];
inst.dMixtureWeight = new double*[inst.iStreamInfo[0]];
inst.dMean = new double**[inst.iStreamInfo[0]];
inst.dCovar = new double**[inst.iStreamInfo[0]];
getc(fp); // read the tailing '\n', begin a new line
break;
case 14: // <VECSIZE>
fscanf(fp,"%d",&inst.iVectorSize);
break;
case 5: // <NULLD>
ch = getc(fp);
ii = 0;
while ((cbuf[ii]=getc(fp))!='>' && ii<20) ii++;
cbuf[ii]=0;
if (ii>=20)
{
printf(" *** Too long TAG in \"%s\"! ::: CGMM::LoadGMMSet()\n",fname);
fclose(fp);return 0;
}
strcpy(inst.cparm,cbuf); // read the parameter's type, such as <MFCC_E>
getc(fp); // skip the '\n', begin a new line
break;
case 7 : // <NUMSTATES>
fscanf(fp,"%d\n",&inst.iNumStates); // Must be 3 in a GMM
if (inst.iNumStates!=3)
{
printf(" *** Not a GMM ! ::: CGMM::LoadGMMSet()\n",fname);
fclose(fp);return 0;
}
break;
case 8: // <STATE>
fscanf(fp,"%d\n",&ibuf);
break;
case 6: // <NUMMIXES>
for (ii=0;ii<inst.iStreamInfo[0];ii++)
{ // for each stream
fscanf(fp,"%d",inst.iNumMixtures+ii);
inst.dDet[ii] = new double[inst.iNumMixtures[ii]];
inst.dMixtureWeight[ii] = new double[inst.iNumMixtures[ii]];
inst.dMean[ii] = new double*[inst.iNumMixtures[ii]];
for (ij=0;ij<inst.iNumMixtures[ii];ij++) // for each mixture in every streams
inst.dMean[ii][ij] = new double[inst.iStreamInfo[ii+1]];
inst.dCovar[ii] = new double*[inst.iNumMixtures[ii]];
for (ij=0;ij<inst.iNumMixtures[ii];ij++) // for each misture in every streams
inst.dCovar[ii][ij] = new double[inst.iStreamInfo[ii+1]];
}
bNUMMIXES = true;
getc(fp);
break;
case 11: // <SWEIGHTS>
fscanf(fp,"%d\n",&ibuf);
// ASSERT(ibuf==inst.iStreamInfo[0]);
for (ii=0;ii<ibuf;ii++)
fscanf(fp,"%lf",&inst.dSWeights[ii]);
getc(fp);
break;
case 9: // <STREAM>
fscanf(fp,"%d\n",&iCurStream); // current stream
iCurStream--;
break;
case 4: // <MIXTURE>
fscanf(fp,"%d",&iCurMixture); // current mixture
iCurMixture--;
fscanf(fp,"%lf\n",&inst.dMixtureWeight[iCurStream][iCurMixture]);
break;
case 3: // <MEAN>
if (!bNUMMIXES)
{ // if there is no NUMMIXES tag (then no MIXTURE tags)
for (ii=0;ii<inst.iStreamInfo[0];ii++)
{ // for each stream
inst.iNumMixtures[ii] = 1;
inst.dDet[ii] = new double[inst.iNumMixtures[ii]];
inst.dMixtureWeight[ii] = new double[inst.iNumMixtures[ii]];
inst.dMixtureWeight[ii][0] = 1;
inst.dMean[ii] = new double*[inst.iNumMixtures[ii]];
for (ij=0;ij<inst.iNumMixtures[ii];ij++) // for each mixture in every streams
inst.dMean[ii][ij] = new double[inst.iStreamInfo[ii+1]];
inst.dCovar[ii] = new double*[inst.iNumMixtures[ii]];
for (ij=0;ij<inst.iNumMixtures[ii];ij++) // for each misture in every streams
inst.dCovar[ii][ij] = new double[inst.iStreamInfo[ii+1]];
}
}
fscanf(fp,"%d\n",&ibuf);
// ASSERT(ibuf==inst.iStreamInfo[iCurStream+1]);
for (ii=0;ii<ibuf;ii++)
fscanf(fp,"%lf",&inst.dMean[iCurStream][iCurMixture][ii]);
getc(fp);
break;
case 13: // <VARIANCE>
fscanf(fp,"%d\n",&ibuf);
// ASSERT(ibuf==inst.iStreamInfo[iCurStream+1]);
for (fdete=1,ii=0;ii<ibuf;ii++)
{
fscanf(fp,"%lf",&inst.dCovar[iCurStream][iCurMixture][ii]);
fdete *= inst.dCovar[iCurStream][iCurMixture][ii];
}
inst.dDet[iCurStream][iCurMixture] = fdete;
getc(fp);
break;
case 2:
case 1:
case 0:
case 12: // <GCONST>,<BEGINHMM>,<ENDHMM>,<TRANSP>
while((ch=getc(fp))!=10 && !feof(fp))
;
break;
default:
printf(" *** Unknown <TAG> ! ::: CGMM::LoadGMMSet()\n",fname);
fclose(fp);return 0;
}
default: ; // not begin with '~' or '<', skipping
}
}
fclose(fp);
bLoaded = true;
// Test output
int ik;
fp = fopen("output","w");
fprintf(fp,"~o\n<STREAMINFO> %d",inst.iStreamInfo[0]);
for (ii=0;ii<inst.iStreamInfo[0];ii++)
fprintf(fp," %d",inst.iStreamInfo[ii+1]);
fprintf(fp,"\n");
fprintf(fp,"<VECTERSIZE> %d<NULLD><%s>\n",inst.iVectorSize,inst.cparm);
fprintf(fp,"~h \"%s\"",inst.cname);
fprintf(fp,"<NUMSTATES> %d\n<NUMMIXES>",inst.iNumStates);
for (ii=0;ii<inst.iStreamInfo[0];ii++)
fprintf(fp," %d",inst.iNumMixtures[ii]);
fprintf(fp,"\n<SWEIGHTS> %d\n",inst.iStreamInfo[0]);
for (ii=0;ii<inst.iStreamInfo[0];ii++)
fprintf(fp," %f",inst.dSWeights[ii]);
fprintf(fp,"\n");
for (ii=0;ii<inst.iStreamInfo[0];ii++)
{
fprintf(fp,"<STREAM> %d\n",ii);
for (ij=0;ij<inst.iNumMixtures[ii];ij++)
{
fprintf(fp,"<MIXTURE> %d %f\n",ij,inst.dMixtureWeight[ii][ij]);
fprintf(fp,"<MEAN> %d\n",inst.iStreamInfo[ii+1]);
for (ik=0;ik<inst.iStreamInfo[ii+1];ik++)
fprintf(fp," %f",inst.dMean[ii][ij][ik]);
fprintf(fp,"\n<VARIANCE> %d\n",inst.iStreamInfo[ii+1]);
for (ik=0;ik<inst.iStreamInfo[ii+1];ik++)
fprintf(fp," %f",inst.dCovar[ii][ij][ik]);
fprintf(fp,"\n");
}
}
fprintf(fp,"<ENDHMM>\n");
fclose(fp);
return 1;
}
//--------------------------------------------------------------
// Free memory before exit
int CGMM::FreeGMMSet()
{
int ii,ij;
if (!bLoaded)
return 0;
for (ii=0;ii<inst.iStreamInfo[0];ii++)
{ // for each stream
for (ij=0;ij<inst.iNumMixtures[ii];ij++)
{ // for each mixture
delete[] inst.dMean[ii][ij];
delete[] inst.dCovar[ii][ij];
}
delete[] inst.dMean[ii];
delete[] inst.dCovar[ii];
delete[] inst.dDet[ii];
delete[] inst.dMixtureWeight[ii];
}
delete[] inst.dMean;
delete[] inst.dCovar;
delete[] inst.dDet;
delete[] inst.dMixtureWeight;
delete[] inst.iNumMixtures;
delete[] inst.dSWeights;
delete[] inst.iStreamInfo;
bLoaded = false;
return 1;
}
//---------------------------------------------------------------
// Calculate the output probility of the given dimension
// Scale : input value
// idx : absolute index
// dresult : buffer for prob of each mixture
// imix : length of the dresult, should be equal to the mixture
// of the given stream
int CGMM::LScaleProb(double Scale,int idx,double *dresult,int imix)
{
int ii,is,iv;
double dsqrt2pai = 2.506628275; // sqrt (2 * PAI)
double dexp,fcoe;
if (!bLoaded || idx>inst.iVectorSize)
return 0;
for (ii=0;ii<inst.iStreamInfo[0];ii++)
{
if (idx < inst.iStreamInfo[ii+1])
break;
idx -= inst.iStreamInfo[ii+1];
}
is = ii; iv = idx;
if (imix!=inst.iNumMixtures[is])
return 0;
for (ii=0;ii<imix;ii++)
{
fcoe = dsqrt2pai * sqrt(inst.dCovar[is][ii][iv]);
dexp = exp(-0.5 * (Scale-inst.dMean[is][ii][iv])*(Scale-inst.dMean[is][ii][iv])/inst.dCovar[is][ii][iv]);
dresult[ii] = inst.dMixtureWeight[is][ii] * dexp / fcoe;
}
return 1;
}
int CGMM::LScaleProb(double Scale,int istrm,int idx,double *fresult)
{
int ii;
double dsqrt2pai = 2.506628275; // sqrt (2 * PAI)
const double dlog2pai = 1.837877066; // log(2*pai)
double dcoe,dtmp;
if (!bLoaded)
return 0;
*fresult = 0;
for (ii=0;ii<inst.iNumMixtures[istrm];ii++)
{
dtmp = Scale-inst.dMean[istrm][ii][idx];
dtmp *= dtmp;
dcoe = - dlog2pai - log(inst.dCovar[istrm][ii][idx]) - dtmp/inst.dCovar[istrm][ii][idx];
dcoe = inst.dMixtureWeight[istrm][ii] * exp(dcoe/2);
*fresult += (float)dcoe;
}
*fresult = log(*fresult);
return 1;
}
//---------------------------------------------------------------
// Calculate the output probility of the given vector according
// to the Triggers (Enable or disable particular dimensions)
// ONLY SUPPORT ONE STREAM NOW !!
double CGMM::LVectorProb(float *Feature_Vector,int *Trigger_Vector)
{
int ii,ij,isum;
double dresult,dsum,ddet,dtmp;
double dlog2pai = 1.837877066;
if (!bLoaded)
return 0.0;
dresult = 0.0;
for (ii=0;ii<inst.iNumMixtures[0];ii++) // !!!
{ // for each mixture
isum = 0; // number of valid values
dsum = 0.0; //
ddet = 1.0; // deltermination
// only ONE stream !!
for (ij=0;ij<inst.iStreamInfo[1];ij++)
{ // for each value of a frame
if (Trigger_Vector[ij])
{ // if valid
dtmp = Feature_Vector[ij] - inst.dMean[0][ii][ij];
dtmp = dtmp * dtmp;
dsum += dtmp / inst.dCovar[0][ii][ij];
isum ++;
ddet *= inst.dCovar[0][ii][ij];
}
}
dsum = - isum*dlog2pai - log(ddet) - dsum;
dsum = exp(dsum/2);
// dsum = exp(-0.5 * dsum) / sqrt(pow(d2pai,isum)*ddet);
dresult += inst.dMixtureWeight[0][ii] * dsum;
}
return (log(dresult));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -