Skip to content

Instantly share code, notes, and snippets.

@tomonari-masada
Created March 15, 2013 10:23
Show Gist options
  • Save tomonari-masada/5168843 to your computer and use it in GitHub Desktop.
Save tomonari-masada/5168843 to your computer and use it in GitHub Desktop.
A Revised Inference for Correlated Topic Model
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <omp.h>
#include <xmmintrin.h>
#include <pmmintrin.h>
#include <lbfgs.h>
#define DIAGONAL_RATIO 0.0
#define REG_CONST 1.0
#define BUFFSIZE 100000
#define TOKENLEN 256
#define HASH_SIZE 65537
#define DTYPE double
#define MIN_HYP 1e-3
#define HYP_CONV 1e-3
#define NUM_OF_CGS_ITERATIONS 1000
#define NUM_OF_THREADS 16
#define NUM_OF_VB_ITERATIONS 200
FILE *fOut;
int *nWordNums;
int **nWordIDs;
int nNumOfTopics;
int nNumOfTopics2;
int nNumOfWords;
char **sWords;
int nNumOfDocs;
int *nDocHeadCell;
int *nDocNumOfCells;
int *nDocLen;
char **sDocName;
int nMaxDocNumOfCells;
int nNumOfTokens;
int nNumOfTestTokens;
int nNumOfCells;
int *nWordCell;
int *nTFCell;
int *nTestTFCell;
int **nTopicArray;
DTYPE *dNu;
DTYPE *dMeanR;
DTYPE *dStdevS;
DTYPE *dInvSigma;
DTYPE dLogDetSigma;
DTYPE *dMu;
DTYPE *dLambda;
DTYPE *dLambdaSum;
DTYPE *dZeta;
DTYPE *dZetaSum;
DTYPE *dZeta2;
DTYPE *dZetaSum2;
DTYPE *dAlpha;
DTYPE dAlphaSum;
DTYPE *dBeta;
DTYPE dBetaSum;
DTYPE dDiagonal;
//--------
typedef struct { int nID; DTYPE dData; } sortData;
int sort_compdata(const void *a, const void *b)
{
if (((sortData *) a)->dData < ((sortData *) b)->dData) { return 1; }
else if (((sortData *) a)->dData > ((sortData *) b)->dData) { return -1; }
else { return 0; }
}
//--------
time_t start_time;
void put_time(FILE *f)
{
time_t current_time;
time(&current_time);
fprintf(f, "%.0lf", difftime(current_time, start_time));
fflush(f);
}
//--------
DTYPE dDigammaOne;
DTYPE digamma(DTYPE dX)
{
DTYPE dXX, dXX2, dTemp, dSum;
dXX = dX; dTemp = 0.0; dSum = 0.0;
while (dXX < 8.0) { dTemp += 1.0 / dXX; dXX = dXX + 1.0; }
dXX2 = dXX * dXX;
dSum = 1.0 / (120.0 * dXX2) - 1.0 / 12.0;
dSum = dSum / dXX2 - 1.0 / (2.0 * dXX) + logl(dXX) - dTemp;
return dSum;
}
DTYPE trigamma(DTYPE dX)
{
DTYPE dXX, dXX2, dTemp, dSum;
dXX = dX; dTemp = 0.0; dSum = 0.0;
while (dXX < 8.0) { dTemp -= 1.0 / (dXX * dXX); dXX = dXX + 1.0; }
dXX2 = dXX * dXX;
dSum = - 1.0 / (30.0 * dXX2) + 1.0 / 6.0;
dSum = (dSum / dXX2 + 1.0 / (2.0 * dXX) + 1.0) / dXX - dTemp;
return dSum;
}
DTYPE tetragamma(DTYPE dX)
{
DTYPE dXX, dXX2, dTemp, dSum;
dXX = dX; dTemp = 0.0; dSum = 0.0;
while (dXX < 8.0) { dTemp += 2.0 / (dXX * dXX * dXX); dXX = dXX + 1.0; }
dXX2 = dXX * dXX;
dSum = (1.0 / 6.0) / dXX2 - 1.0 / 2.0;
dSum = (dSum / dXX2 - 1.0 / dXX - 1.0) / dXX2 - dTemp;
return dSum;
}
DTYPE invDigamma(DTYPE dY)
{
DTYPE dX;
int nCount;
if (dY >= -2.22) dX = exp(dY) + 0.5;
else dX = - 1.0 / (dY - dDigammaOne);
for (nCount = 0; nCount < 5; nCount ++)
dX = dX - (digamma(dX) - dY) / trigamma(dX);
return dX;
}
//-------- MT
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
unsigned long *mt; /* the array for the state vector */
int *mti; /* mti==N+1 means mt[N] is not initialized */
void init_genrand(unsigned long s, int nThreadID)
{
int nTemp;
mt[nThreadID * N + 0]= s & 0xffffffffUL;
for (mti[nThreadID] = 1; mti[nThreadID] < N; mti[nThreadID] ++) {
nTemp = nThreadID * N + mti[nThreadID];
mt[nTemp] = (1812433253UL * (mt[nTemp - 1] ^ (mt[nTemp - 1] >> 30)) + mti[nThreadID]);
mt[nTemp] &= 0xffffffffUL;
}
}
unsigned long genrand_int32(int nThreadID)
{
unsigned long y;
unsigned long mag01[2]={0x0UL, MATRIX_A};
int nTemp;
if (mti[nThreadID] >= N) { /* generate N words at one time */
int kk;
if (mti[nThreadID] == N+1) /* if init_genrand() has not been called, */
init_genrand(5489UL, nThreadID); /* a default initial seed is used */
for (kk = 0; kk < N - M; kk ++) {
nTemp = nThreadID * N + kk;
y = (mt[nTemp] & UPPER_MASK) | (mt[nTemp + 1] & LOWER_MASK);
mt[nTemp] = mt[nTemp + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (; kk < N - 1; kk ++) {
nTemp = nThreadID * N + kk;
y = (mt[nTemp] & UPPER_MASK) | (mt[nTemp + 1] & LOWER_MASK);
mt[nTemp] = mt[nTemp + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
nTemp = nThreadID * N;
y = (mt[nTemp + N - 1] & UPPER_MASK) | (mt[nTemp] & LOWER_MASK);
mt[nTemp + N - 1] = mt[nTemp + M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti[nThreadID] = 0;
}
y = mt[nThreadID * N + mti[nThreadID]];
mti[nThreadID] ++;
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
long genrand_int31(int nT) { return (long)(genrand_int32(nT)>>1); }
double genrand_real1(int nT) { return genrand_int32(nT)*(1.0/4294967295.0); /* divided by 2^32-1 */ }
double genrand_real2(int nT) { return genrand_int32(nT)*(1.0/4294967296.0); /* divided by 2^32 */ }
double genrand_real3(int nT) { return (((double)genrand_int32(nT)) + 0.5)*(1.0/4294967296.0); /* divided by 2^32 */ }
double genrand_res53(int nT) { unsigned long a=genrand_int32(nT)>>5, b=genrand_int32(nT)>>6; return(a*67108864.0+b)*(1.0/9007199254740992.0); }
void initRand()
{
int nCount;
mt = (unsigned long *) malloc(sizeof(unsigned long) * NUM_OF_THREADS * N); /* the array for the state vector */
mti = (int *) malloc(sizeof(int) * NUM_OF_THREADS);
init_genrand((unsigned) time(NULL), 0);
for (nCount = 1; nCount < NUM_OF_THREADS; nCount ++)
init_genrand(genrand_int31(nCount - 1), nCount);
return;
}
//--------
int hash_func(const char *sStr)
{
int n1, n2, n3, n4, nL;
nL = (int) strlen(sStr); if (nL < 0) nL = - nL; n1 = (int) sStr[0];
if (strlen(sStr) > 1) { n2 = (int) sStr[1]; n3 = (int) sStr[nL - 2]; n4 = (int) sStr[nL - 1]; }
else { n2 = (int) sStr[0]; n3 = (int) sStr[0]; n4 = (int) sStr[0]; }
if (n1 < 0) n1 = - n1; if (n2 < 0) n2 = - n2; if (n3 < 0) n3 = - n3; if (n4 < 0) n4 = - n4;
return ((n2 + n1 * 1025 + nL * 4097 + n3 * 32769) % HASH_SIZE + (n4 * 65537) % HASH_SIZE) % HASH_SIZE;
}
int initHash()
{
int nCount;
nNumOfWords = 0;
nWordNums = (int *) malloc(sizeof(int) * HASH_SIZE);
nWordIDs = (int **) malloc(sizeof(int *) * HASH_SIZE);
if ((nWordNums == NULL) || (nWordIDs == NULL)) return 1;
for (nCount = 0; nCount < HASH_SIZE; nCount ++) nWordNums[nCount] = 0;
return 0;
}
int addWord(const char *s)
{
unsigned nCount;
int nID;
int nHashKey;
nID = 0;
nHashKey = hash_func(s);
for (nCount = 0; nCount < nWordNums[nHashKey]; nCount ++)
if (strcmp(s, sWords[nWordIDs[nHashKey][nCount] - 1]) == 0) {
nID = nWordIDs[nHashKey][nCount];
break;
}
if (nID == 0) {
nNumOfWords ++;
nWordNums[nHashKey] ++;
if (nWordNums[nHashKey] == 1)
nWordIDs[nHashKey] = (int *) malloc(sizeof(int));
else
nWordIDs[nHashKey] = (int *) realloc(nWordIDs[nHashKey], sizeof(int) * nWordNums[nHashKey]);
nWordIDs[nHashKey][nWordNums[nHashKey] - 1] = nNumOfWords;
if (nNumOfWords == 1)
sWords = (char **) malloc(sizeof(char *));
else
sWords = (char **) realloc(sWords, sizeof(char *) * nNumOfWords);
sWords[nNumOfWords - 1] = (char *) malloc(sizeof(char) * (strlen(s) + 1));
memset(sWords[nNumOfWords - 1], 0, strlen(s) + 1);
strcpy(sWords[nNumOfWords - 1], s);
nID = nNumOfWords;
}
return nID;
}
//-------- matrix calculations
DTYPE inverse(DTYPE *dMat, int nDim)
{
int nC, nOrder, nLdim, *nPivot, nLwork, nInfo;
DTYPE dRet, *dWork;
nOrder = nDim; nLdim = nDim;
nLwork = nDim * nDim;
nPivot = (int *) malloc(sizeof(int) * (nDim + 1));
dWork = (DTYPE *) malloc(sizeof(DTYPE) * nLwork);
dgetrf_(&nOrder, &nOrder, dMat, &nLdim, nPivot, &nInfo);
if (nInfo != 0) { fprintf(stderr, "fatal error in inverse %d (%d)\n",nInfo,nDim); exit(1); }
dRet = 0.0;
for (nC = 0; nC < nDim; nC ++) dRet += log(fabs(dMat[nC + nDim * nC]));
dgetri_(&nOrder, dMat, &nLdim, nPivot, dWork, &nLwork, &nInfo);
free(nPivot);
free(dWork);
return dRet;
}
//--------
//DTYPE dConst = REG_CONST * DIAGONAL_RATIO;
DTYPE dConst = REG_CONST;
static lbfgsfloatval_t LBFGS_MeanR(
void *instance,
const lbfgsfloatval_t *dX,
lbfgsfloatval_t *dG,
const int nDim,
const lbfgsfloatval_t dStep
)
{
int nCD, nCK, nCK2;
int nTemp, nTemp2;
lbfgsfloatval_t dFX;
DTYPE dTemp;
nCD = (*((int *) instance));
nTemp = nCD * nNumOfTopics;
dFX = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
nTemp2 = nCK * nNumOfTopics;
dG[nCK] = 0.0;
for (nCK2 = 0; nCK2 < nNumOfTopics; nCK2 ++)
dG[nCK] += (dX[nCK2] - dMu[nCK2]) * dInvSigma[nTemp2 + nCK2];
dTemp = exp(dX[nCK]
+ 0.5 * dX[nNumOfTopics + nCK] * dX[nNumOfTopics + nCK]);
dTemp *= ((DTYPE) nDocLen[nCD]) / dNu[nCD];
dFX -= dX[nCK] * dG[nCK];
dFX += 0.5 * dX[nCK] * dX[nCK] * dInvSigma[nTemp2 + nCK];
dFX += dX[nCK] * dLambda[nTemp + nCK];
dFX -= dTemp;
dFX -= 0.5 * dX[nNumOfTopics + nCK] * dX[nNumOfTopics + nCK]
* dInvSigma[nTemp2 + nCK];
dFX += log(fabs(dX[nNumOfTopics + nCK]));
dG[nCK] = dLambda[nTemp + nCK] - dTemp - dG[nCK];
dG[nNumOfTopics + nCK] = - dTemp
- fabs(dX[nNumOfTopics + nCK]) * dInvSigma[nTemp2 + nCK]
+ 1.0 / fabs(dX[nNumOfTopics + nCK]);
dTemp = dX[nCK] - log(dLambda[nTemp + nCK] + dAlpha[nCK]);
dFX -= dConst * dTemp * dTemp;
dG[nCK] -= 2.0 * dConst * dTemp;
}
dFX = - dFX;
for (nCK = 0; nCK < nNumOfTopics * 2; nCK ++) dG[nCK] = - dG[nCK];
return dFX;
}
static int LBFGS_progress(
void *instance,
const lbfgsfloatval_t *x,
const lbfgsfloatval_t *g,
const lbfgsfloatval_t fx,
const lbfgsfloatval_t xnorm,
const lbfgsfloatval_t gnorm,
const lbfgsfloatval_t step,
int n,
int k,
int ls
)
{
/*
printf("Iteration %d:\n", k);
printf(" fx = %f, x[0] = %f, x[1] = %f\n", fx, x[0], x[1]);
printf(" xnorm = %f, gnorm = %f, step = %f\n", xnorm, gnorm, step);
printf("\n");
*/
if (k > 1000) return 1;
return 0;
}
//--------
int statistics()
{
int nCD, nCK, nCW, nCC, nCToken;
for (nCD = 0; nCD < nNumOfDocs; nCD ++) {
dLambdaSum[nCD] = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dLambda[nCD * nNumOfTopics + nCK] = 0.0;
}
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
dZetaSum[nCK] = 0.0;
for (nCW = 0; nCW < nNumOfWords; nCW ++)
dZeta[nCK * nNumOfWords + nCW] = 0.0;
}
for (nCD = 0; nCD < nNumOfDocs; nCD ++)
for (nCC = nDocHeadCell[nCD]; nCC < nDocHeadCell[nCD] + nDocNumOfCells[nCD]; nCC ++)
for (nCToken = 0; nCToken < nTFCell[nCC]; nCToken ++) {
dLambda[nCD * nNumOfTopics + nTopicArray[nCC][nCToken]] += 1.0;
dZeta[nTopicArray[nCC][nCToken] * nNumOfWords + nWordCell[nCC]] += 1.0;
}
for (nCD = 0; nCD < nNumOfDocs; nCD ++)
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dLambdaSum[nCD] += dLambda[nCD * nNumOfTopics + nCK];
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
for (nCW = 0; nCW < nNumOfWords; nCW ++)
dZetaSum[nCK] += dZeta[nCK * nNumOfWords + nCW];
return 0;
}
//-------- updating hyper parameters
int optHypA2(FILE *fOut, int nI)
{
int nCK, nIter;
DTYPE dPrevAlphaSum;
DTYPE dConv;
fprintf(fOut, "#hA\t%d", nI);
dAlphaSum = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dAlphaSum += dAlpha[nCK];
nIter = 0;
do {
#pragma omp parallel
{
int nCD, nCK;
DTYPE dNSum, dDSum;
#ifdef _OPENMP
int nThreadID = omp_get_thread_num();
int nNumOfThreads = omp_get_num_threads();
#else
int nThreadID = 0;
int nNumOfThreads = 1;
#endif
for (nCK = nThreadID; nCK < nNumOfTopics; nCK += nNumOfThreads) {
dNSum = 0.0;
dDSum = 0.0;
for (nCD = 0; nCD < nNumOfDocs; nCD ++) {
dNSum += digamma(dLambda[nCD * nNumOfTopics + nCK] + dAlpha[nCK]);
dDSum += digamma(dLambdaSum[nCD] + dAlphaSum);
}
dNSum = dAlpha[nCK] * (dNSum - digamma(dAlpha[nCK]) * ((DTYPE) nNumOfDocs));
dDSum = 1.0 + dDSum - digamma(dAlphaSum) * ((DTYPE) nNumOfDocs);
dAlpha[nCK] = dNSum / dDSum;
if (dAlpha[nCK] < MIN_HYP) dAlpha[nCK] = MIN_HYP;
}
}
nIter ++;
dPrevAlphaSum = dAlphaSum;
dAlphaSum = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dAlphaSum += dAlpha[nCK];
dConv = fabs((dAlphaSum - dPrevAlphaSum) / dAlphaSum);
} while (dConv > HYP_CONV);
fprintf(fOut, "\t%.6lf\t%d\n", dAlphaSum / ((DTYPE) nNumOfTopics), nIter);
return 0;
}
int optHypB2(FILE *fOut, int nI)
{
int nCW, nIter;
DTYPE dPrevBetaSum;
DTYPE dConv;
fprintf(fOut, "#hB\t%d", nI);
dBetaSum = 0.0;
for (nCW = 0; nCW < nNumOfWords; nCW ++) dBetaSum += dBeta[nCW];
nIter = 0;
do {
#pragma omp parallel
{
int nCK, nCW;
DTYPE dNSum, dDSum;
#ifdef _OPENMP
int nThreadID = omp_get_thread_num();
int nNumOfThreads = omp_get_num_threads();
#else
int nThreadID = 0;
int nNumOfThreads = 1;
#endif
for (nCW = nThreadID; nCW < nNumOfWords; nCW += nNumOfThreads) {
dNSum = 0.0;
dDSum = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
dNSum += digamma(dZeta[nCK * nNumOfWords + nCW] + dBeta[nCW]);
dDSum += digamma(dZetaSum[nCK] + dBetaSum);
}
dNSum = dBeta[nCW] * (dNSum - digamma(dBeta[nCW]) * ((DTYPE) nNumOfTopics));
dDSum = 1.0 + dDSum - digamma(dBetaSum) * ((DTYPE) nNumOfTopics);
dBeta[nCW] = dNSum / dDSum;
if (dBeta[nCW] < MIN_HYP) dBeta[nCW] = MIN_HYP;
}
}
nIter ++;
dPrevBetaSum = dBetaSum;
dBetaSum = 0.0;
for (nCW = 0; nCW < nNumOfWords; nCW ++) dBetaSum += dBeta[nCW];
dConv = fabs((dBetaSum - dPrevBetaSum) / dBetaSum);
} while (dConv > HYP_CONV);
fprintf(fOut, "\t%.6lf\t%d\n", dBetaSum / ((DTYPE) nNumOfWords), nIter);
return 0;
}
//-------- for evaluation
double logEviLB()
{
double dRet;
dRet = 0.0;
#pragma omp parallel
{
double dLocalRet;
double dLR;
int nCD, nCK, nCK2, nCW, nCC;
int nTemp, nTemp3;
//int nCD2;
double *dPi;
double dTemp;
#ifdef _OPENMP
int nThreadID = omp_get_thread_num();
int nNumOfThreads = omp_get_num_threads();
#else
int nThreadID = 0;
int nNumOfThreads = 1;
#endif
dPi = (double *) malloc(sizeof(double) * nNumOfTopics);
#pragma omp barrier
dLocalRet = 0.0;
for (nCD = nThreadID; nCD < nNumOfDocs; nCD += nNumOfThreads) {
nTemp = nCD * nNumOfTopics;
for (nCC = nDocHeadCell[nCD]; nCC < nDocHeadCell[nCD] + nDocNumOfCells[nCD]; nCC ++) {
nCW = nWordCell[nCC];
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dPi[nCK] = dMeanR[nTemp + nCK]
+ dZeta2[nCK * nNumOfWords + nCW] - dZetaSum2[nCK];
dTemp = dPi[0];
for (nCK = 1; nCK < nNumOfTopics; nCK ++) if (dTemp < dPi[nCK]) dTemp = dPi[nCK];
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dPi[nCK] = exp(dPi[nCK] - dTemp);
dTemp = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dTemp += dPi[nCK];
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dPi[nCK] /= dTemp;
dLR = dLocalRet;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dLocalRet += ((double) nTFCell[nCC]) * dPi[nCK]
* (dMeanR[nTemp + nCK] - log(dNu[nCD])
+ dZeta2[nCK * nNumOfWords + nCW] - dZetaSum2[nCK]);
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
if (dPi[nCK] > 1e-5)
dLocalRet -= ((double) nTFCell[nCC]) * dPi[nCK] * log(dPi[nCK]);
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####00\t%d\t%d\t%.8lf\t%.8lf\n",nCD,nCC,dLR,dLocalRet);fflush(stdout);}}
}
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
nTemp = nCD * nNumOfTopics + nCK;
nTemp3 = nCK * nNumOfTopics + nCK;
dLR = dLocalRet;
dLocalRet -= 0.5 * (dStdevS[nTemp] * dStdevS[nTemp] * dInvSigma[nTemp3]);
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####01a\t%d\t%d\t%.8lf\t%.8lf\n",nCD,nCK,dLR,dLocalRet);fflush(stdout);}}
dLR = dLocalRet;
dLocalRet += log(dStdevS[nTemp]);
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####01b\t%d\t%d\t%.8lf\t%.8lf\t%.8lf\n",nCD,nCK,dLR,dLocalRet,dStdevS[nTemp]);fflush(stdout);}}
dLR = dLocalRet;
dLocalRet -= 0.5 * (dMeanR[nTemp] - dMu[nCK]) * (dMeanR[nTemp] - dMu[nCK]) * dInvSigma[nTemp3];
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####01d\t%d\t%d\t%.8lf\t%.8lf\n",nCD,nCK,dLR,dLocalRet);fflush(stdout);}}
nTemp = nCD * nNumOfTopics;
nTemp3 = nCK * nNumOfTopics;
dLR = dLocalRet;
for (nCK2 = nCK + 1; nCK2 < nNumOfTopics; nCK2 ++)
dLocalRet -= (dMeanR[nTemp + nCK] - dMu[nCK]) * (dMeanR[nTemp + nCK2] - dMu[nCK2]) * dInvSigma[nTemp3 + nCK2];
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####02\t%d\t%d\t%.8lf\t%.8lf\n",nCD,nCK,dLR,dLocalRet);fflush(stdout);}}
}
}
#pragma omp barrier
for (nCK = nThreadID; nCK < nNumOfTopics; nCK += nNumOfThreads) {
for (nCW = 0; nCW < nNumOfWords; nCW ++) {
nTemp = nCK * nNumOfWords + nCW;
dLR = dLocalRet;
dLocalRet += (dBeta[nCW] - dZeta[nTemp]) * (dZeta2[nTemp] - dZetaSum2[nCK]) + lgamma(dZeta[nTemp]);
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####04\t%d\t%s\t%.8lf\t%.8lf\n",nCK,sWords[nCW],dLR,dLocalRet);fflush(stdout);}}
{if((!isinf(dLR))&&(isinf(dLocalRet))){printf("#---04\t%d\t%s\t%.8lf\t%.8lf\t%.8lf\n",nCK,sWords[nCW],dLR,dLocalRet,dZeta[nTemp]);fflush(stdout);}}
}
dLR = dLocalRet;
dLocalRet -= lgamma(dZetaSum[nCK]);
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####05\t%d\t%.8lf\t%.8lf\n",nCK,dLR,dLocalRet);fflush(stdout);}}
{if((!isinf(dLR))&&(isinf(dLocalRet))){printf("#---05\t%d\t%.8lf\t%.8lf\n",nCK,dLR,dLocalRet);fflush(stdout);}}
}
#pragma omp barrier
for (nCW = nThreadID; nCW < nNumOfWords; nCW += nNumOfThreads) {
dLR = dLocalRet;
dLocalRet -= ((DTYPE) nNumOfTopics) * lgamma(dBeta[nCW]);
{if((!isnan(dLR))&&(isnan(dLocalRet))){printf("####06\t%s\t%.8lf\t%.8lf\n",sWords[nCW],dLR,dLocalRet);fflush(stdout);}}
{if((!isinf(dLR))&&(isinf(dLocalRet))){printf("#---06\t%s\t%.8lf\t%.8lf\n",sWords[nCW],dLR,dLocalRet);fflush(stdout);}}
}
#pragma omp critical
{
dRet += dLocalRet;
}
free(dPi);
}
dRet += ((DTYPE) nNumOfTopics) * lgamma(dBetaSum);
dRet += ((DTYPE) nNumOfDocs) * ((DTYPE) nNumOfTopics);
// Determinants cannot be calculated correctly.
//dPrevRet = dRet;
dRet -= 0.5 * ((DTYPE) nNumOfDocs) * dLogDetSigma;
//{if((!isnan(dPrevRet))&&(isnan(dRet))){printf("####07\t%.8lf\t%.8lf\n",dPrevRet,dRet);fflush(stdout);}}
//dPrevRet = dRet;
//dRet -= 0.5 * ((DTYPE) nNumOfTopics) * dLogDetGram;
//{if((!isnan(dPrevRet))&&(isnan(dRet))){printf("####08\t%.8lf\t%.8lf\n",dPrevRet,dRet);fflush(stdout);}}
return dRet;
}
double perplexityLDA(int nFlag) // call setTempDocTopic before calling this function when nFlag != 0
{
double dRet = 0.0;
#pragma omp parallel
{
double dLocalRet;
double dProb;
double dTempSum;
int nCD, nCK, nCC, nCW;
#ifdef _OPENMP
int nThreadID = omp_get_thread_num();
int nNumOfThreads = omp_get_num_threads();
#else
int nThreadID = 0;
int nNumOfThreads = 1;
#endif
dLocalRet = 0.0;
for (nCD = nThreadID; nCD < nNumOfDocs; nCD += nNumOfThreads) {
dTempSum = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dTempSum += exp(dMeanR[nCD * nNumOfTopics + nCK]);
for (nCC = nDocHeadCell[nCD]; nCC < nDocHeadCell[nCD] + nDocNumOfCells[nCD]; nCC ++)
if (nTestTFCell[nCC] > 0) {
nCW = nWordCell[nCC];
dProb = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
if (nFlag == 0)
dProb += (dLambda[nCD * nNumOfTopics + nCK] + dAlpha[nCK])
* (dZeta[nCK * nNumOfWords + nCW] + dBeta[nCW]) / (dZetaSum[nCK] + dBetaSum);
else
dProb += exp(dMeanR[nCD * nNumOfTopics + nCK])
* dZeta[nCK * nNumOfWords + nCW] / dZetaSum[nCK];
if (nFlag == 0)
dProb /= (dLambdaSum[nCD] + dAlphaSum);
else
dProb /= dTempSum;
dLocalRet += ((double) nTestTFCell[nCC]) * log(dProb);
}
}
#pragma omp critical
{
dRet -= dLocalRet;
}
}
return exp(dRet / ((double) nNumOfTestTokens));
}
int setTestData()
{
int nCD, nCC;
int nCToken;
nNumOfTestTokens = 0;
nTestTFCell = (int *) malloc(sizeof(int) * nNumOfCells);
nTopicArray = (int **) malloc(sizeof(int *) * nNumOfCells);
for (nCC = 0; nCC < nNumOfCells; nCC ++) nTestTFCell[nCC] = 0;
for (nCD = 0; nCD < nNumOfDocs; nCD ++)
for (nCC = nDocHeadCell[nCD]; nCC < nDocHeadCell[nCD] + nDocNumOfCells[nCD]; nCC ++) {
nTestTFCell[nCC] = 0;
for (nCToken = 0; nCToken < nTFCell[nCC]; nCToken ++)
if (genrand_int32(nCC % NUM_OF_THREADS) % 10 == 0) nTestTFCell[nCC] ++;
nTFCell[nCC] -= nTestTFCell[nCC];
nNumOfTestTokens += nTestTFCell[nCC];
nNumOfTokens -= nTestTFCell[nCC];
if (nTFCell[nCC] > 0) nTopicArray[nCC] = (int *) malloc(sizeof(int) * nTFCell[nCC]);
}
return 0;
}
int printLog(int nI)
{
sortData *stData;
int nCD, nCK, nCW;
stData = (sortData *) malloc(sizeof(sortData) * nNumOfWords);
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
for (nCW = 0; nCW < nNumOfWords; nCW ++) {
stData[nCW].nID = nCW;
stData[nCW].dData = dZeta[nCK * nNumOfWords + nCW];
}
qsort(stData, nNumOfWords, sizeof(sortData), sort_compdata);
printf("#KW %d %d", nI, nCK);
for (nCW = 0; nCW < 100; nCW ++)
if (stData[nCW].dData > 0.0)
printf(" %s %.4le", sWords[stData[nCW].nID], stData[nCW].dData);
printf("\n");
fflush(stdout);
}
free(stData);
for (nCD = 0; nCD < nNumOfDocs; nCD ++) {
printf("#JK %d %s", nI, sDocName[nCD]);
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
printf(" %.4le", dLambda[nCD * nNumOfTopics + nCK]);
printf("\n");
}
if (nI > 0)
for (nCD = 0; nCD < nNumOfDocs; nCD ++) {
printf("#Me %d %s", nI, sDocName[nCD]);
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
printf(" %.4le", exp(dMeanR[nCD * nNumOfTopics + nCK]));
printf("\n");
}
return 0;
}
//--------
int main(int argc, char **argv)
{
char sBuff[BUFFSIZE];
int nDocID, nWordID;
char sTempDoc[TOKENLEN];
char sPrevDoc[TOKENLEN];
char sTempWord[TOKENLEN];
int nTF;
int nIteration;
if (argc < 2) {
fprintf(stderr, "usage : %s num_of_topics\n", argv[0]);
exit(1);
}
nNumOfTopics = atoi(argv[1]);
if (nNumOfTopics < 2) { fprintf(stderr, "%s : illegal argument : %s\n", argv[0], argv[1]); exit(1); }
// denormal values
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
fOut = stdout;
initHash();
initRand();
nNumOfDocs = 0;
nDocHeadCell = (int *) malloc(sizeof(int));
nDocNumOfCells = (int *) malloc(sizeof(int));
nDocLen = (int *) malloc(sizeof(int));
sDocName= (char **) malloc(sizeof(char *));
nNumOfCells = 0;
nWordCell = (int *) malloc(sizeof(int));
nTFCell = (int *) malloc(sizeof(int));
memset(sPrevDoc, 0, TOKENLEN);
while (! feof(stdin)) {
memset(sBuff, 0, BUFFSIZE);
fgets(sBuff, BUFFSIZE - 1, stdin);
memset(sTempWord, 0, TOKENLEN);
memset(sTempDoc, 0, TOKENLEN);
if (sscanf(sBuff, "W %s %s %d\n", sTempDoc, sTempWord, &nTF) == 3) {
if (strcmp(sPrevDoc, sTempDoc) != 0) {
nNumOfDocs ++;
nDocHeadCell = (int *) realloc(nDocHeadCell, sizeof(int) * nNumOfDocs);
nDocNumOfCells = (int *) realloc(nDocNumOfCells, sizeof(int) * nNumOfDocs);
nDocLen = (int *) realloc(nDocLen, sizeof(int) * nNumOfDocs);
sDocName = (char **) realloc(sDocName, sizeof(char *) * nNumOfDocs);
nDocHeadCell[nNumOfDocs - 1] = nNumOfCells;
nDocNumOfCells[nNumOfDocs - 1] = 0;
nDocLen[nNumOfDocs - 1] = 0;
sDocName[nNumOfDocs - 1] = (char *) malloc(sizeof(char) * (strlen(sTempDoc) + 1));
memset(sDocName[nNumOfDocs - 1], 0, strlen(sTempDoc) + 1);
strcpy(sDocName[nNumOfDocs - 1], sTempDoc);
}
nDocID = nNumOfDocs - 1;
nWordID = addWord(sTempWord);
if (nWordID > 0) {
nNumOfCells ++;
nDocNumOfCells[nDocID] ++;
nWordCell = (int *) realloc(nWordCell, sizeof(int) * nNumOfCells);
nWordCell[nNumOfCells - 1] = nWordID - 1;
nTFCell = (int *) realloc(nTFCell, sizeof(int) * nNumOfCells);
nTFCell[nNumOfCells - 1] = nTF;
nDocLen[nDocID] += nTF;
nNumOfTokens += nTF;
} else { fprintf(stderr, "Invalid data : %s\n", sTempWord); exit(1); }
memset(sPrevDoc, 0, TOKENLEN);
strcpy(sPrevDoc, sTempDoc);
}
}
if (nNumOfDocs == 0) { fprintf(stderr, "no valid data.\n"); exit(1); }
{
int nCD;
nMaxDocNumOfCells = 0;
for (nCD = 0; nCD < nNumOfDocs; nCD ++)
if (nDocNumOfCells[nCD] > nMaxDocNumOfCells) nMaxDocNumOfCells = nDocNumOfCells[nCD];
}
setTestData();
// print statistics
{
fprintf(fOut, "### J : %d; ", nNumOfDocs);
fprintf(fOut, "W : %d; ", nNumOfWords);
fprintf(fOut, "K : %d; ", nNumOfTopics);
fprintf(fOut, "JW pairs : %d; ", nNumOfCells);
fprintf(fOut, "M : %d + %d; ", nNumOfTokens, nNumOfTestTokens);
fprintf(fOut, "X : %d; ", nMaxDocNumOfCells);
fprintf(fOut, "\n");
fflush(fOut);
}
// initialization
{
int nCD, nCC, nCToken;
for (nCD = 0; nCD < nNumOfDocs; nCD ++)
for (nCC = nDocHeadCell[nCD]; nCC < nDocHeadCell[nCD] + nDocNumOfCells[nCD]; nCC ++)
for (nCToken = 0; nCToken < nTFCell[nCC]; nCToken ++)
nTopicArray[nCC][nCToken] = genrand_int32(genrand_int32(nCD % NUM_OF_THREADS) % NUM_OF_THREADS) % nNumOfTopics;
}
dDigammaOne = digamma(1.0);
{
int nCK, nCW;
dAlpha = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics);
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dAlpha[nCK] = 50.0 / ((DTYPE) nNumOfTopics);
dAlphaSum = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dAlphaSum += dAlpha[nCK];
dBeta = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfWords);
for (nCW = 0; nCW < nNumOfWords; nCW ++) dBeta[nCW] = 0.01;
dBetaSum = 0.0;
for (nCW = 0; nCW < nNumOfWords; nCW ++) dBetaSum += dBeta[nCW];
dLambda = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfDocs * nNumOfTopics);
dLambdaSum = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfDocs);
dZeta = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics * nNumOfWords);
dZetaSum = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics);
dZeta2 = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics * nNumOfWords);
dZetaSum2 = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics);
dNu = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfDocs);
dMeanR = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfDocs * nNumOfTopics);
dStdevS = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfDocs * nNumOfTopics);
dMu = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics);
dInvSigma = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics * nNumOfTopics);
}
statistics();
// initialization by CGS for LDA
nIteration = 0;
time(&start_time);
do {
#pragma omp parallel
{
DTYPE *dTempDist;
int nCD, nCC, nCToken, nCK, nCW;
int nOldTopic, nNewTopic;
DTYPE dTemp;
#ifdef _OPENMP
int nThreadID = omp_get_thread_num();
int nNumOfThreads = omp_get_num_threads();
#else
int nThreadID = 0;
int nNumOfThreads = 1;
#endif
dTempDist = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics);
for (nCD = nThreadID; nCD < nNumOfDocs; nCD += nNumOfThreads) {
for (nCC = nDocHeadCell[nCD]; nCC < nDocHeadCell[nCD] + nDocNumOfCells[nCD]; nCC ++) {
nCW = nWordCell[nCC];
for (nCToken = 0; nCToken < nTFCell[nCC]; nCToken ++) {
nOldTopic = nTopicArray[nCC][nCToken];
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
if (nCK == nOldTopic)
dTempDist[nCK] = (dLambda[nCD * nNumOfTopics + nCK] + dAlpha[nCK] - 1.0)
* (dZeta[nCK * nNumOfWords + nCW] + dBeta[nCW] - 1.0) / (dZetaSum[nCK] + dBetaSum - 1.0);
else
dTempDist[nCK] = (dLambda[nCD * nNumOfTopics + nCK] + dAlpha[nCK])
* (dZeta[nCK * nNumOfWords + nCW] + dBeta[nCW]) / (dZetaSum[nCK] + dBetaSum);
if (dTempDist[nCK] < 0.0) dTempDist[nCK] = 0.0;
}
dTemp = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dTemp += dTempDist[nCK];
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dTempDist[nCK] /= dTemp;
dTemp = genrand_res53(nThreadID);
nCK = 0;
while ((dTemp > 0.0) && (nCK < nNumOfTopics)) dTemp -= dTempDist[nCK ++];
nNewTopic = nCK - 1;
if (nNewTopic == -1) nNewTopic = 0;
if (nOldTopic != nNewTopic) {
nTopicArray[nCC][nCToken] = nNewTopic;
dLambda[nCD * nNumOfTopics + nOldTopic] -= 1.0;
dLambda[nCD * nNumOfTopics + nNewTopic] += 1.0;
#pragma omp critical
{
dZeta[nOldTopic * nNumOfWords + nCW] -= 1.0;
dZeta[nNewTopic * nNumOfWords + nCW] += 1.0;
dZetaSum[nOldTopic] -= 1.0;
dZetaSum[nNewTopic] += 1.0;
}
}
}
}
}
free(dTempDist);
}
nIteration ++;
fprintf(fOut, "#i\t%d\t", nIteration);
fprintf(fOut, "\t%.3lf\t", perplexityLDA(0));
put_time(fOut);
fprintf(fOut, "\n");
fflush(fOut);
if ((nIteration > 10)
&& ((nIteration < 30)
|| ((nIteration < 100) && (nIteration % 10 == 0))
|| (nIteration % 20 == 0))) {
optHypA2(fOut, nIteration);
optHypB2(fOut, nIteration);
}
} while (nIteration < NUM_OF_CGS_ITERATIONS);
//
{
int nCD, nCK, nCW;
int nTemp;
for (nCD = 0; nCD < nNumOfDocs; nCD ++) {
nTemp = nCD * nNumOfTopics;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dMeanR[nTemp + nCK] = log(dLambda[nTemp + nCK] + dAlpha[nCK]);
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dStdevS[nTemp + nCK] = 1.0;
}
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
nTemp = nCK * nNumOfWords;
for (nCW = 0; nCW < nNumOfWords; nCW ++) dZeta[nTemp + nCW] += dBeta[nCW];
for (nCW = 0; nCW < nNumOfWords; nCW ++) dZeta2[nTemp + nCW] += digamma(dZeta[nTemp + nCW]);
dZetaSum[nCK] = 0.0;
for (nCW = 0; nCW < nNumOfWords; nCW ++) dZetaSum[nCK] += dZeta[nTemp + nCW];
dZetaSum2[nCK] = digamma(dZetaSum[nCK]);
}
}
// VB for LOCCTM
nIteration = 0;
do {
#pragma omp parallel
{
int nCD, nCK, nCK2, nCW, nCC;
DTYPE dTemp;
int nTemp;
DTYPE *dPi;
lbfgsfloatval_t dFX;
lbfgsfloatval_t *dX;
lbfgs_parameter_t param;
#ifdef _OPENMP
int nThreadID = omp_get_thread_num();
int nNumOfThreads = omp_get_num_threads();
#else
int nThreadID = 0;
int nNumOfThreads = 1;
#endif
dPi = (DTYPE *) malloc(sizeof(DTYPE) * nNumOfTopics);
dX = lbfgs_malloc(nNumOfDocs * 2);
#pragma omp barrier
for (nCK = nThreadID; nCK < nNumOfTopics; nCK += nNumOfThreads) {
dMu[nCK] = 0.0;
for (nCD = 0; nCD < nNumOfDocs; nCD ++)
dMu[nCK] += dMeanR[nCD * nNumOfTopics + nCK];
dMu[nCK] /= ((DTYPE) nNumOfDocs);
}
#pragma omp barrier
for (nCK = nThreadID; nCK < nNumOfTopics; nCK += nNumOfThreads) {
dPi[nCK] = 0.0;
for (nCD = 0; nCD < nNumOfDocs; nCD ++) {
dTemp = dStdevS[nCD * nNumOfTopics + nCK];
dPi[nCK] += dTemp * dTemp;
}
dPi[nCK] /= ((DTYPE) nNumOfDocs);
nTemp = nCK * nNumOfTopics;
for (nCK2 = nCK; nCK2 < nNumOfTopics; nCK2 ++) {
dInvSigma[nTemp + nCK2] = 0.0;
for (nCD = 0; nCD < nNumOfDocs; nCD ++)
dInvSigma[nTemp + nCK2] += (dMeanR[nCD * nNumOfTopics + nCK] - dMu[nCK])
* (dMeanR[nCD * nNumOfTopics + nCK2] - dMu[nCK2]);
dInvSigma[nTemp + nCK2] /= ((DTYPE) nNumOfDocs);
if (nCK != nCK2)
dInvSigma[nCK2 * nNumOfTopics + nCK] = dInvSigma[nTemp + nCK2];
}
nTemp = nCK * nNumOfWords;
dZetaSum[nCK] = dBetaSum;
for (nCW = 0; nCW < nNumOfWords; nCW ++) dZeta[nTemp + nCW] = dBeta[nCW];
}
#pragma omp barrier
if (nThreadID == 0) {
dDiagonal = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dDiagonal += dInvSigma[nCK * nNumOfTopics + nCK];
dDiagonal /= ((DTYPE) nNumOfTopics);
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dInvSigma[nCK * nNumOfTopics + nCK]
+= (1.0 - DIAGONAL_RATIO) * dPi[nCK] + DIAGONAL_RATIO * dDiagonal;
dLogDetSigma = inverse(dInvSigma, nNumOfTopics);
}
#pragma omp barrier
for (nCD = nThreadID; nCD < nNumOfDocs; nCD += nNumOfThreads) {
nTemp = nCD * nNumOfTopics;
dNu[nCD] = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
dNu[nCD] += exp(dMeanR[nTemp + nCK]
+ 0.5 * dStdevS[nTemp + nCK] * dStdevS[nTemp + nCK]);
}
dLambdaSum[nCD] = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dLambda[nTemp + nCK] = 0.0;
for (nCC = nDocHeadCell[nCD]; nCC < nDocHeadCell[nCD] + nDocNumOfCells[nCD]; nCC ++) {
nCW = nWordCell[nCC];
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dPi[nCK] = dMeanR[nTemp + nCK]
+ dZeta2[nCK * nNumOfWords + nCW] - dZetaSum2[nCK];
dTemp = dPi[0];
for (nCK = 1; nCK < nNumOfTopics; nCK ++) if (dTemp < dPi[nCK]) dTemp = dPi[nCK];
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dPi[nCK] = exp(dPi[nCK] - dTemp);
dTemp = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) dTemp += dPi[nCK];
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dPi[nCK] = ((DTYPE) nTFCell[nCC]) * dPi[nCK] / dTemp;
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
dLambda[nTemp + nCK] += dPi[nCK];
dLambdaSum[nCD] += dPi[nCK];
}
#pragma omp critical
{
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
dZeta[nCK * nNumOfWords + nCW] += dPi[nCK];
dZetaSum[nCK] += dPi[nCK];
}
}
}
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
dX[nCK] = dMeanR[nTemp + nCK];
dX[nNumOfTopics + nCK] = dStdevS[nTemp + nCK];
}
lbfgs_parameter_init(&param);
param.linesearch = LBFGS_LINESEARCH_BACKTRACKING_ARMIJO;
lbfgs(nNumOfTopics * 2, dX, &dFX, LBFGS_MeanR, LBFGS_progress, &nCD, &param);
//printf("LBFGS(%d)\t%d\t", nRet, nCD);
//printf("fx = %.6le, x[0] = %.6le, x[1] = %.6le\n", dFX, dX[nNumOfTopics], dX[nNumOfTopics + 1]);
if ((! isnan(dFX)) && (! isinf(dFX))) {
for (nCK = 0; nCK < nNumOfTopics; nCK ++) {
dMeanR[nTemp + nCK] = dX[nCK];
if (dX[nNumOfTopics + nCK] > 0.0)
dStdevS[nTemp + nCK] = dX[nNumOfTopics + nCK];
}
nTemp = nCD * nNumOfTopics;
dNu[nCD] = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dNu[nCD] += exp(dMeanR[nTemp + nCK]
+ 0.5 * dStdevS[nTemp + nCK] * dStdevS[nTemp + nCK]);
}
}
#pragma omp barrier
for (nCK = nThreadID; nCK < nNumOfTopics; nCK += nNumOfThreads) {
dZetaSum2[nCK] = digamma(dZetaSum[nCK]);
nTemp = nCK * nNumOfWords;
for (nCW = 0; nCW < nNumOfWords; nCW ++)
dZeta2[nTemp + nCW] = digamma(dZeta[nTemp + nCW]);
}
#pragma omp barrier
for (nCW = nThreadID; nCW < nNumOfWords; nCW += nNumOfThreads) {
dTemp = dBeta[nCW];
dBeta[nCW] = 0.0;
for (nCK = 0; nCK < nNumOfTopics; nCK ++)
dBeta[nCW] += (dZeta2[nCK * nNumOfWords + nCW] - dZetaSum2[nCK]);
dBeta[nCW] = invDigamma(digamma(dBetaSum) + dBeta[nCW] / ((DTYPE) nNumOfTopics));
if ((dBeta[nCW] < MIN_HYP) || isnan(dBeta[nCW]) || isinf(dBeta[nCW])) dBeta[nCW] = dTemp;
}
#pragma omp barrier
free(dPi);
lbfgs_free(dX);
}
{
int nCW;
dBetaSum = 0.0;
for (nCW = 0; nCW < nNumOfWords; nCW ++) dBetaSum += dBeta[nCW];
}
fprintf(fOut, "#I\t%d\t", nIteration);
fprintf(fOut, "%.3lf\t", logEviLB());
fprintf(fOut, "%.3lf\t", perplexityLDA(1));
put_time(fOut);
fprintf(fOut, "\t%d\t%.6lf", nIteration, dBetaSum / ((DTYPE) nNumOfWords));
fprintf(fOut, "\n");
fflush(fOut);
nIteration ++;
if (nIteration == 1) printLog(nIteration);
} while (nIteration < NUM_OF_VB_ITERATIONS);
printLog(nIteration);
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment