Added missing files.

This commit is contained in:
Neil Lawrence 2013-09-24 06:15:09 +02:00
parent c800e0687f
commit 0509b6f9d0
6 changed files with 297 additions and 160 deletions

View file

@ -39,11 +39,12 @@ class Eq_ode1(Kernpart):
self.name = 'eq_ode1'
self.output_dim = output_dim
self.lengthscale = lengthscale
self.num_params = self.output_dim*(1. + self.rank) + 1
self.num_params = self.output_dim*self.rank + 1 + (self.output_dim - 1)
if kappa is not None:
self.num_params+=self.output_dim
if delay is not None:
self.num_params+=self.output_dim
assert delay.shape==(self.output_dim-1,)
self.num_params+=self.output_dim-1
self.rank = rank
if W is None:
self.W = 0.5*np.random.randn(self.output_dim,self.rank)/np.sqrt(self.rank)
@ -51,18 +52,17 @@ class Eq_ode1(Kernpart):
assert W.shape==(self.output_dim,self.rank)
self.W = W
if decay is None:
self.decay = np.ones(self.output_dim)
self.decay = np.ones(self.output_dim-1)
if kappa is not None:
assert kappa.shape==(self.output_dim,)
self.kappa = kappa
if delay is not None:
assert delay.shape==(self.output_dim,)
self.delay = delay
self.is_normalized = True
self.is_stationary = False
self.gaussian_initial = False
self._set_params(self._get_params())
def _get_params(self):
param_list = [self.W.flatten()]
if self.kappa is not None:
@ -84,11 +84,11 @@ class Eq_ode1(Kernpart):
self.kappa = x[start:end]
self.B += np.diag(self.kappa)
start=end
end+=self.output_dim
end+=self.output_dim-1
self.decay = x[start:end]
start=end
if self.delay is not None:
end+=self.output_dim
end+=self.output_dim-1
self.delay = x[start:end]
start=end
end+=1
@ -100,9 +100,9 @@ class Eq_ode1(Kernpart):
param_names = sum([['W%i_%i'%(i,j) for j in range(self.rank)] for i in range(self.output_dim)],[])
if self.kappa is not None:
param_names += ['kappa_%i'%i for i in range(self.output_dim)]
param_names += ['decay_%i'%i for i in range(self.output_dim)]
param_names += ['decay_%i'%i for i in range(1,self.output_dim)]
if self.delay is not None:
param_names += ['delay_%i'%i for i in range(self.output_dim)]
param_names += ['delay_%i'%i for i in 1+range(1,self.output_dim)]
param_names+= ['lengthscale']
return param_names
@ -112,7 +112,7 @@ class Eq_ode1(Kernpart):
raise ValueError('Input matrix for ode1 covariance should have at most two columns, one containing times, the other output indices')
self._K_computations(X, X2)
target += self._scales*self._dK_dvar
target += self._scale*self._K_dvar
if self.gaussian_initial:
# Add covariance associated with initial condition.
@ -140,9 +140,8 @@ class Eq_ode1(Kernpart):
# TODO: some fast checking here to see if this needs recomputing?
self._t = X[:, 0]
if X.shape[1]==1:
# No index passed, assume single output of ode model.
self._index = np.ones_like(X[:, 1],dtype=np.int)
if not X.shape[1] == 2:
raise ValueError('Input matrix for ode1 covariance should have two columns, one containing times, the other output indices')
self._index = np.asarray(X[:, 1],dtype=np.int)
# Sort indices so that outputs are in blocks for computational
# convenience.
@ -156,15 +155,12 @@ class Eq_ode1(Kernpart):
self._index2 = None
self._rorder2 = self._rorder
else:
if X2.shape[1] > 2:
raise ValueError('Input matrix for ode1 covariance should have at most two columns, one containing times, the other output indices')
if not X2.shape[1] == 2:
raise ValueError('Input matrix for ode1 covariance should have two columns, one containing times, the other output indices')
self._t2 = X2[:, 0]
if X.shape[1]==1:
# No index passed, assume single output of ode model.
self._index2 = np.ones_like(X2[:, 1],dtype=np.int)
self._index2 = np.asarray(X2[:, 1],dtype=np.int)
self._order2 = self._index2.argsort()
slef._index2 = self._index2[self._order2]
self._index2 = self._index2[self._order2]
self._t2 = self._t2[self._order2]
self._rorder2 = self._order2.argsort() # rorder2 is for reversing order
@ -180,25 +176,65 @@ class Eq_ode1(Kernpart):
else:
self._K_compute_ode_eq(transpose=True)
self._K_compute_ode()
if X2 is None:
self._K_dvar = np.zeros((self._t.shape[0], self._t.shape[0]))
else:
self._K_dvar = np.zeros((self._t.shape[0], self._t2.shape[0]))
# Reorder values of blocks for placing back into _K_dvar.
self._K_dvar[self._rorder, :] = np.vstack((np.hstack((self._K_eq, self._Keq_ode)),
np.hstack((self._K_ode_eq, self.K_ode))))[:, self._rorder2]
self._K_dvar = np.vstack((np.hstack((self._K_eq, self._K_eq_ode)),
np.hstack((self._K_ode_eq, self._K_ode))))
self._K_dvar = self._K_dvar[self._rorder, :]
self._K_dvar = self._K_dvar[:, self._rorder2]
if X2 is None:
# Matrix giving scales of each output
self._scale = np.zeros((self._t.size, self._t.size))
code="""
for(int i=0;i<N; i++){
scale_mat[i+i*N] = B[index[i]+output_dim*(index[i])];
for(int j=0; j<i; j++){
scale_mat[j+i*N] = B[index[i]+output_dim*index[j]];
scale_mat[i+j*N] = scale_mat[j+i*N];
}
}
"""
scale_mat, B, index = self._scale, self.B, self._index
N, output_dim = self._t.size, self.output_dim
weave.inline(code,['index',
'scale_mat', 'B',
'N', 'output_dim'])
else:
self._scale = np.zeros((self._t.size, self._t2.size))
code = """
for(int i=0; i<N; i++){
for(int j=0; j<N2; j++){
scale_mat[i+j*N] = B[index[i]+output_dim*index2[j]];
}
}
"""
scale_mat, B, index, index2 = self._scale, self.B, self._index, self._index2
N, N2, output_dim = self._t.size, self._t2.size, self.output_dim
weave.inline(code, ['index', 'index2',
'scale_mat', 'B',
'N', 'N2', 'output_dim'])
def _K_compute_eq(self):
"""Compute covariance for latent covariance."""
t_eq = self._t[self._index==0]
if t_eq.shape[0]==0:
self._K_eq = np.zeros((0, 0))
return
if self._t2 is None:
if t_eq.size==0:
self._K_eq = np.zeros((0, 0))
return
self._dist2 = np.square(t_eq[:, None] - t_eq[None, :])
else:
t2_eq = self._t2[self._index2==0]
if t2_eq.shape[0]==0:
self._K_eq_eq = np.zeros((0, 0))
if t_eq.size==0 or t2_eq.size==0:
self._K_eq = np.zeros((t_eq.size, t2_eq.size))
return
self._dist2 = np.square(t_eq[:, None] - t2_eq[None, :])
@ -212,63 +248,27 @@ class Eq_ode1(Kernpart):
:param transpose: if set to false the exponentiated quadratic is on the rows of the matrix and is computed according to self._t, if set to true it is on the columns and is computed according to self._t2 (default=False).
:type transpose: bool"""
if transpose:
if self._t2 is not None:
if self._t2 is not None:
if transpose:
t_eq = self._t[self._index==0]
t_ode = self._t2[self._index2>0]
index_ode = self._index2[self._index2>0]-1
if t_ode.shape[0]==0:
self._K_eq_ode = np.zeros((0, 0))
return
else:
self._K_eq_ode = np.zeros((0, 0))
return
t_eq = self._t[self._index==0]
if t_eq.shape[0]==0:
self._K_eq_ode = np.zeros((0, 0))
return
t_eq = self._t2[self._index2==0]
t_ode = self._t[self._index>0]
index_ode = self._index[self._index>0]-1
else:
t_eq = self._t[self._index==0]
t_ode = self._t[self._index>0]
index_ode = self._index[self._index>0]-1
if t_ode.shape[0]==0:
self._K_ode_eq = np.zeros((0, 0))
return
if self._t2 is not None:
t_eq = self._t2[self._index2==0]
if t_eq.shape[0]==0:
self._K_ode_eq = np.zeros((0, 0))
return
if t_ode.size==0 or t_eq.size==0:
if transpose:
self._K_eq_ode = np.zeros((t_eq.shape[0], t_ode.shape[0]))
else:
self._K_ode_eq = np.zeros((0, 0))
return
# Matrix giving scales of each output
# self._scale = np.zeros((t_ode.shape[0], t_eq.shape[0]))
# code="""
# for(int i=0;i<N; i++){
# for(int j=0; j<N2; j++){
# scale_mat[i+j*N] = W[index_ode[i]+index_eq[j]*output_dim];
# }
# }
# """
# scale_mat, B = self._scale, self._B
# N, N2, output_dim = index_ode.size, index_eq.size, self.output_dim
# weave.inline(code,['index_ode', 'index_eq',
# 'scale_mat', 'B',
# 'N', 'N2', 'output_dim'])
# else:
# self._scale = np.zeros((t_ode.shape[0], t2_ode.shape[0]))
# code = """
# for(int i=0; i<N; i++){
# for(int j=0; j<N2; j++){
# scale_mat[i+j*N] = B[index_ode[i]+output_dim*index2_ode[j]]
# }
# }
# """
# scale_mat, B = self._scale, self._B
# N, N2, output_dim = index_ode.size, index2.size, self.output_dim
# weave.inline(code, ['index_ode', 'index2_ode',
# 'scale_mat', 'B',
# 'N', 'N2', 'output_dim'])
self._K_ode_eq = np.zeros((t_ode.shape[0], t_eq.shape[0]))
return
t_ode_mat = t_ode[:, None]
t_eq_mat = t_eq[None, :]
if self.delay is not None:
@ -276,13 +276,14 @@ class Eq_ode1(Kernpart):
diff_t = (t_ode_mat - t_eq_mat)
inv_sigma_diff_t = 1./self.sigma*diff_t
half_sigma_d_i = 0.5*self.sigma*self.decay
decay_vals = self.decay[index_ode][:, None]
half_sigma_d_i = 0.5*self.sigma*decay_vals
if self.is_stationary == False:
ln_part, signs = ln_diff_erfs(half_sigma_d_i + t_eq_mat/sigma, half_sigma_d_i - inv_sigma_diff_t, return_sign=True)
ln_part, signs = ln_diff_erfs(half_sigma_d_i + t_eq_mat/self.sigma, half_sigma_d_i - inv_sigma_diff_t, return_sign=True)
else:
ln_part, signs = ln_diff_erfs(inf, half_sigma_d_i - inv_sigma_diff_t, return_sign=True)
sK = signs*exp(half_sigma_d_i*half_sigma_d_i - self.decay*diff_t + ln_part)
sK = signs*np.exp(half_sigma_d_i*half_sigma_d_i - decay_vals*diff_t + ln_part)
sK *= 0.5
@ -294,58 +295,24 @@ class Eq_ode1(Kernpart):
self._K_eq_ode = sK.T
else:
self._K_ode_eq = sK
return K
def _K_compute_ode(self):
# Compute covariances between outputs of the ODE models.
t_ode = self._t[self._index>0]
index_ode = self._index[self._index>0]-1
if t_ode.shape[0]==0:
self._K_ode = np.zeros((0, 0))
return
if self._t2 is None:
if t_ode.size==0:
self._K_ode = np.zeros((0, 0))
return
t2_ode = t_ode
index2_ode = index_ode
else:
t2_ode = self._t2[self._index2>0]
index2_ode = self._index2[self._index2>0]-1
if t2_eq.shape[0]==0:
self._K_ode = np.zeros((0, 0))
if t_ode.size==0 or t2_ode.size==0:
self._K_ode = np.zeros((t_ode.size, t2_ode.size))
return
if self._index2 is None:
# Matrix giving scales of each output
self._scale = np.zeros((t_ode.shape[0], t_ode.shape[0]))
code="""
for(int i=0;i<N; i++){
scale_mat[i+i*N] = B[index_ode[i]+output_dim*(index_ode[i])];
for(int j=0; j<i; j++){
scale_mat[j+i*N] = B[index_ode[i]+output_dim*index_ode[j]];
scale_mat[i+j*N] = scale_mat[j+i*N];
}
}
"""
scale_mat, B = self._scale, self.B
N, output_dim = index_ode.size, self.output_dim
weave.inline(code,['index_ode',
'scale_mat', 'B',
'N', 'output_dim'])
else:
self._scale = np.zeros((t_ode.shape[0], t2_ode.shape[0]))
code = """
for(int i=0; i<N; i++){
for(int j=0; j<N2; j++){
scale_mat[i+j*N] = B[index_ode[i]+output_dim*index2_ode[j]]
}
}
"""
scale_mat, B = self._scale, self.B
N, N2, output_dim = index_ode.size, index2.size, self.output_dim
weave.inline(code, ['index_ode', 'index2_ode',
'scale_mat', 'B',
'N', 'N2', 'output_dim'])
index2_ode = self._index2[self._index2>0]-1
# When index is identical
if self.is_stationary:
@ -360,10 +327,10 @@ class Eq_ode1(Kernpart):
h2 = self._compute_H_stat(t2_ode, index2_ode, t_ode, index_ode)
else:
h2 = self._compute_H(t2_ode, index2_ode, t_ode, index_ode)
self._K_ode += 0.5 * (h + h2.T)
self._K_ode = 0.5 * (h + h2.T)
if not self.is_normalized:
self._K_ode *= np.sqrt(np.pi)*sigma
self._K_ode *= np.sqrt(np.pi)*self.sigma
def _compute_H(self, t, index, t2, index2, update_derivatives=False):
"""Helper function for computing part of the ode1 covariance function.
@ -441,7 +408,7 @@ class Eq_ode1(Kernpart):
-Decay[:, None]*t_mat-Decay2[None, :]*t2_mat+ln_part_2
-np.log(Decay[:, None] + Decay2[None, :]))
return h
# if update_derivatives:
# sigma2 = self.sigma*self.sigma
# # Update ith decay gradient