1
1
package ai .chronon .online .stats
2
-
3
- import ai .chronon .api .ColorPrinter .ColorString
4
2
import ai .chronon .api .Window
5
3
6
4
import scala .math ._
7
5
8
-
9
6
object DistanceMetrics {
10
7
11
8
// TODO move this to unit test
@@ -22,19 +19,18 @@ object DistanceMetrics {
22
19
val hd = hellingerDistance(A , B )
23
20
println(f " The Hellinger Distance between distributions A and B is: $hd%.5f " )
24
21
25
-
26
22
// format: off
27
23
// aligned vertically for easier reasoning
28
24
val ptiles = Array ( 1 , 4 , 6 ,6 ,6 , 8 , 9 )
29
25
val breaks = Array (0 , 1 , 2 , 3 , 5 , 6 , 7 , 8 , 9 , 10 )
30
26
// format: on
31
27
32
28
// val interval = 0.25
33
- val expected = Array (0.0 , 1.0 / 3.0 , 1.0 / 3.0 , (1.0 )/ (3.0 ) + (1.0 )/ (2.0 ), (1.0 )/ (2.0 ), 2.5 , 0.5 , 1 , 0 )
29
+ val expected = Array (0.0 , 1.0 / 3.0 , 1.0 / 3.0 , (1.0 ) / (3.0 ) + (1.0 ) / (2.0 ), (1.0 ) / (2.0 ), 2.5 , 0.5 , 1 , 0 )
34
30
35
31
val result = AssignIntervals .on(ptiles = ptiles.map(_.toDouble), breaks = breaks.map(_.toDouble))
36
32
37
- expected.zip(result).foreach{ case (e, r) => println(s " exp: $e res: $r" )}
33
+ expected.zip(result).foreach { case (e, r) => println(s " exp: $e res: $r" ) }
38
34
39
35
}
40
36
@@ -43,15 +39,13 @@ object DistanceMetrics {
43
39
44
40
case class Comparison [T ](previous : T , current : T , timeDelta : Window )
45
41
46
-
47
- def functionBuilder [T ](binningFunc : Comparison [T ] => Distributions , distanceFunc : Distributions => Double ): Comparison [T ] => Double = {
48
- c =>
49
- val dists = binningFunc(c)
50
- val distance = distanceFunc(dists)
51
- distance
42
+ def functionBuilder [T ](binningFunc : Comparison [T ] => Distributions ,
43
+ distanceFunc : Distributions => Double ): Comparison [T ] => Double = { c =>
44
+ val dists = binningFunc(c)
45
+ val distance = distanceFunc(dists)
46
+ distance
52
47
}
53
48
54
-
55
49
def hellingerDistance (p : Array [Double ], q : Array [Double ]): Double = {
56
50
val (pProbs, qProbs) = computePDFs(p, q)
57
51
@@ -110,14 +104,14 @@ object DistanceMetrics {
110
104
val interval : Double = 1 .toDouble / (n - 1.0 )
111
105
112
106
def mass (i : Int , eh : Int ): Mass = {
113
- def indexMass (i : Int ): Double = interval / (percentiles(i) - percentiles(i- 1 ))
107
+ def indexMass (i : Int ): Double = interval / (percentiles(i) - percentiles(i - 1 ))
114
108
val isPointMass = eh > 1
115
109
val m = (i, eh) match {
116
- case (0 , _) => 0.0 // before range
117
- case (x, 0 ) if x>= n => 0.0 // after range
118
- case (_, e) if e > 1 => (e - 1 ) * interval // point mass
119
- case (x, 1 ) if x== n => indexMass(n- 1 ) // exactly at end of range
120
- case (x, _) => indexMass(x) // somewhere in between
110
+ case (0 , _) => 0.0 // before range
111
+ case (x, 0 ) if x >= n => 0.0 // after range
112
+ case (_, e) if e > 1 => (e - 1 ) * interval // point mass
113
+ case (x, 1 ) if x == n => indexMass(n - 1 ) // exactly at end of range
114
+ case (x, _) => indexMass(x) // somewhere in between
121
115
}
122
116
Mass (m, isPointMass)
123
117
}
@@ -137,8 +131,8 @@ object DistanceMetrics {
137
131
require(p.length == q.length, s " Inputs are of different length ${p.length}, ${q.length}" )
138
132
var i = 0
139
133
var result = 0.0
140
- while (i < p.length) {
141
- val inc = if (p(i)> 0 && q(i) > 0 ) p(i) * math.log(p(i) / q(i)) else 0
134
+ while (i < p.length) {
135
+ val inc = if (p(i) > 0 && q(i) > 0 ) p(i) * math.log(p(i) / q(i)) else 0
142
136
result += inc
143
137
i += 1
144
138
}
0 commit comments