use of com.amazon.randomcutforest.returntypes.DiVector in project random-cut-forest-by-aws by aws.
the class AnomalyAttributionVisitorTest method testAcceptLeafEquals.
@Test
public void testAcceptLeafEquals() {
float[] point = { 1.1f, -2.2f, 3.3f };
INodeView leafNode = mock(NodeView.class);
when(leafNode.getLeafPoint()).thenReturn(point);
when(leafNode.getBoundingBox()).thenReturn(new BoundingBox(point, point));
int leafDepth = 100;
int leafMass = 10;
when(leafNode.getMass()).thenReturn(leafMass);
int treeMass = 21;
AnomalyAttributionVisitor visitor = new AnomalyAttributionVisitor(point, treeMass, 0);
visitor.acceptLeaf(leafNode, leafDepth);
assertTrue(visitor.hitDuplicates);
double expectedScoreSum = CommonUtils.defaultDampFunction(leafMass, treeMass) / (leafDepth + Math.log(leafMass + 1) / Math.log(2));
double expectedScore = expectedScoreSum / (2 * point.length);
DiVector result = visitor.getResult();
for (int i = 0; i < point.length; i++) {
assertEquals(defaultScalarNormalizerFunction(expectedScore, treeMass), result.low[i], EPSILON);
assertEquals(defaultScalarNormalizerFunction(expectedScore, treeMass), result.high[i], EPSILON);
}
}
use of com.amazon.randomcutforest.returntypes.DiVector in project random-cut-forest-by-aws by aws.
the class RandomCutForestFunctionalTest method testSideEffectsB.
@ParameterizedTest
@ArgumentsSource(TestForestProvider.class)
public void testSideEffectsB(RandomCutForest forest) {
/* the changes to score and attribution should be in sync */
DiVector initial = forest.getAnomalyAttribution(new double[] { 0.0, 0.0, 0.0 });
NormalMixtureTestData generator2 = new NormalMixtureTestData(baseMu, baseSigma, anomalyMu, anomalySigma, transitionToAnomalyProbability, transitionToBaseProbability);
double[][] newData = generator2.generateTestData(dataSize, dimensions);
for (int i = 0; i < dataSize; i++) {
forest.getAnomalyAttribution(newData[i]);
}
double newScore = forest.getAnomalyScore(new double[] { 0.0, 0.0, 0.0 });
DiVector newVector = forest.getAnomalyAttribution(new double[] { 0.0, 0.0, 0.0 });
assertEquals(initial.getHighLowSum(), newVector.getHighLowSum(), 10E-10);
assertEquals(initial.getHighLowSum(), newScore, 1E-10);
assertArrayEquals(initial.high, newVector.high, 1E-10);
assertArrayEquals(initial.low, newVector.low, 1E-10);
}
use of com.amazon.randomcutforest.returntypes.DiVector in project random-cut-forest-by-aws by aws.
the class RandomCutForestFunctionalTest method testShadowBuffer.
@Test
public void testShadowBuffer() {
/**
* This test checks that the attribution *DOES NOT* change as a ratio as more
* copies of the points are added. The shadowbox in
* the @DirectionalAttributionVisitor allows us to simulate a deletion without
* performing a deletion.
*
* The goal is to measure the attribution and have many copies of the same point
* and eventually the attribution will become uniform in all directions.
*
* we create a new forest so that other tests are unaffected.
*/
numberOfTrees = 100;
sampleSize = 256;
dimensions = 3;
randomSeed = 123;
RandomCutForest newForest = RandomCutForest.builder().numberOfTrees(numberOfTrees).sampleSize(sampleSize).dimensions(dimensions).randomSeed(randomSeed).centerOfMassEnabled(true).timeDecay(1e-5).storeSequenceIndexesEnabled(true).build();
dataSize = 10_000;
baseMu = 0.0;
baseSigma = 1.0;
anomalyMu = 5.0;
anomalySigma = 1.5;
transitionToAnomalyProbability = 0.01;
transitionToBaseProbability = 0.4;
NormalMixtureTestData generator = new NormalMixtureTestData(baseMu, baseSigma, anomalyMu, anomalySigma, transitionToAnomalyProbability, transitionToBaseProbability);
double[][] data = generator.generateTestData(dataSize, dimensions);
for (int i = 0; i < dataSize; i++) {
newForest.update(data[i]);
}
double[] point = new double[] { -8.0, -8.0, 0.0 };
DiVector result = newForest.getAnomalyAttribution(point);
double score = newForest.getAnomalyScore(point);
assertEquals(score, result.getHighLowSum(), 1E-5);
assertTrue(score > 2);
assertTrue(result.getHighLowSum(2) < 0.2);
// 256/10_000
for (int i = 0; i < 5; i++) {
newForest.update(point);
}
DiVector newResult = newForest.getAnomalyAttribution(point);
double newScore = newForest.getAnomalyScore(point);
assertEquals(newScore, newResult.getHighLowSum(), 1E-5);
assertTrue(newScore < score);
for (int j = 0; j < 3; j++) {
// relationship holds at larger values
if (result.high[j] > 0.2) {
assertEquals(score * newResult.high[j], newScore * result.high[j], 0.1 * score);
} else {
assertTrue(newResult.high[j] < 0.2);
}
if (result.low[j] > 0.2) {
assertEquals(score * newResult.low[j], newScore * result.low[j], 0.1 * score);
} else {
assertTrue(newResult.low[j] < 0.2);
}
}
// this will make the point an inlier
for (int i = 0; i < 5000; i++) {
newForest.update(point);
}
DiVector finalResult = newForest.getAnomalyAttribution(point);
double finalScore = newForest.getAnomalyScore(point);
assertTrue(finalScore < 1);
assertEquals(finalScore, finalResult.getHighLowSum(), 1E-5);
for (int j = 0; j < 3; j++) {
// relationship holds at larger values
if (finalResult.high[j] > 0.2) {
assertEquals(score * finalResult.high[j], finalScore * result.high[j], 0.1 * score);
} else {
assertTrue(newResult.high[j] < 0.2);
}
if (finalResult.low[j] > 0.2) {
assertEquals(score * finalResult.low[j], finalScore * result.low[j], 0.1 * score);
} else {
assertTrue(finalResult.low[j] < 0.2);
}
}
}
use of com.amazon.randomcutforest.returntypes.DiVector in project random-cut-forest-by-aws by aws.
the class RandomCutForestTest method testGetAnomalyAttribution.
@Test
public void testGetAnomalyAttribution() {
float[] point = { 1.2f, -3.4f };
assertFalse(forest.isOutputReady());
DiVector zero = new DiVector(dimensions);
DiVector result = forest.getAnomalyAttribution(point);
assertArrayEquals(zero.high, result.high);
assertArrayEquals(zero.low, result.low);
doReturn(true).when(forest).isOutputReady();
DiVector expectedResult = new DiVector(dimensions);
for (int i = 0; i < numberOfTrees; i++) {
DiVector treeResult = new DiVector(dimensions);
for (int j = 0; j < dimensions; j++) {
treeResult.high[j] = Math.random();
treeResult.low[j] = Math.random();
}
SamplerPlusTree<Integer, float[]> component = (SamplerPlusTree<Integer, float[]>) components.get(i);
ITree<Integer, float[]> tree = component.getTree();
when(tree.traverse(aryEq(point), any(VisitorFactory.class))).thenReturn(treeResult);
when(tree.getMass()).thenReturn(256);
DiVector.addToLeft(expectedResult, treeResult);
}
expectedResult = expectedResult.scale(1.0 / numberOfTrees);
result = forest.getAnomalyAttribution(point);
assertArrayEquals(expectedResult.high, result.high, EPSILON);
assertArrayEquals(expectedResult.low, result.low, EPSILON);
}
use of com.amazon.randomcutforest.returntypes.DiVector in project random-cut-forest-by-aws by aws.
the class RandomCutForest method getApproximateAnomalyAttribution.
public DiVector getApproximateAnomalyAttribution(float[] point) {
if (!isOutputReady()) {
return new DiVector(dimensions);
}
IVisitorFactory<DiVector> visitorFactory = new VisitorFactory<>((tree, y) -> new AnomalyAttributionVisitor(tree.projectToTree(y), tree.getMass()), (tree, x) -> x.lift(tree::liftFromTree));
ConvergingAccumulator<DiVector> accumulator = new OneSidedConvergingDiVectorAccumulator(dimensions, DEFAULT_APPROXIMATE_ANOMALY_SCORE_HIGH_IS_CRITICAL, DEFAULT_APPROXIMATE_DYNAMIC_SCORE_PRECISION, DEFAULT_APPROXIMATE_DYNAMIC_SCORE_MIN_VALUES_ACCEPTED, numberOfTrees);
Function<DiVector, DiVector> finisher = x -> x.scale(1.0 / accumulator.getValuesAccepted());
return traverseForest(transformToShingledPoint(point), visitorFactory, accumulator, finisher);
}
Aggregations