mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-03 16:52:39 +02:00
REFACTORING: model names, lowercase, classes uppercase
This commit is contained in:
parent
2a39440619
commit
2e5e8ac026
50 changed files with 436 additions and 3307 deletions
|
|
@ -1,87 +1,80 @@
|
|||
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||
|
||||
#tdot function courtesy of Ian Murray:
|
||||
# tdot function courtesy of Ian Murray:
|
||||
# Iain Murray, April 2013. iain contactable via iainmurray.net
|
||||
# http://homepages.inf.ed.ac.uk/imurray2/code/tdot/tdot.py
|
||||
|
||||
import numpy as np
|
||||
from scipy import linalg, optimize, weave
|
||||
import pylab as pb
|
||||
import Tango
|
||||
import sys
|
||||
import re
|
||||
import pdb
|
||||
import cPickle
|
||||
from scipy import linalg, weave
|
||||
import types
|
||||
import ctypes
|
||||
from ctypes import byref, c_char, c_int, c_double # TODO
|
||||
#import scipy.lib.lapack
|
||||
import scipy as sp
|
||||
# import scipy.lib.lapack
|
||||
|
||||
try:
|
||||
_blaslib = ctypes.cdll.LoadLibrary(np.core._dotblas.__file__)
|
||||
_blaslib = ctypes.cdll.LoadLibrary(np.core._dotblas.__file__) # @UndefinedVariable
|
||||
_blas_available = True
|
||||
except:
|
||||
_blas_available = False
|
||||
|
||||
def trace_dot(a,b):
|
||||
def trace_dot(a, b):
|
||||
"""
|
||||
efficiently compute the trace of the matrix product of a and b
|
||||
"""
|
||||
return np.sum(a*b)
|
||||
return np.sum(a * b)
|
||||
|
||||
def mdot(*args):
|
||||
"""Multiply all the arguments using matrix product rules.
|
||||
The output is equivalent to multiplying the arguments one by one
|
||||
from left to right using dot().
|
||||
Precedence can be controlled by creating tuples of arguments,
|
||||
for instance mdot(a,((b,c),d)) multiplies a (a*((b*c)*d)).
|
||||
Note that this means the output of dot(a,b) and mdot(a,b) will differ if
|
||||
a or b is a pure tuple of numbers.
|
||||
"""
|
||||
if len(args)==1:
|
||||
return args[0]
|
||||
elif len(args)==2:
|
||||
return _mdot_r(args[0],args[1])
|
||||
else:
|
||||
return _mdot_r(args[:-1],args[-1])
|
||||
"""Multiply all the arguments using matrix product rules.
|
||||
The output is equivalent to multiplying the arguments one by one
|
||||
from left to right using dot().
|
||||
Precedence can be controlled by creating tuples of arguments,
|
||||
for instance mdot(a,((b,c),d)) multiplies a (a*((b*c)*d)).
|
||||
Note that this means the output of dot(a,b) and mdot(a,b) will differ if
|
||||
a or b is a pure tuple of numbers.
|
||||
"""
|
||||
if len(args) == 1:
|
||||
return args[0]
|
||||
elif len(args) == 2:
|
||||
return _mdot_r(args[0], args[1])
|
||||
else:
|
||||
return _mdot_r(args[:-1], args[-1])
|
||||
|
||||
def _mdot_r(a,b):
|
||||
"""Recursive helper for mdot"""
|
||||
if type(a)==types.TupleType:
|
||||
if len(a)>1:
|
||||
a = mdot(*a)
|
||||
else:
|
||||
a = a[0]
|
||||
if type(b)==types.TupleType:
|
||||
if len(b)>1:
|
||||
b = mdot(*b)
|
||||
else:
|
||||
b = b[0]
|
||||
return np.dot(a,b)
|
||||
def _mdot_r(a, b):
|
||||
"""Recursive helper for mdot"""
|
||||
if type(a) == types.TupleType:
|
||||
if len(a) > 1:
|
||||
a = mdot(*a)
|
||||
else:
|
||||
a = a[0]
|
||||
if type(b) == types.TupleType:
|
||||
if len(b) > 1:
|
||||
b = mdot(*b)
|
||||
else:
|
||||
b = b[0]
|
||||
return np.dot(a, b)
|
||||
|
||||
def jitchol(A,maxtries=5):
|
||||
def jitchol(A, maxtries=5):
|
||||
A = np.asfortranarray(A)
|
||||
L,info = linalg.lapack.flapack.dpotrf(A,lower=1)
|
||||
if info ==0:
|
||||
L, info = linalg.lapack.flapack.dpotrf(A, lower=1)
|
||||
if info == 0:
|
||||
return L
|
||||
else:
|
||||
diagA = np.diag(A)
|
||||
if np.any(diagA<0.):
|
||||
if np.any(diagA < 0.):
|
||||
raise linalg.LinAlgError, "not pd: negative diagonal elements"
|
||||
jitter= diagA.mean()*1e-6
|
||||
for i in range(1,maxtries+1):
|
||||
jitter = diagA.mean() * 1e-6
|
||||
for i in range(1, maxtries + 1):
|
||||
print 'Warning: adding jitter of {:.10e}'.format(jitter)
|
||||
try:
|
||||
return linalg.cholesky(A+np.eye(A.shape[0]).T*jitter, lower = True)
|
||||
return linalg.cholesky(A + np.eye(A.shape[0]).T * jitter, lower=True)
|
||||
except:
|
||||
jitter *= 10
|
||||
raise linalg.LinAlgError,"not positive definite, even with jitter."
|
||||
raise linalg.LinAlgError, "not positive definite, even with jitter."
|
||||
|
||||
|
||||
|
||||
def jitchol_old(A,maxtries=5):
|
||||
def jitchol_old(A, maxtries=5):
|
||||
"""
|
||||
:param A : An almost pd square matrix
|
||||
|
||||
|
|
@ -93,20 +86,20 @@ def jitchol_old(A,maxtries=5):
|
|||
np.allclose(sp.linalg.cholesky(XXT, lower = True), np.triu(sp.linalg.cho_factor(XXT)[0]).T)
|
||||
"""
|
||||
try:
|
||||
return linalg.cholesky(A, lower = True)
|
||||
return linalg.cholesky(A, lower=True)
|
||||
except linalg.LinAlgError:
|
||||
diagA = np.diag(A)
|
||||
if np.any(diagA<0.):
|
||||
if np.any(diagA < 0.):
|
||||
raise linalg.LinAlgError, "not pd: negative diagonal elements"
|
||||
jitter= diagA.mean()*1e-6
|
||||
for i in range(1,maxtries+1):
|
||||
jitter = diagA.mean() * 1e-6
|
||||
for i in range(1, maxtries + 1):
|
||||
print '\rWarning: adding jitter of {:.10e} '.format(jitter),
|
||||
try:
|
||||
return linalg.cholesky(A+np.eye(A.shape[0]).T*jitter, lower = True)
|
||||
return linalg.cholesky(A + np.eye(A.shape[0]).T * jitter, lower=True)
|
||||
except:
|
||||
jitter *= 10
|
||||
|
||||
raise linalg.LinAlgError,"not positive definite, even with jitter."
|
||||
raise linalg.LinAlgError, "not positive definite, even with jitter."
|
||||
|
||||
def pdinv(A, *args):
|
||||
"""
|
||||
|
|
@ -125,7 +118,7 @@ def pdinv(A, *args):
|
|||
logdet = 2.*np.sum(np.log(np.diag(L)))
|
||||
Li = chol_inv(L)
|
||||
Ai, _ = linalg.lapack.flapack.dpotri(L)
|
||||
#Ai = np.tril(Ai) + np.tril(Ai,-1).T
|
||||
# Ai = np.tril(Ai) + np.tril(Ai,-1).T
|
||||
symmetrify(Ai)
|
||||
|
||||
return Ai, L, Li, logdet
|
||||
|
|
@ -140,7 +133,7 @@ def chol_inv(L):
|
|||
|
||||
"""
|
||||
|
||||
return linalg.lapack.flapack.dtrtri(L, lower = True)[0]
|
||||
return linalg.lapack.flapack.dtrtri(L, lower=True)[0]
|
||||
|
||||
|
||||
def multiple_pdinv(A):
|
||||
|
|
@ -155,11 +148,11 @@ def multiple_pdinv(A):
|
|||
hld: 0.5* the log of the determinants of A
|
||||
"""
|
||||
N = A.shape[-1]
|
||||
chols = [jitchol(A[:,:,i]) for i in range(N)]
|
||||
chols = [jitchol(A[:, :, i]) for i in range(N)]
|
||||
halflogdets = [np.sum(np.log(np.diag(L[0]))) for L in chols]
|
||||
invs = [linalg.lapack.flapack.dpotri(L[0],True)[0] for L in chols]
|
||||
invs = [np.triu(I)+np.triu(I,1).T for I in invs]
|
||||
return np.dstack(invs),np.array(halflogdets)
|
||||
invs = [linalg.lapack.flapack.dpotri(L[0], True)[0] for L in chols]
|
||||
invs = [np.triu(I) + np.triu(I, 1).T for I in invs]
|
||||
return np.dstack(invs), np.array(halflogdets)
|
||||
|
||||
|
||||
def PCA(Y, input_dim):
|
||||
|
|
@ -179,18 +172,18 @@ def PCA(Y, input_dim):
|
|||
if not np.allclose(Y.mean(axis=0), 0.0):
|
||||
print "Y is not zero mean, centering it locally (GPy.util.linalg.PCA)"
|
||||
|
||||
#Y -= Y.mean(axis=0)
|
||||
# Y -= Y.mean(axis=0)
|
||||
|
||||
Z = linalg.svd(Y-Y.mean(axis=0), full_matrices = False)
|
||||
[X, W] = [Z[0][:,0:input_dim], np.dot(np.diag(Z[1]), Z[2]).T[:,0:input_dim]]
|
||||
Z = linalg.svd(Y - Y.mean(axis=0), full_matrices=False)
|
||||
[X, W] = [Z[0][:, 0:input_dim], np.dot(np.diag(Z[1]), Z[2]).T[:, 0:input_dim]]
|
||||
v = X.std(axis=0)
|
||||
X /= v;
|
||||
W *= v;
|
||||
return X, W.T
|
||||
|
||||
|
||||
def tdot_numpy(mat,out=None):
|
||||
return np.dot(mat,mat.T,out)
|
||||
def tdot_numpy(mat, out=None):
|
||||
return np.dot(mat, mat.T, out)
|
||||
|
||||
def tdot_blas(mat, out=None):
|
||||
"""returns np.dot(mat, mat.T), but faster for large 2D arrays of doubles."""
|
||||
|
|
@ -198,16 +191,16 @@ def tdot_blas(mat, out=None):
|
|||
return np.dot(mat, mat.T)
|
||||
nn = mat.shape[0]
|
||||
if out is None:
|
||||
out = np.zeros((nn,nn))
|
||||
out = np.zeros((nn, nn))
|
||||
else:
|
||||
assert(out.dtype == 'float64')
|
||||
assert(out.shape == (nn,nn))
|
||||
assert(out.shape == (nn, nn))
|
||||
# FIXME: should allow non-contiguous out, and copy output into it:
|
||||
assert(8 in out.strides)
|
||||
# zeroing needed because of dumb way I copy across triangular answer
|
||||
out[:] = 0.0
|
||||
|
||||
## Call to DSYRK from BLAS
|
||||
# # Call to DSYRK from BLAS
|
||||
# If already in Fortran order (rare), and has the right sorts of strides I
|
||||
# could avoid the copy. I also thought swapping to cblas API would allow use
|
||||
# of C order. However, I tried that and had errors with large matrices:
|
||||
|
|
@ -226,17 +219,17 @@ def tdot_blas(mat, out=None):
|
|||
_blaslib.dsyrk_(byref(UPLO), byref(TRANS), byref(N), byref(K),
|
||||
byref(ALPHA), A, byref(LDA), byref(BETA), C, byref(LDC))
|
||||
|
||||
symmetrify(out,upper=True)
|
||||
symmetrify(out, upper=True)
|
||||
|
||||
return out
|
||||
|
||||
def tdot(*args, **kwargs):
|
||||
if _blas_available:
|
||||
return tdot_blas(*args,**kwargs)
|
||||
return tdot_blas(*args, **kwargs)
|
||||
else:
|
||||
return tdot_numpy(*args,**kwargs)
|
||||
return tdot_numpy(*args, **kwargs)
|
||||
|
||||
def DSYR_blas(A,x,alpha=1.):
|
||||
def DSYR_blas(A, x, alpha=1.):
|
||||
"""
|
||||
Performs a symmetric rank-1 update operation:
|
||||
A <- A + alpha * np.dot(x,x.T)
|
||||
|
|
@ -256,9 +249,9 @@ def DSYR_blas(A,x,alpha=1.):
|
|||
INCX = c_int(1)
|
||||
_blaslib.dsyr_(byref(UPLO), byref(N), byref(ALPHA),
|
||||
x_, byref(INCX), A_, byref(LDA))
|
||||
symmetrify(A,upper=True)
|
||||
symmetrify(A, upper=True)
|
||||
|
||||
def DSYR_numpy(A,x,alpha=1.):
|
||||
def DSYR_numpy(A, x, alpha=1.):
|
||||
"""
|
||||
Performs a symmetric rank-1 update operation:
|
||||
A <- A + alpha * np.dot(x,x.T)
|
||||
|
|
@ -269,23 +262,23 @@ def DSYR_numpy(A,x,alpha=1.):
|
|||
:param x: Nx1 np.array
|
||||
:param alpha: scalar
|
||||
"""
|
||||
A += alpha*np.dot(x[:,None],x[None,:])
|
||||
A += alpha * np.dot(x[:, None], x[None, :])
|
||||
|
||||
|
||||
def DSYR(*args, **kwargs):
|
||||
if _blas_available:
|
||||
return DSYR_blas(*args,**kwargs)
|
||||
return DSYR_blas(*args, **kwargs)
|
||||
else:
|
||||
return DSYR_numpy(*args,**kwargs)
|
||||
return DSYR_numpy(*args, **kwargs)
|
||||
|
||||
def symmetrify(A,upper=False):
|
||||
def symmetrify(A, upper=False):
|
||||
"""
|
||||
Take the square matrix A and make it symmetrical by copting elements from the lower half to the upper
|
||||
|
||||
works IN PLACE.
|
||||
"""
|
||||
N,M = A.shape
|
||||
assert N==M
|
||||
N, M = A.shape
|
||||
assert N == M
|
||||
c_contig_code = """
|
||||
int iN;
|
||||
for (int i=1; i<N; i++){
|
||||
|
|
@ -305,13 +298,13 @@ def symmetrify(A,upper=False):
|
|||
}
|
||||
"""
|
||||
if A.flags['C_CONTIGUOUS'] and upper:
|
||||
weave.inline(f_contig_code,['A','N'], extra_compile_args=['-O3'])
|
||||
weave.inline(f_contig_code, ['A', 'N'], extra_compile_args=['-O3'])
|
||||
elif A.flags['C_CONTIGUOUS'] and not upper:
|
||||
weave.inline(c_contig_code,['A','N'], extra_compile_args=['-O3'])
|
||||
weave.inline(c_contig_code, ['A', 'N'], extra_compile_args=['-O3'])
|
||||
elif A.flags['F_CONTIGUOUS'] and upper:
|
||||
weave.inline(c_contig_code,['A','N'], extra_compile_args=['-O3'])
|
||||
weave.inline(c_contig_code, ['A', 'N'], extra_compile_args=['-O3'])
|
||||
elif A.flags['F_CONTIGUOUS'] and not upper:
|
||||
weave.inline(f_contig_code,['A','N'], extra_compile_args=['-O3'])
|
||||
weave.inline(f_contig_code, ['A', 'N'], extra_compile_args=['-O3'])
|
||||
else:
|
||||
if upper:
|
||||
tmp = np.tril(A.T)
|
||||
|
|
@ -319,15 +312,15 @@ def symmetrify(A,upper=False):
|
|||
tmp = np.tril(A)
|
||||
A[:] = 0.0
|
||||
A += tmp
|
||||
A += np.tril(tmp,-1).T
|
||||
A += np.tril(tmp, -1).T
|
||||
|
||||
|
||||
def symmetrify_murray(A):
|
||||
A += A.T
|
||||
nn = A.shape[0]
|
||||
A[[range(nn),range(nn)]] /= 2.0
|
||||
A[[range(nn), range(nn)]] /= 2.0
|
||||
|
||||
def cholupdate(L,x):
|
||||
def cholupdate(L, x):
|
||||
"""
|
||||
update the LOWER cholesky factor of a pd matrix IN PLACE
|
||||
|
||||
|
|
@ -337,7 +330,7 @@ def cholupdate(L,x):
|
|||
support_code = """
|
||||
#include <math.h>
|
||||
"""
|
||||
code="""
|
||||
code = """
|
||||
double r,c,s;
|
||||
int j,i;
|
||||
for(j=0; j<N; j++){
|
||||
|
|
@ -353,11 +346,11 @@ def cholupdate(L,x):
|
|||
"""
|
||||
x = x.copy()
|
||||
N = x.size
|
||||
weave.inline(code, support_code=support_code, arg_names=['N','L','x'], type_converters=weave.converters.blitz)
|
||||
weave.inline(code, support_code=support_code, arg_names=['N', 'L', 'x'], type_converters=weave.converters.blitz)
|
||||
|
||||
def backsub_both_sides(L, X,transpose='left'):
|
||||
def backsub_both_sides(L, X, transpose='left'):
|
||||
""" Return L^-T * X * L^-1, assumuing X is symmetrical and L is lower cholesky"""
|
||||
if transpose=='left':
|
||||
if transpose == 'left':
|
||||
tmp, _ = linalg.lapack.flapack.dtrtrs(L, np.asfortranarray(X), lower=1, trans=1)
|
||||
return linalg.lapack.flapack.dtrtrs(L, np.asfortranarray(tmp.T), lower=1, trans=1)[0].T
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue