InformationGainScorer.java
package org.hammer.audio.experimental.acoustic.feature.ranking;
import java.util.Map;
import org.hammer.audio.experimental.acoustic.feature.evaluation.ClassSeparationScore;
import org.hammer.audio.experimental.acoustic.feature.evaluation.FeatureEvaluationEntry;
/**
* Estimates feature utility with a Fisher-weighted entropy proxy.
*
* <p>This scorer computes the class-label prior entropy {@code H(Y)} from {@link
* ClassSeparationScore#classCounts()} and then scales it by {@code fisherRatio / (1 +
* fisherRatio)}. It is an information-gain-inspired heuristic, not an exact information gain
* computation.
*/
public final class InformationGainScorer implements FeatureScorer {
private static final double LOG2 = Math.log(2.0);
@Override
public double score(FeatureEvaluationEntry entry) {
ClassSeparationScore sep = entry.separation();
Map<String, Integer> counts = sep.classCounts();
int total = 0;
for (int c : counts.values()) {
total += c;
}
if (total == 0) {
return 0.0;
}
// H(Y): entropy of the marginal class distribution
double priorEntropy = 0.0;
for (int c : counts.values()) {
if (c > 0) {
double p = c / (double) total;
priorEntropy -= p * (Math.log(p) / LOG2);
}
}
// Approximation: features with high Fisher ratio reduce entropy proportionally.
// IG ≈ priorEntropy * (fisherRatio / (1 + fisherRatio))
double fisher = sep.fisherRatio();
return priorEntropy * (fisher / (1.0 + fisher));
}
@Override
public String name() {
return "informationGain";
}
}