-
Notifications
You must be signed in to change notification settings - Fork 0
/
sdem.go
108 lines (92 loc) · 2.69 KB
/
sdem.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
98
99
100
101
102
103
104
105
106
107
108
package smartsifter
import (
"math/rand"
"time"
"gonum.org/v1/gonum/mat"
)
type SDEM struct {
r float64
alpha float64
dim int
mixtureNum int
mixtureRates []float64
averages []*mat.VecDense
averages_ []*mat.VecDense
matrices []*mat.Dense
matrices_ []*mat.Dense
gmm GMM
}
func newSDEM(discount, alpha float64, mixtureNum, dim int) *SDEM {
sdem := &SDEM{
r: discount,
alpha: alpha,
mixtureNum: mixtureNum,
dim: dim,
gmm: GMM{},
}
sdem.initialize()
return sdem
}
func (sdem *SDEM) initialize() {
rand.Seed(time.Now().UnixNano())
sdem.mixtureRates = make([]float64, sdem.mixtureNum)
sdem.averages = make([]*mat.VecDense, sdem.mixtureNum)
sdem.averages_ = make([]*mat.VecDense, sdem.mixtureNum)
sdem.matrices = make([]*mat.Dense, sdem.mixtureNum)
sdem.matrices_ = make([]*mat.Dense, sdem.mixtureNum)
for i := 0; i < sdem.mixtureNum; i++ {
sdem.mixtureRates[i] = 1.0 / float64(sdem.mixtureNum)
sdem.averages[i] = uniformVector(sdem.dim)
var average_ mat.VecDense
average_.ScaleVec(sdem.mixtureRates[i], sdem.averages[i])
sdem.averages_[i] = &average_
sdem.matrices[i] = identifyMatrix(sdem.dim)
var matrix_ mat.Dense
matrix_.Outer(1.0, sdem.averages[i], sdem.averages[i])
matrix_.Add(&matrix_, sdem.matrices[i])
matrix_.Scale(sdem.mixtureRates[i], &matrix_)
sdem.matrices_[i] = &matrix_
}
}
func (sdem *SDEM) input(x []float64, update bool) float64 {
p, ps := sdem.gmm.probabilityDensity(x, sdem.mixtureRates, sdem.averages, sdem.matrices)
if update {
sdem.update(x, p, ps)
}
return p
}
func (sdem *SDEM) update(x []float64, p float64, ps []float64) {
for k := 0; k < sdem.mixtureNum; k++ {
// gamma
gamma := (1.0-sdem.alpha*sdem.r)*(ps[k]/p) + (sdem.alpha*sdem.r)/float64(sdem.mixtureNum)
// mixtureRate
mixtureRate := (1.0-sdem.r)*sdem.mixtureRates[k] + sdem.r*gamma
// mu_
var mu_ mat.VecDense
mu_.ScaleVec(1.0-sdem.r, sdem.averages_[k])
var mu_2 mat.VecDense
mu_2.ScaleVec(sdem.r*gamma, mat.NewVecDense(len(x), x))
mu_.AddVec(&mu_, &mu_2)
// mu
var mu mat.VecDense
mu.ScaleVec(1.0/mixtureRate, &mu_)
// lambda_
var lambda_ mat.Dense
lambda_.Scale(1.0-sdem.r, sdem.matrices_[k])
var lambda_2 mat.Dense
lambda_2.Outer(sdem.r*gamma, mat.NewVecDense(len(x), x), mat.NewVecDense(len(x), x))
lambda_.Add(&lambda_, &lambda_2)
// lambda
var lambda mat.Dense
lambda.Scale(1.0/mixtureRate, &lambda_)
var lambda2 mat.Dense
lambda2.Outer(-1.0, &mu, &mu)
lambda.Add(&lambda, &lambda2)
// Update parameters
sdem.mixtureRates[k] = mixtureRate
sdem.averages_[k] = &mu_
sdem.averages[k] = &mu
sdem.matrices_[k] = &lambda_
sdem.matrices[k] = &lambda
}
}