Skip to content

Commit dd5461a

Browse files
committed
Separate ChangeDetectorTests and ChangePointAggregatorTests.
1 parent 2cbb0f2 commit dd5461a

File tree

2 files changed

+209
-191
lines changed

2 files changed

+209
-191
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.ml.aggs.changepoint;
9+
10+
import org.apache.commons.math3.distribution.GammaDistribution;
11+
import org.apache.commons.math3.distribution.NormalDistribution;
12+
import org.apache.commons.math3.random.RandomGeneratorFactory;
13+
import org.elasticsearch.common.Randomness;
14+
import org.elasticsearch.search.aggregations.AggregatorTestCase;
15+
16+
import java.util.concurrent.atomic.AtomicInteger;
17+
import java.util.stream.DoubleStream;
18+
19+
import static org.hamcrest.Matchers.equalTo;
20+
import static org.hamcrest.Matchers.greaterThan;
21+
import static org.hamcrest.Matchers.lessThan;
22+
23+
public class ChangeDetectorTests extends AggregatorTestCase {
24+
25+
public void testStationaryFalsePositiveRate() {
26+
NormalDistribution normal = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 0, 2);
27+
int fp = 0;
28+
for (int i = 0; i < 100; i++) {
29+
double[] bucketValues = DoubleStream.generate(() -> 10 + normal.sample()).limit(40).toArray();
30+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(1e-4);
31+
fp += test.type() == ChangeDetector.Type.STATIONARY ? 0 : 1;
32+
}
33+
assertThat(fp, lessThan(10));
34+
35+
fp = 0;
36+
GammaDistribution gamma = new GammaDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 1, 2);
37+
for (int i = 0; i < 100; i++) {
38+
double[] bucketValues = DoubleStream.generate(() -> gamma.sample()).limit(40).toArray();
39+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(1e-4);
40+
fp += test.type() == ChangeDetector.Type.STATIONARY ? 0 : 1;
41+
}
42+
assertThat(fp, lessThan(10));
43+
}
44+
45+
public void testSampledDistributionTestFalsePositiveRate() {
46+
NormalDistribution normal = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 0.0, 1.0);
47+
int fp = 0;
48+
for (int i = 0; i < 100; i++) {
49+
double[] bucketValues = DoubleStream.generate(() -> 10 + normal.sample()).limit(5000).toArray();
50+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(1e-4);
51+
fp += test.type() == ChangeDetector.Type.STATIONARY ? 0 : 1;
52+
}
53+
assertThat(fp, lessThan(10));
54+
}
55+
56+
public void testNonStationaryFalsePositiveRate() {
57+
NormalDistribution normal = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 0, 2);
58+
int fp = 0;
59+
for (int i = 0; i < 100; i++) {
60+
AtomicInteger j = new AtomicInteger();
61+
double[] bucketValues = DoubleStream.generate(() -> j.incrementAndGet() + normal.sample()).limit(40).toArray();
62+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(1e-4);
63+
fp += test.type() == ChangeDetector.Type.NON_STATIONARY ? 0 : 1;
64+
}
65+
assertThat(fp, lessThan(10));
66+
67+
fp = 0;
68+
GammaDistribution gamma = new GammaDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 1, 2);
69+
for (int i = 0; i < 100; i++) {
70+
AtomicInteger j = new AtomicInteger();
71+
double[] bucketValues = DoubleStream.generate(() -> j.incrementAndGet() + gamma.sample()).limit(40).toArray();
72+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(1e-4);
73+
fp += test.type() == ChangeDetector.Type.NON_STATIONARY ? 0 : 1;
74+
}
75+
assertThat(fp, lessThan(10));
76+
}
77+
78+
public void testStepChangePower() {
79+
NormalDistribution normal = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 0, 2);
80+
int tp = 0;
81+
for (int i = 0; i < 100; i++) {
82+
double[] bucketValues = DoubleStream.concat(
83+
DoubleStream.generate(() -> normal.sample()).limit(20),
84+
DoubleStream.generate(() -> 10 + normal.sample()).limit(20)
85+
).toArray();
86+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(0.05);
87+
tp += test.type() == ChangeDetector.Type.STEP_CHANGE ? 1 : 0;
88+
}
89+
assertThat(tp, greaterThan(80));
90+
91+
tp = 0;
92+
GammaDistribution gamma = new GammaDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 1, 2);
93+
for (int i = 0; i < 100; i++) {
94+
double[] bucketValues = DoubleStream.concat(
95+
DoubleStream.generate(() -> gamma.sample()).limit(20),
96+
DoubleStream.generate(() -> 10 + gamma.sample()).limit(20)
97+
).toArray();
98+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(0.05);
99+
tp += test.type() == ChangeDetector.Type.STEP_CHANGE ? 1 : 0;
100+
}
101+
assertThat(tp, greaterThan(80));
102+
}
103+
104+
public void testTrendChangePower() {
105+
NormalDistribution normal = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 0, 2);
106+
int tp = 0;
107+
for (int i = 0; i < 100; i++) {
108+
AtomicInteger j = new AtomicInteger();
109+
double[] bucketValues = DoubleStream.concat(
110+
DoubleStream.generate(() -> j.incrementAndGet() + normal.sample()).limit(20),
111+
DoubleStream.generate(() -> 2.0 * j.incrementAndGet() + normal.sample()).limit(20)
112+
).toArray();
113+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(0.05);
114+
tp += test.type() == ChangeDetector.Type.TREND_CHANGE ? 1 : 0;
115+
}
116+
assertThat(tp, greaterThan(80));
117+
118+
tp = 0;
119+
GammaDistribution gamma = new GammaDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 1, 2);
120+
for (int i = 0; i < 100; i++) {
121+
AtomicInteger j = new AtomicInteger();
122+
double[] bucketValues = DoubleStream.concat(
123+
DoubleStream.generate(() -> j.incrementAndGet() + gamma.sample()).limit(20),
124+
DoubleStream.generate(() -> 2.0 * j.incrementAndGet() + gamma.sample()).limit(20)
125+
).toArray();
126+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(0.05);
127+
tp += test.type() == ChangeDetector.Type.TREND_CHANGE ? 1 : 0;
128+
}
129+
assertThat(tp, greaterThan(80));
130+
}
131+
132+
public void testDistributionChangeTestPower() {
133+
NormalDistribution normal1 = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 0.0, 1.0);
134+
NormalDistribution normal2 = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 0.0, 10.0);
135+
int tp = 0;
136+
for (int i = 0; i < 100; i++) {
137+
double[] bucketValues = DoubleStream.concat(
138+
DoubleStream.generate(() -> 10 + normal1.sample()).limit(50),
139+
DoubleStream.generate(() -> 10 + normal2.sample()).limit(50)
140+
).toArray();
141+
ChangeDetector.TestStats test = new ChangeDetector(bucketValues).testForChange(0.05);
142+
tp += test.type() == ChangeDetector.Type.DISTRIBUTION_CHANGE ? 1 : 0;
143+
}
144+
assertThat(tp, greaterThan(90));
145+
}
146+
147+
public void testMultipleChanges() {
148+
NormalDistribution normal1 = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 78.0, 3.0);
149+
NormalDistribution normal2 = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 40.0, 6.0);
150+
NormalDistribution normal3 = new NormalDistribution(RandomGeneratorFactory.createRandomGenerator(Randomness.get()), 1.0, 0.3);
151+
int tp = 0;
152+
for (int i = 0; i < 100; i++) {
153+
double[] bucketValues = DoubleStream.concat(
154+
DoubleStream.concat(DoubleStream.generate(normal1::sample).limit(7), DoubleStream.generate(normal2::sample).limit(6)),
155+
DoubleStream.generate(normal3::sample).limit(23)
156+
).toArray();
157+
ChangeDetector.TestStats result = new ChangeDetector(bucketValues).testForChange(0.05);
158+
tp += result.type() == ChangeDetector.Type.TREND_CHANGE ? 1 : 0;
159+
}
160+
assertThat(tp, greaterThan(90));
161+
}
162+
163+
public void testProblemDistributionChange() {
164+
double[] bucketValues = new double[] {
165+
546.3651753325270,
166+
550.872738079514,
167+
551.1312487618040,
168+
550.3323904749380,
169+
549.2652495378930,
170+
548.9761274963630,
171+
549.3433969743010,
172+
549.0935313531350,
173+
551.1762550747600,
174+
551.3772184469220,
175+
548.6163495094490,
176+
548.5866591594080,
177+
546.9364791288570,
178+
548.1167839989470,
179+
549.3484016149320,
180+
550.4242803917040,
181+
551.2316023050940,
182+
548.4713993534340,
183+
546.0254901960780,
184+
548.4376996805110,
185+
561.1920529801320,
186+
557.3930041152260,
187+
565.8497217068650,
188+
566.787072243346,
189+
546.6094890510950,
190+
530.5905797101450,
191+
556.7340823970040,
192+
557.3857677902620,
193+
543.0754716981130,
194+
574.3297101449280,
195+
559.2962962962960,
196+
549.5202952029520,
197+
531.7217741935480,
198+
551.4333333333330,
199+
557.637168141593,
200+
545.1880733944950,
201+
564.6893203883500,
202+
543.0204081632650,
203+
571.820809248555,
204+
541.2589928057550,
205+
520.4387755102040 };
206+
ChangeDetector.TestStats result = new ChangeDetector(bucketValues).testForChange(0.05);
207+
assertThat(result.type(), equalTo(ChangeDetector.Type.DISTRIBUTION_CHANGE));
208+
}
209+
}

0 commit comments

Comments
 (0)