double[][] scores = new double[trainingList.size()][numLabels];
// pass 1: calculate model distribution
for (int ii = 0; ii < trainingList.size(); ii++) {
Instance instance = trainingList.get(ii);
double instanceWeight = trainingList.getInstanceWeight(instance);
// skip if labeled
if (instance.getTarget() != null) {
continue;
}
FeatureVector fv = (FeatureVector) instance.getData();
classifier.getClassificationScoresWithTemperature(instance, temperature, scores[ii]);
for (int loc = 0; loc < fv.numLocations(); loc++) {
int featureIndex = fv.indexAtLocation(loc);
if (constraints.containsKey(featureIndex)) {
int cIndex = mapping.get(featureIndex);
double val;
if (!useValues) {
val = 1.;
}
else {
val = fv.valueAtLocation(loc);
}
featureCounts[cIndex] += val;
for (int l = 0; l < numLabels; l++) {
modelExpectations[cIndex][l] += scores[ii][l] * val * instanceWeight;
}
}
}
// special case of label regularization
if (constraints.containsKey(defaultFeatureIndex)) {
int cIndex = mapping.get(defaultFeatureIndex);
featureCounts[cIndex] += 1;
for (int l = 0; l < numLabels; l++) {
modelExpectations[cIndex][l] += scores[ii][l] * instanceWeight;
}
}
}
double value = 0;
for (int featureIndex : constraints.keySet()) {
int cIndex = mapping.get(featureIndex);
if (featureCounts[cIndex] > 0) {
for (int label = 0; label < numLabels; label++) {
double cProb = constraints.get(featureIndex)[label];
// normalize by count
modelExpectations[cIndex][label] /= featureCounts[cIndex];
ratio[cIndex][label] = cProb / modelExpectations[cIndex][label];
// add to the cross entropy term
value += scalingFactor * cProb * Math.log(modelExpectations[cIndex][label]);
// add to the entropy term
if (cProb > 0) {
value -= scalingFactor * cProb * Math.log(cProb);
}
}
assert(Maths.almostEquals(MatrixOps.sum(modelExpectations[cIndex]),1));
}
}
// pass 2: determine per example gradient
for (int ii = 0; ii < trainingList.size(); ii++) {
Instance instance = trainingList.get(ii);
// skip if labeled
if (instance.getTarget() != null) {
continue;
}
double instanceWeight = trainingList.getInstanceWeight(instance);
FeatureVector fv = (FeatureVector) instance.getData();
for (int loc = 0; loc < fv.numLocations() + 1; loc++) {
int featureIndex;
if (loc == fv.numLocations()) {
featureIndex = defaultFeatureIndex;