public MaximizableTrainer (){}
public MaximizableTrainer (InstanceList ilist, RankMaxEnt initialClassifier)
{
this.trainingList = ilist;
Alphabet fd = ilist.getDataAlphabet();
LabelAlphabet ld = (LabelAlphabet) ilist.getTargetAlphabet();
// Don't fd.stopGrowth, because someone might want to do feature induction
//ld.stopGrowth();
// Add one feature for the "default feature".
// assume underlying Instances are binary
//this.numLabels = underlyingLabelAlphabet.size();
// xxx
this.numLabels = 2;
this.numFeatures = fd.size() + 1;
this.defaultFeatureIndex = numFeatures-1;
this.parameters = new double [numLabels * numFeatures];
this.constraints = new double [numLabels * numFeatures];
this.cachedGradient = new double [numLabels * numFeatures];
Arrays.fill (parameters, 0.0);
Arrays.fill (constraints, 0.0);
Arrays.fill (cachedGradient, 0.0);
this.featureSelection = ilist.getFeatureSelection();
this.perLabelFeatureSelection = ilist.getPerLabelFeatureSelection();
// Add the default feature index to the selection
if (featureSelection != null)
featureSelection.add (defaultFeatureIndex);
if (perLabelFeatureSelection != null)
for (int i = 0; i < perLabelFeatureSelection.length; i++)
perLabelFeatureSelection[i].add (defaultFeatureIndex);
// xxx Later change this to allow both to be set, but select which one to use by a boolean flag?
assert (featureSelection == null || perLabelFeatureSelection == null);
if (initialClassifier != null) {
this.theClassifier = initialClassifier;
this.parameters = theClassifier.parameters;
this.featureSelection = theClassifier.featureSelection;
this.perLabelFeatureSelection = theClassifier.perClassFeatureSelection;
this.defaultFeatureIndex = theClassifier.defaultFeatureIndex;
assert (initialClassifier.getInstancePipe() == ilist.getPipe());
}
else if (this.theClassifier == null) {
this.theClassifier = new RankMaxEnt (ilist.getPipe(), parameters, featureSelection, perLabelFeatureSelection);
}
cachedValueStale = true;
cachedGradientStale = true;
// Initialize the constraints, using only the constraints from
// the "positive" instance
Iterator<Instance> iter = trainingList.iterator ();
logger.fine("Number of instances in training list = " + trainingList.size());
while (iter.hasNext()) {
Instance instance = iter.next();
double instanceWeight = trainingList.getInstanceWeight(instance);
FeatureVectorSequence fvs = (FeatureVectorSequence) instance.getData();
// label of best instance in subList
Object target = instance.getTarget();
Label label = null;
if (target instanceof Labels)
label = ((Labels)target).get(0);
else label = (Label)target;
int positiveIndex =
Integer.valueOf(label.getBestLabel().getEntry().toString()).intValue();
if (positiveIndex == -1) { // invalid instance
logger.warning("True label is -1. Skipping...");
continue;
}
FeatureVector fv = (FeatureVector)fvs.get(positiveIndex);
Alphabet fdict = fv.getAlphabet();
assert (fv.getAlphabet() == fd);
// xxx ensure dimensionality of constraints correct
MatrixOps.rowPlusEquals (constraints, numFeatures, 0, fv, instanceWeight);
// For the default feature, whose weight is 1.0
assert(!Double.isNaN(instanceWeight)) : "instanceWeight is NaN";
//assert(!Double.isNaN(li)) : "bestIndex is NaN";
boolean hasNaN = false;
for(int i = 0; i < fv.numLocations(); i++) {
if(Double.isNaN(fv.valueAtLocation(i))) {
logger.info("NaN for feature " + fdict.lookupObject(fv.indexAtLocation(i)).toString());
hasNaN = true;
}
}
if(hasNaN)
logger.info("NaN in instance: " + instance.getName());