📄 weightedperformancemeasures.java
字号:
if (this.getProbability(i + Attribute.FIRST_CLASS_INDEX, prediction) > 0)
nonNulls++;
}
return nonNulls;
}
/**
* The bias of the rule specified by the nominal variable's indices.
* <code>RULE_DOES_NOT_APPLY</code> is returned to indicate that no
* such example has ever been observed, <code>Double.POSITIVE_INFINITY</code>
* is returned if the class membership can deterministically be concluded
* from the prediction.
*
* Important: In the multi-class case some of the classes might not be
* observed at all when a specific rule applies, but still the rule does
* not necessarily have a deterministic part. In this case the remaining
* number of classes is considered to be the complete set of classes when
* calculating the default values and biases! This does not affect the
* prediction of the most likely class label, because the classes not observed
* have a probability of one, the other estimates increase proportionally.
* However, to calculate probabilities it is necessary to normalize the
* estimates in the class <code>BayBoostModel</code>.
*
* @param label the true label
* @param prediction the predicted label
* @return the bias, which is a value >= 0, positive infinity if all examples
* with this prediction belong to that class (deterministic rule), or
* <code>RULE_DOES_NOT_APPLY</code> if no prediction can be made.
*/
public double getBias(int label, int prediction) {
double prLabel = this.getProbabilityLabel(label);
double prPred = this.getProbabilityPrediction(prediction);
double prJoint = this.getProbability(label, prediction);
if (prPred == 0) {
return RULE_DOES_NOT_APPLY;
}
else if (prJoint == 0) {
return (0);
}
else if (prJoint == prPred) {
return (Double.POSITIVE_INFINITY);
}
double bias = prJoint / (prLabel * prPred);
return bias;
}
/**
* The factor to be applied (pn-ratio) for each label if the model yields the
* specific prediction.
* @param prediction the predicted class
* @return a <code>double[]</code> array containing one factor for each class.
* The first index is 0 and needs to be translated into the YALE representation
* by adding <code>Attribute.FIRST_CLASS_INDEX</code>. The result should either
* consist of well defined biases >= 0, or all fields should mutually contain the
* constant <code>RULE_DOES_NOT_APPLY</code>.
*/
public double[] getPnRatios(int prediction) {
double[] biases = new double[this.labels.length];
for (int i=0; i<biases.length; i++) {
int yaleLabelIndex = i + Attribute.FIRST_CLASS_INDEX;
double b = this.getBias(yaleLabelIndex, prediction);
if (b == 0 || b == Double.POSITIVE_INFINITY) {
biases[i] = b;
}
else {
// In this case the corresponding bias of the remaining classes
// should also be defined. Using the odds avoids calculating the
// probability of premises.
double negLabel = 1 - this.getProbabilityLabel(yaleLabelIndex);
double probPred = this.getProbabilityPrediction(prediction);
double probPredLabel = this.getProbability(yaleLabelIndex, prediction);
double negLabelPred = probPred - probPredLabel;
double oppositeBias = negLabelPred / (negLabel * probPred);
// What is stored is Prob(label | pred) / Prob (neg(label) | pred):
biases[i] = b / oppositeBias;
}
}
return biases;
}
/** @return a matrix with one pn-bias per prediction/label combination. */
public double[][] createBiasMatrix() {
int numPredictions = this.getNumberOfPredictions();
double[][] biasMatrix = new double[numPredictions][];
for (int i=0; i<numPredictions; i++) {
biasMatrix[i] = this.getPnRatios(i + Attribute.FIRST_CLASS_INDEX);
}
return biasMatrix;
}
/** @return a <code>double[]</code> with the prior probabilities of all class labels. */
public double[] getLabelPriors() {
double[] priors = new double[this.getNumberOfLabels()];
for (int i=0; i<priors.length; i++) {
priors[i] = this.getProbabilityLabel(i + Attribute.FIRST_CLASS_INDEX);
}
return priors;
}
/**
* Helper method of the <code>BayesianBoosting</code> operator
*
* This method reweights the example set with respect to the <code>WeightedPerformanceMeasures</code>
* object. Please note that the weights will not be reset at any time, because they continuously
* change from one iteration to the next.
* This method does not change the priors of the classes.
* @param exampleSet <code>ExampleSet</code> to be reweighted
* @return <code>true</code> iff the total weight is greater than 0 after reweighting.
*/
public boolean reweightExamples(ExampleSet exampleSet) throws OperatorException
{
return this.reweightExamples(exampleSet, false);
}
/**
* Helper method of the <code>BayesianBoosting</code> operator
*
* This method reweights the example set with respect to the <code>WeightedPerformanceMeasures</code>
* object. Please note that the weights will not be reset at any time, because they continuously
* change from one iteration to the next.
* @param exampleSet <code>ExampleSet</code> to be reweighted
* @param rescalePriors <code>true</code> iff all labels should be equally likely after reweighting
* @return <code>true</code> iff the total weight is greater than 0 after reweighting.
*/
public boolean reweightExamples(ExampleSet exampleSet, boolean rescalePriors) throws OperatorException
{
ExampleReader reader = exampleSet.getExampleReader();
double totalWeight = 0;
final boolean crisp;
{
Attribute predictedLabel = exampleSet.getPredictedLabel();
if (predictedLabel.isNumerical()) {
crisp = false; // soft classifier
}
else crisp = true; // default: crisp classifier, multi-class predictions possible
}
while (reader.hasNext()) {
Example example = reader.next();
int label = (int) example.getLabel();
double bias = 0;
if (crisp == true) {
int predicted = (int) example.getPredictedLabel();
bias = this.getBias(label, predicted);
if (rescalePriors == true) {
// multiply with Pr(y) to get Pr(y | x) and divide by target probability
// of (1 / #classes), equivalent to multiplying with ( Pr(y) * #classes ).
bias *= (this.getProbabilityLabel(label) * this.getNumberOfLabels());
}
}
else {
double predicted1 = Math.max(0, Math.min(1, example.getPredictedLabel()));
Attribute labelAttr = exampleSet.getLabel();
// This code seems to be problematic:
double bias0 = this.getBias(label, labelAttr.getNegativeIndex());
double bias1 = this.getBias(label, labelAttr.getPositiveIndex());
// Please replace by lines above as soon as the code has been debugged:
//double bias0 = this.getBias(label, Attribute.FIRST_CLASS_INDEX);
//double bias1 = this.getBias(label, Attribute.FIRST_CLASS_INDEX + 1);
// ---
if (rescalePriors == true) {
// multiply with Pr(y) to get Pr(y | x) and divide by target probability
// of (1 / #classes), equivalent to multiplying with ( Pr(y) * #classes ).
int numLabels = this.getNumberOfLabels();
bias0 *= (this.getProbabilityLabel(labelAttr.getNegativeIndex()) * numLabels);
bias1 *= (this.getProbabilityLabel(labelAttr.getPositiveIndex()) * numLabels);
}
if (bias0 == RULE_DOES_NOT_APPLY || bias1 == Double.POSITIVE_INFINITY || Double.isNaN(bias0))
bias = bias1;
else if (bias1 == RULE_DOES_NOT_APPLY || bias0 == Double.POSITIVE_INFINITY || Double.isNaN(bias1))
bias = bias0;
else bias = predicted1 * bias1 + (1 - predicted1) * bias0;
}
if (bias == RULE_DOES_NOT_APPLY) {
throw new OperatorException(
"Internal error in class WeightedPerformanceMeasure: Applied rule marked as non-applicable!");
}
if (bias == 0 || bias == Double.POSITIVE_INFINITY || Double.isNaN(bias)) {
example.setWeight(0); // Covered, done. There are nicer ways, however!
}
else {
double newWeight = example.getWeight() / bias;
example.setWeight(newWeight);
totalWeight += newWeight;
}
}
return totalWeight > 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -