-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmidas.go
97 lines (86 loc) · 2.25 KB
/
midas.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package midas
import (
"math"
)
func max(a float64, b float64) float64 {
if a > b {
return a
}
return b
}
func biggest(values []int) int {
b := values[0]
for _, v := range values {
if b < v {
b = v
}
}
return b
}
type MidasModel struct {
curCount *EdgeHash
totalCount *EdgeHash
curT int
}
// Creates a new Midas struct that will enable the use of
// Fit and FitPredict API.
func NewMidasModel(numRows int, numBuckets int, m int) *MidasModel {
return &MidasModel{
totalCount: NewEdgeHash(numRows, numBuckets, m),
curCount: NewEdgeHash(numRows, numBuckets, m),
curT: 1,
}
}
// Fit the source, destination and time to the MidasModel struct
// similar to the sklearn api
func (m *MidasModel) Fit(src, dst, time int){
if time > m.curT {
m.curCount.Clear()
m.curT = time
}
m.curCount.Insert(src, dst, 1)
m.totalCount.Insert(src, dst, 1)
}
// Fit the source, destination and time to the MidasModel struct and
// calculate the anomaly score
func (m *MidasModel) FitPredict(src, dst, time int) float64{
m.Fit(src, dst, time)
curMean := m.totalCount.GetCount(src, dst) / float64(m.curT)
sqerr := math.Pow(m.curCount.GetCount(src, dst)-curMean, 2)
var curScore float64
if m.curT == 1 {
curScore = 0
} else {
curScore = sqerr/curMean + sqerr/(curMean*(float64(m.curT)-1))
}
return curScore
}
// Takes in a list of source, destination and times to do anomaly score of each edge
// This function mirrors the implementation of https://github.com/bhatiasiddharth/MIDAS
func Midas(src []int, dst []int, times []int, numRows int, numBuckets int) []float64 {
m := biggest(src)
curCount := NewEdgeHash(numRows, numBuckets, m)
totalCount := NewEdgeHash(numRows, numBuckets, m)
anomScore := make([]float64, len(src))
curT := 1
for i, _ := range src {
if i == 0 || times[i] > curT {
curCount.Clear()
curT = times[i]
}
curSrc := src[i]
curDst := dst[i]
curCount.Insert(curSrc, curDst, 1)
totalCount.Insert(curSrc, curDst, 1)
curMean := totalCount.GetCount(curSrc, curDst) / float64(curT)
sqerr := math.Pow(curCount.GetCount(curSrc, curDst)-curMean, 2)
var curScore float64
if curT == 1 {
curScore = 0
} else {
curScore = sqerr/curMean + sqerr/(curMean*(float64(curT)-1))
}
anomScore[i] = curScore
}
return anomScore
}