public InferredDocument infer(Vector wordCounts) {
double docTotal = wordCounts.zSum();
int docLength = wordCounts.size();
// initialize variational approximation to p(z|doc)
Vector gamma = new DenseVector(state.numTopics);
gamma.assign(state.topicSmoothing + docTotal / state.numTopics);
Vector nextGamma = new DenseVector(state.numTopics);
DenseMatrix phi = new DenseMatrix(state.numTopics, docLength);
// digamma is expensive, precompute
Vector digammaGamma = digamma(gamma);
// and log normalize:
double digammaSumGamma = digamma(gamma.zSum());
digammaGamma = digammaGamma.plus(-digammaSumGamma);
Map<Integer, Integer> columnMap = new HashMap<Integer, Integer>();
int iteration = 0;
final int MAX_ITER = 20;
boolean converged = false;
double oldLL = 1;
while (!converged && iteration < MAX_ITER) {
nextGamma.assign(state.topicSmoothing); // nG := alpha, for all topics
int mapping = 0;
for (Iterator<Vector.Element> iter = wordCounts.iterateNonZero();
iter.hasNext();) {
Vector.Element e = iter.next();
int word = e.index();
Vector phiW = eStepForWord(word, digammaGamma);
phi.assignColumn(mapping, phiW);
if (iteration == 0) { // first iteration
columnMap.put(word, mapping);
}
for (int k = 0; k < nextGamma.size(); ++k) {
double g = nextGamma.getQuick(k);
nextGamma.setQuick(k, g + e.get() * Math.exp(phiW.get(k)));
}
mapping++;
}