Merge branch 'devel' of github.com:SheffieldML/GPy into devel

This commit is contained in:
Teo de Campos 2013-05-22 15:23:08 +01:00
commit 1707d0544f
11 changed files with 210 additions and 92 deletions

View file

@ -131,7 +131,7 @@ def BGPLVM_oil(optimize=True, N=100, Q=5, M=25, max_f_eval=4e3, plot=False, **k)
m = GPy.models.Bayesian_GPLVM(Yn, Q, kernel=kernel, M=M, **k)
m.data_labels = data['Y'][:N].argmax(axis=1)
m.constrain('variance|leng', logexp_clipped())
# m.constrain('variance|leng', logexp_clipped())
m['lengt'] = m.X.var(0).max() / m.X.var(0)
m['noise'] = Yn.var() / 100.
@ -246,7 +246,7 @@ def bgplvm_simulation_matlab_compare():
def bgplvm_simulation(optimize='scg',
plot=True,
max_f_eval=2e4):
from GPy.core.transformations import logexp_clipped
# from GPy.core.transformations import logexp_clipped
D1, D2, D3, N, M, Q = 15, 8, 8, 100, 3, 5
slist, Slist, Ylist = _simulate_sincos(D1, D2, D3, N, M, Q, plot)
@ -259,8 +259,8 @@ def bgplvm_simulation(optimize='scg',
k = kern.linear(Q, ARD=True) + kern.bias(Q, np.exp(-2)) + kern.white(Q, np.exp(-2)) # + kern.bias(Q)
m = Bayesian_GPLVM(Y, Q, init="PCA", M=M, kernel=k, _debug=True)
m.constrain('variance|noise', logexp_clipped())
# m.ensure_default_constraints()
# m.constrain('variance|noise', logexp_clipped())
m.ensure_default_constraints()
m['noise'] = Y.var() / 100.
m['linear_variance'] = .01
@ -273,8 +273,8 @@ def bgplvm_simulation(optimize='scg',
pylab.figure(); pylab.axis(); m.kern.plot_ARD()
return m
def mrd_simulation(optimize=True, plot_sim=False):
D1, D2, D3, N, M, Q = 150, 250, 30, 300, 3, 7
def mrd_simulation(optimize=True, plot_sim=False, **kw):
D1, D2, D3, N, M, Q = 150, 250, 30, 200, 3, 7
slist, Slist, Ylist = _simulate_sincos(D1, D2, D3, N, M, Q, plot_sim)
from GPy.models import mrd
@ -284,12 +284,12 @@ def mrd_simulation(optimize=True, plot_sim=False):
reload(mrd); reload(kern)
k = kern.linear(Q, [0.01] * Q, True) + kern.bias(Q, np.exp(-2)) + kern.white(Q, np.exp(-2))
m = mrd.MRD(*Ylist, Q=Q, M=M, kernel=k, initx="concat", initz='permute')
m = mrd.MRD(*Ylist, Q=Q, M=M, kernel=k, initx="concat", initz='permute', **kw)
for i, Y in enumerate(Ylist):
m['{}_noise'.format(i + 1)] = Y.var() / 100.
m.constrain('variance|noise', logexp_clipped())
# m.constrain('variance|noise', logexp_clipped())
m.ensure_default_constraints()
# DEBUG

View file

@ -39,11 +39,6 @@ def SCG(f, gradf, x, optargs=(), maxiters=500, max_f_eval=500, display=True, xto
function_eval number of fn evaluations
status: string describing convergence status
"""
if display:
print " SCG"
print ' {0:{mi}s} {1:11s} {2:11s} {3:11s}'.format("I", "F", "Scale", "|g|", mi=len(str(maxiters)))
if xtol is None:
xtol = 1e-6
if ftol is None:
@ -69,6 +64,9 @@ def SCG(f, gradf, x, optargs=(), maxiters=500, max_f_eval=500, display=True, xto
iteration = 0
if display:
print ' {0:{mi}s} {1:11s} {2:11s} {3:11s}'.format("I", "F", "Scale", "|g|", mi=len(str(maxiters)))
# Main optimization loop.
while iteration < maxiters:
@ -129,10 +127,10 @@ def SCG(f, gradf, x, optargs=(), maxiters=500, max_f_eval=500, display=True, xto
else:
# Update variables for new position
fold = fnew
gradold = gradnew
gradnew = gradf(x, *optargs)
current_grad = np.dot(gradnew, gradnew)
gradold = gradnew
fold = fnew
# If the gradient is zero then we are done.
if current_grad <= gtol:
status = 'converged'

View file

@ -53,7 +53,7 @@ class Gaussian(likelihood):
def _set_params(self, x):
x = float(x)
if self._variance != x:
self.precision = 1. / x
self.precision = 1. / max(x, 1e-6)
self.covariance_matrix = np.eye(self.N) * x
self.V = (self.precision) * self.Y
self._variance = x

View file

@ -37,6 +37,7 @@ class Bayesian_GPLVM(sparse_GP, GPLVM):
if X == None:
X = self.initialise_latent(init, Q, likelihood.Y)
self.init = init
if X_variance is None:
X_variance = np.clip((np.ones_like(X) * 0.5) + .01 * np.random.randn(*X.shape), 0.001, 1)
@ -200,21 +201,21 @@ class Bayesian_GPLVM(sparse_GP, GPLVM):
assert not self.likelihood.is_heteroscedastic
N_test = Y.shape[0]
Q = self.Z.shape[1]
means = np.zeros((N_test,Q))
covars = np.zeros((N_test,Q))
means = np.zeros((N_test, Q))
covars = np.zeros((N_test, Q))
dpsi0 = - 0.5 * self.D * self.likelihood.precision
dpsi2 = self.dL_dpsi2[0][None,:,:] # TODO: this may change if we ignore het. likelihoods
V = self.likelihood.precision*Y
dpsi1 = np.dot(self.Cpsi1V,V.T)
dpsi0 = -0.5 * self.D * self.likelihood.precision
dpsi2 = self.dL_dpsi2[0][None, :, :] # TODO: this may change if we ignore het. likelihoods
V = self.likelihood.precision * Y
dpsi1 = np.dot(self.Cpsi1V, V.T)
start = np.zeros(self.Q*2)
start = np.zeros(self.Q * 2)
for n,dpsi1_n in enumerate(dpsi1.T[:,:,None]):
args = (self.kern,self.Z,dpsi0,dpsi1_n,dpsi2)
xopt,fopt,neval,status = SCG(f=latent_cost, gradf=latent_grad, x=start, optargs=args, display = False)
for n, dpsi1_n in enumerate(dpsi1.T[:, :, None]):
args = (self.kern, self.Z, dpsi0, dpsi1_n, dpsi2)
xopt, fopt, neval, status = SCG(f=latent_cost, gradf=latent_grad, x=start, optargs=args, display=False)
mu,log_S = xopt.reshape(2,1,-1)
mu, log_S = xopt.reshape(2, 1, -1)
means[n] = mu[0].copy()
covars[n] = np.exp(log_S[0]).copy()
@ -262,6 +263,14 @@ class Bayesian_GPLVM(sparse_GP, GPLVM):
fig.tight_layout(h_pad=.01) # , rect=(0, 0, 1, .95))
return fig
def __getstate__(self):
return (self.likelihood, self.Q, self.X, self.X_variance,
self.init, self.M, self.Z, self.kern,
self.oldpsave, self._debug)
def __setstate__(self, state):
self.__init__(*state)
def _debug_filter_params(self, x):
start, end = 0, self.X.size,
X = x[start:end].reshape(self.N, self.Q)
@ -523,59 +532,59 @@ class Bayesian_GPLVM(sparse_GP, GPLVM):
def latent_cost_and_grad(mu_S, kern,Z, dL_dpsi0, dL_dpsi1, dL_dpsi2):
def latent_cost_and_grad(mu_S, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2):
"""
objective function for fitting the latent variables for test points
(negative log-likelihood: should be minimised!)
"""
mu,log_S = mu_S.reshape(2,1,-1)
mu, log_S = mu_S.reshape(2, 1, -1)
S = np.exp(log_S)
psi0 = kern.psi0(Z,mu,S)
psi1 = kern.psi1(Z,mu,S)
psi2 = kern.psi2(Z,mu,S)
psi0 = kern.psi0(Z, mu, S)
psi1 = kern.psi1(Z, mu, S)
psi2 = kern.psi2(Z, mu, S)
lik = dL_dpsi0*psi0 + np.dot(dL_dpsi1.flatten(),psi1.flatten()) + np.dot(dL_dpsi2.flatten(),psi2.flatten()) - 0.5*np.sum(np.square(mu) + S) + 0.5*np.sum(log_S)
lik = dL_dpsi0 * psi0 + np.dot(dL_dpsi1.flatten(), psi1.flatten()) + np.dot(dL_dpsi2.flatten(), psi2.flatten()) - 0.5 * np.sum(np.square(mu) + S) + 0.5 * np.sum(log_S)
mu0, S0 = kern.dpsi0_dmuS(dL_dpsi0,Z,mu,S)
mu1, S1 = kern.dpsi1_dmuS(dL_dpsi1,Z,mu,S)
mu2, S2 = kern.dpsi2_dmuS(dL_dpsi2,Z,mu,S)
mu0, S0 = kern.dpsi0_dmuS(dL_dpsi0, Z, mu, S)
mu1, S1 = kern.dpsi1_dmuS(dL_dpsi1, Z, mu, S)
mu2, S2 = kern.dpsi2_dmuS(dL_dpsi2, Z, mu, S)
dmu = mu0 + mu1 + mu2 - mu
#dS = S0 + S1 + S2 -0.5 + .5/S
dlnS = S*(S0 + S1 + S2 -0.5) + .5
return -lik,-np.hstack((dmu.flatten(),dlnS.flatten()))
# dS = S0 + S1 + S2 -0.5 + .5/S
dlnS = S * (S0 + S1 + S2 - 0.5) + .5
return -lik, -np.hstack((dmu.flatten(), dlnS.flatten()))
def latent_cost(mu_S, kern,Z, dL_dpsi0, dL_dpsi1, dL_dpsi2):
def latent_cost(mu_S, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2):
"""
objective function for fitting the latent variables (negative log-likelihood: should be minimised!)
This is the same as latent_cost_and_grad but only for the objective
"""
mu,log_S = mu_S.reshape(2,1,-1)
mu, log_S = mu_S.reshape(2, 1, -1)
S = np.exp(log_S)
psi0 = kern.psi0(Z,mu,S)
psi1 = kern.psi1(Z,mu,S)
psi2 = kern.psi2(Z,mu,S)
psi0 = kern.psi0(Z, mu, S)
psi1 = kern.psi1(Z, mu, S)
psi2 = kern.psi2(Z, mu, S)
lik = dL_dpsi0*psi0 + np.dot(dL_dpsi1.flatten(),psi1.flatten()) + np.dot(dL_dpsi2.flatten(),psi2.flatten()) - 0.5*np.sum(np.square(mu) + S) + 0.5*np.sum(log_S)
lik = dL_dpsi0 * psi0 + np.dot(dL_dpsi1.flatten(), psi1.flatten()) + np.dot(dL_dpsi2.flatten(), psi2.flatten()) - 0.5 * np.sum(np.square(mu) + S) + 0.5 * np.sum(log_S)
return -float(lik)
def latent_grad(mu_S, kern,Z, dL_dpsi0, dL_dpsi1, dL_dpsi2):
def latent_grad(mu_S, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2):
"""
This is the same as latent_cost_and_grad but only for the grad
"""
mu,log_S = mu_S.reshape(2,1,-1)
mu, log_S = mu_S.reshape(2, 1, -1)
S = np.exp(log_S)
mu0, S0 = kern.dpsi0_dmuS(dL_dpsi0,Z,mu,S)
mu1, S1 = kern.dpsi1_dmuS(dL_dpsi1,Z,mu,S)
mu2, S2 = kern.dpsi2_dmuS(dL_dpsi2,Z,mu,S)
mu0, S0 = kern.dpsi0_dmuS(dL_dpsi0, Z, mu, S)
mu1, S1 = kern.dpsi1_dmuS(dL_dpsi1, Z, mu, S)
mu2, S2 = kern.dpsi2_dmuS(dL_dpsi2, Z, mu, S)
dmu = mu0 + mu1 + mu2 - mu
#dS = S0 + S1 + S2 -0.5 + .5/S
dlnS = S*(S0 + S1 + S2 -0.5) + .5
# dS = S0 + S1 + S2 -0.5 + .5/S
dlnS = S * (S0 + S1 + S2 - 0.5) + .5
return -np.hstack((dmu.flatten(),dlnS.flatten()))
return -np.hstack((dmu.flatten(), dlnS.flatten()))

View file

@ -60,7 +60,7 @@ class GPLVM(GP):
mu, var, upper, lower = self.predict(Xnew)
pb.plot(mu[:,0], mu[:,1],'k',linewidth=1.5)
def plot_latent(self, labels=None, which_indices=None, resolution=50, ax=None):
def plot_latent(self, labels=None, which_indices=None, resolution=50, ax=None, marker='o', s=40):
"""
:param labels: a np.array of size self.N containing labels for the points (can be number, strings, etc)
:param resolution: the resolution of the grid on which to evaluate the predictive variance
@ -94,13 +94,23 @@ class GPLVM(GP):
ax.imshow(var.reshape(resolution, resolution).T,
extent=[xmin[0], xmax[0], xmin[1], xmax[1]], cmap=pb.cm.binary,interpolation='bilinear',origin='lower')
for i,ul in enumerate(np.unique(labels)):
# make sure labels are in order of input:
ulabels = []
for lab in labels:
if not lab in ulabels:
ulabels.append(lab)
for i, ul in enumerate(ulabels):
if type(ul) is np.string_:
this_label = ul
elif type(ul) is np.int64:
this_label = 'class %i'%ul
else:
this_label = 'class %i'%i
if len(marker) == len(ulabels):
m = marker[i]
else:
m = marker
index = np.nonzero(labels==ul)[0]
if self.Q==1:
@ -109,7 +119,7 @@ class GPLVM(GP):
else:
x = self.X[index,input_1]
y = self.X[index,input_2]
ax.plot(x,y,marker='o',color=util.plot.Tango.nextMedium(),mew=0,label=this_label,linewidth=0)
ax.scatter(x, y, marker=m, s=s, color=util.plot.Tango.nextMedium(), mew=1.3, label=this_label)
ax.set_xlabel('latent dimension %i'%input_1)
ax.set_ylabel('latent dimension %i'%input_2)

View file

@ -41,8 +41,40 @@ class MRD(model):
:param kernel:
kernel to use
"""
#TODO allow different kernels for different outputs
#def __init__(self, *Ylist, **kwargs):
def __init__(self,likelihood_list,Q,M=10,names=None,kernels=None,initX='PCA',initz='permute',_debug=False, **kwargs):
if names is None:
self.names = ["{}".format(i + 1) for i in range(len(likelihood_list))]
#sort out the kernels
if kernels is None:
kernels = [None]*len(likelihood_list)
elif isinstance(kernels,kern.kern):
kernels = [kernels.copy() for i in range(len(likelihood_list))]
else:
assert len(kernels)==len(likelihood_list), "need one kernel per output"
assert all([isinstance(k, kern.kern) for k in kernels]), "invalid kernel object detected!"
self.Q = Q
self.M = M
self.N = self.gref.N
self.NQ = self.N * self.Q
self.MQ = self.M * self.Q
self._init = True
X = self._init_X(initx, likelihood_list)
Z = self._init_Z(initz, X)
self.bgplvms = [Bayesian_GPLVM(l, k, X=X, Z=Z, M=self.M, **kwargs) for l,k in zip(likelihood_list,kernels)]
del self._init
self.gref = self.bgplvms[0]
nparams = numpy.array([0] + [sparse_GP._get_params(g).size - g.Z.size for g in self.bgplvms])
self.nparams = nparams.cumsum()
model.__init__(self) # @UndefinedVariable
def __init__(self, *likelihood_list, **kwargs):
if kwargs.has_key("_debug"):
self._debug = kwargs['_debug']

View file

@ -7,6 +7,6 @@ import unittest
import sys
def deepTest(reason):
if 'deep' in sys.argv:
if reason:
return lambda x:x
return unittest.skip("Not deep scanning, enable deepscan by adding 'deep' argument")

View file

@ -6,10 +6,9 @@ Created on 26 Apr 2013
import unittest
import GPy
import numpy as np
import sys
from .. import testing
from GPy import testing
__test__ = True
__test__ = False
np.random.seed(0)
def ard(p):
@ -20,7 +19,7 @@ def ard(p):
pass
return ""
@testing.deepTest
@testing.deepTest(__test__)
class Test(unittest.TestCase):
D = 9
M = 4
@ -29,13 +28,22 @@ class Test(unittest.TestCase):
def setUp(self):
self.kerns = (
GPy.kern.rbf(self.D), GPy.kern.rbf(self.D, ARD=True),
GPy.kern.linear(self.D, ARD=False), GPy.kern.linear(self.D, ARD=True),
GPy.kern.linear(self.D) + GPy.kern.bias(self.D),
GPy.kern.rbf(self.D) + GPy.kern.bias(self.D),
GPy.kern.linear(self.D) + GPy.kern.bias(self.D) + GPy.kern.white(self.D),
GPy.kern.rbf(self.D) + GPy.kern.bias(self.D) + GPy.kern.white(self.D),
GPy.kern.bias(self.D), GPy.kern.white(self.D),
# (GPy.kern.rbf(self.D, ARD=True) +
# GPy.kern.linear(self.D, ARD=True) +
# GPy.kern.bias(self.D) +
# GPy.kern.white(self.D)),
(GPy.kern.rbf(self.D, np.random.rand(), np.random.rand(self.D), ARD=True) +
GPy.kern.rbf(self.D, np.random.rand(), np.random.rand(self.D), ARD=True) +
GPy.kern.linear(self.D, np.random.rand(self.D), ARD=True) +
GPy.kern.bias(self.D) +
GPy.kern.white(self.D)),
# GPy.kern.rbf(self.D), GPy.kern.rbf(self.D, ARD=True),
# GPy.kern.linear(self.D, ARD=False), GPy.kern.linear(self.D, ARD=True),
# GPy.kern.linear(self.D) + GPy.kern.bias(self.D),
# GPy.kern.rbf(self.D) + GPy.kern.bias(self.D),
# GPy.kern.linear(self.D) + GPy.kern.bias(self.D) + GPy.kern.white(self.D),
# GPy.kern.rbf(self.D) + GPy.kern.bias(self.D) + GPy.kern.white(self.D),
# GPy.kern.bias(self.D), GPy.kern.white(self.D),
)
self.q_x_mean = np.random.randn(self.D)
self.q_x_variance = np.exp(np.random.randn(self.D))
@ -64,8 +72,9 @@ class Test(unittest.TestCase):
K_ /= self.Nsamples / Nsamples
msg = "psi1: " + "+".join([p.name + ard(p) for p in kern.parts])
try:
# pylab.figure(msg)
# pylab.plot(diffs)
import pylab
pylab.figure(msg)
pylab.plot(diffs)
self.assertTrue(np.allclose(psi1.squeeze(), K_,
rtol=1e-1, atol=.1),
msg=msg + ": not matching")
@ -90,8 +99,9 @@ class Test(unittest.TestCase):
K_ /= self.Nsamples / Nsamples
msg = "psi2: {}".format("+".join([p.name + ard(p) for p in kern.parts]))
try:
# pylab.figure(msg)
# pylab.plot(diffs)
import pylab
pylab.figure(msg)
pylab.plot(diffs)
self.assertTrue(np.allclose(psi2.squeeze(), K_,
rtol=1e-1, atol=.1),
msg=msg + ": not matching")
@ -104,9 +114,11 @@ class Test(unittest.TestCase):
pass
if __name__ == "__main__":
import sys;sys.argv = ['',
'Test.test_psi0',
'Test.test_psi1',
'Test.test_psi2',
]
import sys
__test__ = 'deep' in sys.argv
sys.argv = ['',
'Test.test_psi0',
'Test.test_psi1',
'Test.test_psi2',
]
unittest.main()

View file

@ -1,6 +1,8 @@
import os
import numpy as np
import math
from GPy.util import datasets as dat
import urllib2
class vertex:
def __init__(self, name, id, parents=[], children=[], meta = {}):
@ -687,3 +689,71 @@ def read_connections(file_name, point_names):
skel = acclaim_skeleton()
def fetch_data(base_url = 'http://mocap.cs.cmu.edu:8080/subjects', skel_store_dir = '.', motion_store_dir = '.', subj_motions = None, store_motions = True, return_motions = True, messages = True):
'''
Download and store the skel. and motions indicated in a tuple (A,B) where A is a list of skeletons and B
the corresponding 2-D list of motions, ie B_ij is the j-th motion to download for skeleton A_i
The method can optionally store the fetched data and / or return them as arrays.
If the data are already stored, they are not fetched but just retrieved.
e.g.
# Download the data, do not return anything
GPy.util.mocap.fetch_data(subj_motions = (['35'],[['01','02','03']]), return_motions = False)
# Fetch and return the data in a list. Do not store them anywhere
GPy.util.mocap.fetch_data(subj_motions = (['35'],[['01','02','03']]), return_motions = True, store_motions = False)
In both cases above, if the data do exist in the given skel_store_dir and motion_store_dir, they are just loaded from there.
'''
subjects = subj_motions[0]
motions = subj_motions[1]
all_skels = []
assert len(subjects) == len(motions)
if return_motions:
all_motions = [list() for _ in range(len(subjects))]
else:
all_motions = []
for i in range(len(subjects)):
cur_skel_suffix = '/' + subjects[i] + '/'
cur_skel_dir = skel_store_dir + cur_skel_suffix
cur_skel_file = cur_skel_dir + subjects[i] + '.asf'
cur_skel_url = base_url + cur_skel_suffix + subjects[i] + '.asf'
if os.path.isfile(cur_skel_file):
if return_motions:
with open(cur_skel_file, 'r') as f:
cur_skel_data = f.read()
else:
if store_motions:
if not os.path.isdir(cur_skel_dir):
os.mkdir(cur_skel_dir)
if not os.path.isdir(motion_store_dir + cur_skel_suffix):
os.mkdir(motion_store_dir + cur_skel_suffix)
cur_skel_data = dat.fetch_dataset(cur_skel_url, cur_skel_file, store_motions, messages)
if return_motions:
all_skels.append(cur_skel_data)
for j in range(len(motions[i])):
cur_motion_url = base_url + cur_skel_suffix + subjects[i] + '_' + motions[i][j] + '.amc'
cur_motion_file = motion_store_dir + cur_skel_suffix + subjects[i] + '_' + motions[i][j] + '.amc'
if os.path.isfile(cur_motion_file):
with open(cur_motion_file, 'r') as f:
if return_motions:
cur_motion_data = f.read()
else:
cur_motion_data = dat.fetch_dataset(cur_motion_url, cur_motion_file, store_motions, messages)
if return_motions:
all_motions[i].append(cur_motion_data)
return all_skels, all_motions

View file

@ -1,13 +0,0 @@
import GPy
import urllib2
# TODO...
class mocap_fetch(base_url = 'http://mocap.cs.cmu.edu:8080/subjects/', skel_store_dir = './', motion_store_dir = './'):
def __init__(self):
self.base_url = base_url
self.store_dir = store_dir
self.motion_dict = []
def fetch_motions(self, motion_dict = None):
response = urllib2.urlopen(...)
html = response.read()