/* Copyright 2004, Carnegie Mellon, All Rights Reserved */
package edu.cmu.minorthird.classify.sequential;
import org.apache.log4j.Logger;
import edu.cmu.minorthird.classify.Classifier;
import edu.cmu.minorthird.classify.ExampleSchema;
import edu.cmu.minorthird.classify.algorithms.linear.Hyperplane;
/**
* Adjust the precision-recall of a CMM that is based on an array of hyperplanes,
* by adjusting the bias term of the hyperplane associated with the background (NEG)
* class. This is intended mainly for adjusting precision-recall performance of
* extractors learned by CollinsPerceptronLearner and CRFLearner.
*
* @author William Cohen
*/
public class CMMTweaker implements SequenceConstants
{
static private Logger log = Logger.getLogger(CMMTweaker.class);
static private double oldBias = -1;
static private double newBias = -1;
/** Return the value of bias term before the last tweak.
*/
public double oldBias() { return oldBias; }
/** Return the value of bias term after tweaking.
*/
public double newBias() { return newBias; }
/** Return a copy of a CMM in which the one bias term, for the
* hyperplane corresponding to the NEG class, has been changed.
* The original CMM will not be modified.
*/
public CMM tweak(CMM cmm,double bias)
{
Classifier c = cmm.getClassifier();
if (c instanceof CollinsPerceptronLearner.MultiClassVPClassifier) {
CollinsPerceptronLearner.MultiClassVPClassifier mc =
(CollinsPerceptronLearner.MultiClassVPClassifier)c;
Hyperplane[] h = mc.getHyperplanes();
ExampleSchema schema = mc.getSchema();
int histSize = cmm.getHistorySize();
return new CMM( new SequenceUtils.MultiClassClassifier(schema,tweak(h,schema,bias)),histSize,schema);
} else if (c instanceof SequenceUtils.MultiClassClassifier) {
SequenceUtils.MultiClassClassifier mc = (SequenceUtils.MultiClassClassifier)c;
Classifier[] bc = mc.getBinaryClassifiers();
Hyperplane[] h = new Hyperplane[bc.length];
for (int i=0; i<bc.length; i++) {
if (!(bc[i] instanceof Hyperplane)) {
throw new IllegalArgumentException("invalid type of MultiClassClassifier: contains "+
bc[i].getClass());
}
h[i] = (Hyperplane)bc[i];
}
ExampleSchema schema = mc.getSchema();
int histSize = cmm.getHistorySize();
return new CMM( new SequenceUtils.MultiClassClassifier(schema,tweak(h,schema,bias)),histSize,schema);
} else {
throw new IllegalArgumentException("invalid type of CMM classifier "+c.getClass());
}
}
private Hyperplane[] tweak(Hyperplane[] h,ExampleSchema schema,double bias)
{
Hyperplane[] tweakedH = new Hyperplane[h.length];
for (int i=0; i<h.length; i++) {
tweakedH[i] = h[i];
}
int n = schema.getClassIndex(ExampleSchema.NEG_CLASS_NAME);
tweakedH[n] = new Hyperplane();
tweakedH[n].increment( h[n] );
tweakedH[n].setBias( bias );
oldBias = h[n].featureScore( Hyperplane.BIAS_TERM );
newBias = bias;
log.info("bias term for NEG hyperplane: "+oldBias+" => "+bias);
return tweakedH;
}
}