-
Notifications
You must be signed in to change notification settings - Fork 0
/
t_fit.py
85 lines (74 loc) · 3.01 KB
/
t_fit.py
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
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 28 23:37:40 2020
@author: adars
"""
import numpy as np
from scipy.special import psi, gammaln
import fit_t_cost as ftc
def fit_t(x, precision):
print('Performing fit_t...')
# x = np.random.multivariate_normal(da);
(I,D) = np.shape(x)
# Initialize the Mean
#dataset_mean = np.divide(np.sum(x,axis = 0),I)
dataset_mean = x.mean(axis=0)
mu = np.reshape(dataset_mean,(1,-1))
#Initialize sig to the covariance of the dataset.
dataset_variance = np.zeros([D, D])
x_minus_dataset_mean = np.subtract(x, dataset_mean)
for i in range(I):
mat = np.reshape(x_minus_dataset_mean[i,:],(1,-1))
mat = np.dot(np.transpose(mat),mat)
dataset_variance = dataset_variance + mat;
sig = np.divide(dataset_variance,I);
##Initialize degrees of freedom to 1000 (just a random large value).
nu = 1
##The main loop.
iterations = 0
previous_L = 1000000 # just a random initialization
delta = np.zeros([I,1])
#delta1 = np.zeros([I,1])
while True:
#Expectation step.
#Compute delta.
x_minus_mu = np.subtract(x, mu)
temp = np.dot(x_minus_mu,np.linalg.inv(sig))
for i in range(I):
delta[i] = np.dot(np.reshape(temp[i,:],(1,-1)),np.transpose(np.reshape(x_minus_mu[i,:],(1,-1))))
# Compute E_hi.
nu_plus_delta = nu + delta
E_hi = np.divide((nu + D),nu_plus_delta)
## Compute E_log_hi.
E_log_hi = psi((nu+D)/2) - np.log(nu_plus_delta/2);
## Maximization step.
## Update mu.
E_hi_sum = np.sum(E_hi)
E_hi_times_xi = E_hi * x
mu = np.reshape(np.sum(E_hi_times_xi, axis=0),(1,-1))
mu = np.divide(mu,E_hi_sum)
## Update sig.
x_minus_mu = np.subtract(x, mu)
sig = np.zeros([D,D])
for i in range(I):
xmm = np.reshape(x_minus_mu[i,:],(1,-1))
sig = sig + (E_hi[i] * np.dot(np.transpose(xmm),xmm))
sig = sig / E_hi_sum
#Update nu by minimizing a cost function with line search.
nu = ftc.fit_t_cost(E_hi,E_log_hi)
## Compute delta again, because the parameters were updated.
temp = np.dot(x_minus_mu,np.linalg.inv(sig))
# temp1 = np.linalg.inv(sig)
for i in range(I):
delta[i] = np.dot(np.reshape(temp[i,:],(1,-1)),np.transpose(np.reshape(x_minus_mu[i,:],(1,-1))))
## Compute the log likelihood L.
(sign, logdet) = np.linalg.slogdet(np.array(sig))
L = I * (gammaln((nu+D)/2) - (D/2)*np.log(nu*np.pi) - logdet/2 - gammaln(nu/2))
s = np.sum(np.log(1 + np.divide(delta,nu))) / 2
L = L - (nu+D)*s;
iterations = iterations + 1;
print(str(iterations)+' : '+str(L))
if (np.absolute(L - previous_L) < precision) or iterations == 100:
break
previous_L = L;
return(mu,sig,nu)