I made a EM Algorithm for Gaussian Mixture Models, but that is not working.
error massages → matrix is not Hermitian; Cholesky factorization failed.
why error happen, please teach me.
using LinearAlgebra
using Distributions
struct GMMsResults
post_prob
mean
sigma
mixing_coef
end
function GMMs!( data, num_class ;seed=1, max_iter=100 )
num_data, dims = size( data )
rng = MersenneTwister( seed )
# 初期化
post_prob = fill( 1/num_class, num_data, num_class )
mean = rand( rng, dims, num_class )
sigma = [ Matrix{Float64}( I, dims, dims ) for _ in 1:num_class ] # 配列にΣがクラス数分入っている
mixing_coef = fill( 1/num_class, num_class )
for _ in 1:max_iter
update_post_prob!( data, num_class, post_prob, mean, sigma, mixing_coef )
sum_class_assignment = sum( post_prob', dims=2 )
update_mean!( data, num_class, post_prob, mean, sum_class_assignment )
update_sigma!( data, num_class, post_prob, mean, sigma, sum_class_assignment )
update_mixing_coef!( data, num_class, mixing_coef, sum_class_assignment )
end
return GMMsResults( post_prob, mean, sigma, mixing_coef )
end
function update_post_prob!( data, num_class, post_prob, mean, sigma, mixing_coef )
num_data = size( data )[1]
for n in 1:num_data
sum_tmp = 0
for k in 1:num_class
sum_tmp += mixing_coef[k] * pdf( MvNormal( mean[:,k], sigma[k] ), data[n,:] )
end
for k in 1:num_class
post_prob[n,k] = ( mixing_coef[k] * pdf( MvNormal( mean[:,k], sigma[k] ), data[n,:] ) ) / sum_tmp
end
end
end
function update_mean!( data, num_class, post_prob, mean, sum_class_assignment )
num_data = size( data )[1]
for k in 1:num_class
sum_tmp = zeros( num_class )
for n in 1:num_data
sum_tmp += post_prob[n,k] .* data[n,:]
end
mean[:,k] = sum_tmp ./ sum_class_assignment[k]
end
end
function update_sigma!( data, num_class, post_prob, mean, sigma, sum_class_assignment )
num_data, dims = size( data )
for k in 1:num_class
sum_tmp = zeros( dims, dims )
for n in 1:num_data
sum_tmp += post_prob[n,k] .* ( data[n,:] - mean[:, k] ) * ( data[n,:] - mean[:, k] )'
end
sigma[k] = sum_tmp ./ sum_class_assignment[k]
end
end
function update_mixing_coef!( data, num_class, mixing_coef, sum_class_assignment )
num_data = size( data )[1]
for k in 1:num_class
mixing_coef[k] = sum_class_assignment[k] / num_data
end
end