use of com.amazon.randomcutforest.tree.IBoundingBoxView in project random-cut-forest-by-aws by aws.
the class AnomalyScoreVisitorTest method testGetProbabilityOfSeparation.
@Test
public void testGetProbabilityOfSeparation() {
float[] minPoint = { 0.0f, 0.0f, 0.0f };
float[] maxPoint = { 1.0f, 2.0f, 3.0f };
IBoundingBoxView boundingBox = new BoundingBox(minPoint);
boundingBox = boundingBox.getMergedBox(maxPoint);
float[] point = { 0.5f, 0.5f, 0.5f };
int sampleSize = 2;
AnomalyScoreVisitor visitor = new AnomalyScoreVisitor(point, sampleSize);
double p = visitor.getProbabilityOfSeparation(boundingBox);
assertThat(p, closeTo(0.0, EPSILON));
assertTrue(visitor.coordInsideBox[0]);
assertTrue(visitor.coordInsideBox[1]);
assertTrue(visitor.coordInsideBox[2]);
visitor = new AnomalyScoreVisitor(point, sampleSize);
visitor.coordInsideBox[1] = visitor.coordInsideBox[2] = true;
p = visitor.getProbabilityOfSeparation(boundingBox);
assertThat(p, closeTo(0.0, EPSILON));
assertTrue(visitor.coordInsideBox[0]);
assertTrue(visitor.coordInsideBox[1]);
assertTrue(visitor.coordInsideBox[2]);
point = new float[] { 2.0f, 0.5f, 0.5f };
visitor = new AnomalyScoreVisitor(point, sampleSize);
p = visitor.getProbabilityOfSeparation(boundingBox);
assertThat(p, closeTo(1.0 / (2.0 + 2.0 + 3.0), EPSILON));
assertFalse(visitor.coordInsideBox[0]);
assertTrue(visitor.coordInsideBox[1]);
assertTrue(visitor.coordInsideBox[2]);
visitor = new AnomalyScoreVisitor(point, sampleSize);
visitor.coordInsideBox[1] = visitor.coordInsideBox[2] = true;
p = visitor.getProbabilityOfSeparation(boundingBox);
assertThat(p, closeTo(1.0 / (2.0 + 2.0 + 3.0), EPSILON));
assertFalse(visitor.coordInsideBox[0]);
assertTrue(visitor.coordInsideBox[1]);
assertTrue(visitor.coordInsideBox[2]);
point = new float[] { 0.5f, -3.0f, 4.0f };
visitor = new AnomalyScoreVisitor(point, sampleSize);
p = visitor.getProbabilityOfSeparation(boundingBox);
assertThat(p, closeTo((3.0 + 1.0) / (1.0 + 5.0 + 4.0), EPSILON));
assertTrue(visitor.coordInsideBox[0]);
assertFalse(visitor.coordInsideBox[1]);
assertFalse(visitor.coordInsideBox[2]);
visitor = new AnomalyScoreVisitor(point, sampleSize);
visitor.coordInsideBox[0] = true;
p = visitor.getProbabilityOfSeparation(boundingBox);
assertThat(p, closeTo((3.0 + 1.0) / (1.0 + 5.0 + 4.0), EPSILON));
assertTrue(visitor.coordInsideBox[0]);
assertFalse(visitor.coordInsideBox[1]);
assertFalse(visitor.coordInsideBox[2]);
}
use of com.amazon.randomcutforest.tree.IBoundingBoxView in project random-cut-forest-by-aws by aws.
the class AbstractAttributionVisitor method accept.
/**
* Update the anomaly score based on the next step of the tree traversal.
*
* @param node The current node in the tree traversal
* @param depthOfNode The depth of the current node in the tree
*/
@Override
public void accept(INodeView node, int depthOfNode) {
if (pointInsideBox) {
return;
}
IBoundingBoxView smallBox;
if (hitDuplicates || ignoreLeaf) {
// use the sibling bounding box to represent counterfactual "what if point & the
// candidate near neighbor
// had not been inserted in the tree"
shadowBox = shadowBox == null ? node.getSiblingBoundingBox(pointToScore) : shadowBox.getMergedBox(node.getSiblingBoundingBox(pointToScore));
smallBox = shadowBox;
} else {
smallBox = node.getBoundingBox();
}
IBoundingBoxView largeBox = smallBox.getMergedBox(pointToScore);
updateRangesForScoring(smallBox, largeBox);
double probOfCut = sumOfDifferenceInRange / sumOfNewRange;
// if leaves were ignored we need to keep accounting for the score
if (ignoreLeaf) {
savedScore = probOfCut * scoreUnseen(depthOfNode, node.getMass()) + (1 - probOfCut) * savedScore;
}
if (probOfCut <= 0) {
pointInsideBox = true;
} else {
double newScore = scoreUnseen(depthOfNode, node.getMass());
for (int i = 0; i < pointToScore.length; i++) {
double probOfCutInSpikeDirection = differenceInRangeVector[2 * i] / sumOfNewRange;
directionalAttribution.high[i] = probOfCutInSpikeDirection * newScore + (1 - probOfCut) * directionalAttribution.high[i];
double probOfCutInDipDirection = differenceInRangeVector[2 * i + 1] / sumOfNewRange;
directionalAttribution.low[i] = probOfCutInDipDirection * newScore + (1 - probOfCut) * directionalAttribution.low[i];
}
}
if ((hitDuplicates || ignoreLeaf) && (pointInsideBox || depthOfNode == 0)) {
// final rescaling; this ensures agreement with the ScalarScoreVector
// the scoreUnseen/scoreSeen should be the same as scoring; other uses need
// caution.
directionalAttribution.renormalize(savedScore);
}
}
use of com.amazon.randomcutforest.tree.IBoundingBoxView in project random-cut-forest-by-aws by aws.
the class TransductiveScalarScoreVisitor method getWeight.
// for this visitor class the assumption is that the trees are built using the
// same probabilities as are used in scoring. In the application herein
// vecSepBuild
// is the same as vecSepScore as in the accept(node) above; however the function
// is
// written in the more general form so that it can be used for the Simulated
// version as well without any changes.
protected double getWeight(int dim, Function<IBoundingBoxView, double[]> vecSepBuild, final IBoundingBoxView boundingBox) {
double[] vecSmall = vecSepBuild.apply(boundingBox);
// the smaller box was built!
IBoundingBoxView largeBox = boundingBox.getMergedBox(pointToScore);
double[] vecLarge = vecSepScore.apply(largeBox);
// the larger box is only scored!
double sumSmall = 0;
double sumLarge = 0;
for (int i = 0; i < pointToScore.length; i++) {
sumSmall += vecSmall[i];
sumLarge += vecLarge[i];
}
return (boundingBox.getRange(dim) / largeBox.getRange(dim)) * (sumSmall / sumLarge) * (vecLarge[dim] / vecSmall[dim]);
// this can be larger than 1
// For RCFs vecLarge[dim] = largeBox.getRange(dim) and
// vecSmall[dim] = smallBox.getRange(dim)
// sumSmall/sumLarge is the probability of non-separation
}
Aggregations