forked from memoiry/LightML.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gaussianMixtureModel.jl
141 lines (114 loc) · 3.5 KB
/
gaussianMixtureModel.jl
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
type GaussianMixture
K::Integer
max_iters::Integer
method::String
tolerance::Float64
weights::Vector
means::Matrix
cov_::Dict{Integer,Matrix}
responsibilities::Matrix
likelihood::Vector
end
function GaussianMixture(;
K::Integer = 4,
max_iters::Integer = 500,
tolerance::Float64 = 1e-3,
method::String = "random",
weights::Vector = zeros(4),
means::Matrix = zeros(4,4),
cov_::Dict{Integer,Matrix} = Dict{Integer,Matrix}(),
likelihood::Vector = zeros(4),
responsibilities::Matrix = zeros(4,4))
return GaussianMixture(K, max_iters, method,
tolerance, weights, means, cov_, responsibilities, likelihood)
end
function train!(model::GaussianMixture, X::Matrix)
n_sample = size(X,1)
initialize_(model, X)
for i = 1:model.max_iters
E_step!(model,X)
M_step!(model,X)
if isconverge_(model)
break
end
end
end
function initialize_(model, X)
model.weights = ones(model.K) * (1/model.K)
model.means = X[randperm(size(X,1))[1:model.K],:]'
rand_cov = cov(X)
for i = 1:model.K
model.cov_[i] = rand_cov
end
model.likelihood = Vector{Real}()
end
function E_step!(model, X)
likelihood = zeros(size(X,1),model.K)
for i = 1:model.K
model.cov_[i] = Symmetric(model.cov_[i],:L)
dis = MvNormal(model.means[:,i], model.cov_[i])
likeli = pdf(dis, X')
likelihood[:, i] = likeli
end
weighted_likelihood = repmat(model.weights',size(X,1),1) .* likelihood
temp1 = sum(log(sum(weighted_likelihood,2)))
push!(model.likelihood, temp1)
for i = 1:size(weighted_likelihood, 1)
weighted_likelihood[i,:] = weighted_likelihood[i,:] / sum(weighted_likelihood[i,:])
end
model.responsibilities = weighted_likelihood
end
function M_step!(model, X)
n_sample = size(X,1)
n_feature = size(X,2)
for i = 1:model.K
resp = model.responsibilities[:,i]
resp = resp'
model.weights[i] = sum(resp)/n_sample
for j = 1:n_feature
temp = resp * X[:,j]/sum(resp)
model.means[j, i] = temp[1]
end
cov_ = 0
for j = 1:n_sample
temp = (X[j,:] - model.means[:,i])
cov_ += resp[j] .* temp * temp'
end
model.cov_[i] = cov_ ./ sum(resp)
end
end
function isconverge_(model::GaussianMixture)
if length(model.likelihood) > 1 && model.likelihood[end] - model.likelihood[end-1] <= model.tolerance
return true
end
return false
end
function predict(model::GaussianMixture,
x::Matrix)
n = size(x,1)
res = zeros(n)
for i = 1:n
res[i] = predict(model, x[i,:])
end
return res
end
function predict(model::GaussianMixture,
x::Vector)
likelihood = zeros(model.K)
for i = 1:model.K
model.cov_[i] = Symmetric(model.cov_[i],:L)
dis = MvNormal(model.means[:,i], model.cov_[i])
likeli = pdf(dis, x)
likelihood[i] = likeli
end
weighted_likelihood = model.weights .* likelihood
return indmax(weighted_likelihood)
end
# maybe some problem
function test_GaussianMixture()
X_train, y_test= make_blo()
clu = size(X_train, 2)
model = GaussianMixture(K = clu)
train!(model,X_train)
predictions = predict(model,X_train)
end