mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-30 14:35:15 +02:00
Expand class description and some speed improvements
This commit is contained in:
parent
09c72eeec5
commit
1cd8606451
1 changed files with 37 additions and 8 deletions
|
|
@ -7,11 +7,25 @@ class Symmetric(Kern):
|
||||||
"""
|
"""
|
||||||
Symmetric kernel that models a function with even or odd symmetry:
|
Symmetric kernel that models a function with even or odd symmetry:
|
||||||
|
|
||||||
|
For even symmetry we have:
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
|
|
||||||
f(x) = f(Ax)
|
f(x) = f(Ax)
|
||||||
|
|
||||||
or
|
we then model the function as:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
f(x) = g(x) + g(Ax)
|
||||||
|
|
||||||
|
the corresponding kernel is:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
k(x, x') + k(Ax, x') + k(x, Ax') + k(Ax, Ax')
|
||||||
|
|
||||||
|
For odd symmetry we have:
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
|
|
||||||
|
|
@ -21,13 +35,13 @@ class Symmetric(Kern):
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
|
|
||||||
f(x) = g(x) \pm g(Ax)
|
f(x) = g(x) - g(Ax)
|
||||||
|
|
||||||
with kernel
|
with kernel
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
|
|
||||||
k(x, x') \pm k(Ax, x') \pm k(x, Ax') + k(Ax, Ax')
|
k(x, x') - k(Ax, x') - k(x, Ax') + k(Ax, Ax')
|
||||||
|
|
||||||
where k(x, x') is the kernel of g(x)
|
where k(x, x') is the kernel of g(x)
|
||||||
|
|
||||||
|
|
@ -37,8 +51,8 @@ class Symmetric(Kern):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, base_kernel, transform, symmetry_type='even'):
|
def __init__(self, base_kernel, transform, symmetry_type='even'):
|
||||||
|
n_dims = max(base_kernel.active_dims) + 1
|
||||||
super(Symmetric, self).__init__(1, [0], name='symmetric_kernel')
|
super(Symmetric, self).__init__(n_dims, list(range(n_dims)), name='symmetric_kernel')
|
||||||
if symmetry_type is 'odd':
|
if symmetry_type is 'odd':
|
||||||
self.symmetry_sign = -1.
|
self.symmetry_sign = -1.
|
||||||
elif symmetry_type is 'even':
|
elif symmetry_type is 'even':
|
||||||
|
|
@ -114,15 +128,30 @@ class Symmetric(Kern):
|
||||||
dL_dK_full = np.diag(dL_dK)
|
dL_dK_full = np.diag(dL_dK)
|
||||||
X_sym = X.dot(self.transform)
|
X_sym = X.dot(self.transform)
|
||||||
|
|
||||||
|
# Calculate gradient for k(Ax, Ax')
|
||||||
self.base_kernel.update_gradients_diag(dL_dK, X_sym)
|
self.base_kernel.update_gradients_diag(dL_dK, X_sym)
|
||||||
gradient = self.base_kernel.gradient.copy()
|
gradient = self.base_kernel.gradient.copy()
|
||||||
|
|
||||||
|
# Calculate gradient for k(x, x')
|
||||||
self.base_kernel.update_gradients_diag(dL_dK, X)
|
self.base_kernel.update_gradients_diag(dL_dK, X)
|
||||||
gradient += self.base_kernel.gradient.copy()
|
gradient += self.base_kernel.gradient.copy()
|
||||||
|
|
||||||
# The contribution from both cross terms is the same
|
# Batch process cross term for speed
|
||||||
self.base_kernel.update_gradients_full(dL_dK_full, X, X_sym)
|
batch_size = 100
|
||||||
gradient += 2 * self.symmetry_sign * self.base_kernel.gradient.copy()
|
n_points = dL_dK.shape[0]
|
||||||
|
n_batches = int(np.ceil(n_points / float(batch_size)))
|
||||||
|
gradient_part = np.zeros(gradient.shape)
|
||||||
|
for i in range(n_batches):
|
||||||
|
i_start = i * batch_size
|
||||||
|
i_end = np.min([(i + 1) * batch_size, n_points])
|
||||||
|
dL_dK_part = dL_dK_full[i_start:i_end, i_start:i_end]
|
||||||
|
X_part = X[i_start:i_end, :]
|
||||||
|
X_sym_part = X_sym[i_start:i_end, :]
|
||||||
|
self.base_kernel.update_gradients_full(
|
||||||
|
dL_dK_part, X_part, X_sym_part)
|
||||||
|
gradient_part += self.base_kernel.gradient.copy()
|
||||||
|
|
||||||
|
gradient += 2 * self.symmetry_sign * gradient_part
|
||||||
|
|
||||||
self.base_kernel.gradient = gradient
|
self.base_kernel.gradient = gradient
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue