in samoa-api/src/main/java/org/apache/samoa/moa/classifiers/core/attributeclassobservers/VFMLNumericAttributeClassObserver.java [72:177]
public void observeAttributeClass(double attVal, int classVal, double weight) {
if (!Utils.isMissingValue(attVal)) {
if (this.binList.size() < 1) {
// create the first bin
Bin newBin = new Bin();
newBin.classWeights.addToValue(classVal, weight);
newBin.boundaryClass = classVal;
newBin.boundaryWeight = weight;
newBin.upperBound = attVal;
newBin.lowerBound = attVal;
this.binList.add(newBin);
} else {
// find bin containing new example with binary search
int index = 0;
boolean found = false;
int min = 0;
int max = this.binList.size() - 1;
while ((min <= max) && !found) {
int i = (min + max) / 2;
Bin bin = this.binList.get(i);
if (((attVal >= bin.lowerBound) && (attVal < bin.upperBound))
|| ((i == this.binList.size() - 1)
&& (attVal >= bin.lowerBound) && (attVal <= bin.upperBound))) {
found = true;
index = i;
} else if (attVal < bin.lowerBound) {
max = i - 1;
} else {
min = i + 1;
}
}
boolean first = false;
boolean last = false;
if (!found) {
// determine if it is before or after the existing range
Bin bin = this.binList.get(0);
if (bin.lowerBound > attVal) {
// go before the first bin
index = 0;
first = true;
} else {
// if we haven't found it yet value must be > last bins
// upperBound
index = this.binList.size() - 1;
last = true;
}
}
Bin bin = this.binList.get(index); // VLIndex(ct->bins, index);
if ((bin.lowerBound == attVal)
|| (this.binList.size() >= this.numBinsOption.getValue())) {// Option.getValue())
// {//1000)
// {
// if this is the exact same boundary and class as the bin
// boundary or we aren't adding new bins any more then
// increment
// boundary counts
bin.classWeights.addToValue(classVal, weight);
if ((bin.boundaryClass == classVal)
&& (bin.lowerBound == attVal)) {
// if it is also the same class then special case it
bin.boundaryWeight += weight;
}
} else {
// create a new bin
Bin newBin = new Bin();
newBin.classWeights.addToValue(classVal, weight);
newBin.boundaryWeight = weight;
newBin.boundaryClass = classVal;
newBin.upperBound = bin.upperBound;
newBin.lowerBound = attVal;
double percent = 0.0;
// estimate initial counts with a linear interpolation
if (!((bin.upperBound - bin.lowerBound == 0) || last || first)) {
percent = 1.0 - ((attVal - bin.lowerBound) / (bin.upperBound - bin.lowerBound));
}
// take out the boundry points, they stay with the old bin
bin.classWeights.addToValue(bin.boundaryClass,
-bin.boundaryWeight);
DoubleVector weightToShift = new DoubleVector(
bin.classWeights);
weightToShift.scaleValues(percent);
newBin.classWeights.addValues(weightToShift);
bin.classWeights.subtractValues(weightToShift);
// put the boundry examples back in
bin.classWeights.addToValue(bin.boundaryClass,
bin.boundaryWeight);
// insert the new bin in the right place
if (last) {
bin.upperBound = attVal;
newBin.upperBound = attVal;
this.binList.add(newBin);
} else if (first) {
newBin.upperBound = bin.lowerBound;
this.binList.add(0, newBin);
} else {
newBin.upperBound = bin.upperBound;
bin.upperBound = attVal;
this.binList.add(index + 1, newBin);
}
}
}
}
}