예제 #1
0
def _linear_fallback(Z: TensorLike,
                     u: TensorLike,
                     f: TensorLike,
                     *,
                     L: TensorLike = None,
                     diag: TensorLike = None,
                     basis: AbstractBasis = None,
                     **kwargs):

    u_shape = tuple(u.shape)
    f_shape = tuple(f.shape)
    assert u_shape[-1] == 1, "Recieved multiple output features"
    assert u_shape == f_shape[-len(u_shape):], "Incompatible shapes detected"

    # Prepare diagonal term
    if diag is None:  # used by <GPflow.conditionals>
        diag = default_jitter()
    if isinstance(diag, float):
        diag = tf.convert_to_tensor(diag, dtype=f.dtype)
    diag = tf.expand_dims(diag, axis=-1)  # [M, 1] or [1, 1] or [1]

    # Extract "features" of Z
    if basis is None:
        if isinstance(Z, inducing_variables.InducingVariables):
            feat = inducing_to_tensor(Z)  # [M, D]
        else:
            feat = Z
    else:
        feat = basis(Z)  # [M, D] (maybe a different "D" than above)

    # Compute error term and matrix square root $Cov(u, u)^{1/2}$
    err = swap_axes(u - f, -3, -1)  # [1, M, S]
    err -= tf.sqrt(diag) * tf.random.normal(err.shape, dtype=err.dtype)
    M, D = feat.shape[-2:]
    if L is None:
        if D < M:
            feat_iDiag = feat * tf.math.reciprocal(diag)
            S = tf.matmul(feat_iDiag, feat, transpose_a=True)  # [D, D]
            L = tf.linalg.cholesky(S + tf.eye(S.shape[-1], dtype=S.dtype))
        else:
            K = tf.matmul(feat, feat, transpose_b=True)  # [M, M]
            K = tf.linalg.set_diag(K, tf.linalg.diag_part(K) + diag[..., 0])
            L = tf.linalg.cholesky(K)
    else:
        assert L.shape[-1] == min(M, D)  # TODO: improve me

    # Solve for $Cov(u, u)^{-1}(u - f(Z))$
    if D < M:
        feat_iDiag = feat * tf.math.reciprocal(diag)
        weights = tf.linalg.adjoint(
            tf.linalg.cholesky_solve(
                L, tf.matmul(feat_iDiag, err, transpose_a=True)))
    else:
        iK_err = tf.linalg.cholesky_solve(L, err)  # [S, M, 1]
        weights = tf.matmul(iK_err, feat, transpose_a=True)  # [S, 1, D]

    return DenseSampler(basis=basis,
                        weights=move_axis(weights, -2, -3),
                        **kwargs)
예제 #2
0
def _test_fourier_conv2d_common(config, kern, X, Z):
  # Use closed-form evaluations as ground truth
  Kuu = covariances.Kuu(Z, kern)
  Kfu = covariances.Kfu(Z, kern, X)
  Kff = kern(X, full_cov=True)

  # Test Fourier-feature-based kernel approximator
  basis = fourier_basis(kern, num_bases=config.num_bases)
  feat_x = basis(X)  # [N, B] or [N, L, B]
  feat_z = basis(Z)

  tol = 3 * config.num_bases ** -0.5
  assert allclose(_avg_spatial_inner_product(feat_x, feat_x), Kff, tol, tol)
  assert allclose(_avg_spatial_inner_product(feat_x, feat_z), Kfu, tol, tol)
  assert allclose(_avg_spatial_inner_product(feat_z, feat_z), Kuu, tol, tol)
  del feat_x, feat_z

  # Test covariance of functions draw from approximate prior
  fx = []
  fz = []
  count = 0
  while count < config.num_samples:
    size = min(config.shard_size, config.num_samples - count)
    funcs = random_fourier(kern,
                           basis=basis,
                           num_bases=config.num_bases,
                           sample_shape=[size])

    fx.append(funcs(X))
    fz.append(funcs(Z))
    count += size

  fx = swap_axes(tf.concat(fx, axis=0), 0, -1)  # [L, N, H, W, S]
  fz = swap_axes(tf.concat(fz, axis=0), 0, -1)  # [L, M, 1, 1, S]
  nb = fx.shape.ndims - 4  # num. of batch dimensions
  tol += 3 * config.num_samples ** -0.5
  frac = 1 / config.num_samples

  assert allclose(frac * _avg_spatial_inner_product(fx, fx, nb), Kff, tol, tol)
  assert allclose(frac * _avg_spatial_inner_product(fx, fz, nb), Kfu, tol, tol)
  assert allclose(frac * _avg_spatial_inner_product(fz, fz, nb), Kuu, tol, tol)
def _Kuf_conv2d_fallback(Z, kernel, X, full_spatial: bool = False, **kwargs):
  Kfu = Kfu_dispatch(Z, kernel, X, full_spatial=full_spatial, **kwargs)

  ndims_x = X.shape.ndims - 3  # assume x lives in 3d image space
  ndims_z = Z.as_images.shape.ndims - 3

  if full_spatial:
    assert Kfu.shape.ndims == ndims_x + ndims_z + 2
    return swap_axes(Kfu, -4, -1)  # TODO: this is a hack

  # Swap the batch axes of x and z
  assert Kfu.shape.ndims == ndims_x + ndims_z
  axes = list(range(ndims_x + ndims_z))
  perm = axes[ndims_x: ndims_x + ndims_z] + axes[:ndims_x]
  return tf.transpose(Kfu, perm)
예제 #4
0
def _exact_independent(kern: kernels.MultioutputKernel,
                       Z: TensorLike,
                       u: TensorLike,
                       f: TensorLike,
                       *,
                       L: TensorLike = None,
                       diag: TensorLike = None,
                       basis: AbstractBasis = None,
                       multioutput_axis: int = 0,
                       **kwargs):
    """
  Return (independent) pathwise updates for each of the latent prior processes
  $f$ subject to the condition $p(f | u) = N(f | u, diag)$ on $f = f(Z)$.
  """
    u_shape = tuple(u.shape)
    f_shape = tuple(f.shape)
    assert u_shape[
        -1] == kern.num_latent_gps, "Num. outputs != num. latent GPs"
    assert u_shape == f_shape[-len(u_shape):], "Incompatible shapes detected"
    if basis is None:  # finite-dimensional basis used to express the update
        basis = kernel_basis(kern, centers=Z)

    # Prepare diagonal term
    if diag is None:  # used by <GPflow.conditionals>
        diag = default_jitter()
    if isinstance(diag, float):
        diag = tf.convert_to_tensor(diag, dtype=f.dtype)
    diag = tf.expand_dims(diag, axis=-1)  # ([L] or []) + ([M] or []) + [1]

    # Compute error term and matrix square root $Cov(u, u)^{1/2}$
    err = swap_axes(u - f, -3, -1)  # [L, M, S]
    err -= tf.sqrt(diag) * tf.random.normal(err.shape, dtype=err.dtype)
    if L is None:
        if isinstance(Z, inducing_variables.InducingVariables):
            K = covariances.Kuu(Z, kern, jitter=0.0)
        else:
            K = kern(Z, full_cov=True, full_output_cov=False)
        K = tf.linalg.set_diag(K, tf.linalg.diag_part(K) + diag[..., 0])
        L = tf.linalg.cholesky(K)

    # Solve for $Cov(u, u)^{-1}(u - f(Z))$
    weights = move_axis(tf.linalg.cholesky_solve(L, err), -1, -3)  # [S, L, M]
    return MultioutputDenseSampler(basis=basis,
                                   weights=weights,
                                   multioutput_axis=multioutput_axis,
                                   **kwargs)
예제 #5
0
  def convolve(self,
               input,
               filters,
               strides: List = None,
               padding: str = None,
               dilations: List = None,
               data_format: str = None):

    if strides is None:
      strides = self.strides

    if padding is None:
      padding = self.padding

    if dilations is None:
      dilations = self.dilations

    if data_format is None:
      data_format = self.data_format

    shape_out = self.get_shape_out(shape_in=input.shape,
                                   filter_shape=filters.shape,
                                   strides=strides,
                                   dilations=dilations,
                                   data_format=data_format)

    _filters = swap_axes(filters, -2, -1)
    conv_kwargs = dict(filters=_filters,
                       padding=padding,
                       output_shape=shape_out)

    if dilations != [1, 1]:  # TODO: improve me
      assert data_format == 'NHWC'
      assert list(strides) == [1, 1]
      assert len(dilations) == 2 and dilations[0] == dilations[1]
      return tf.nn.atrous_conv2d_transpose(input,
                                           rate=dilations[0],
                                           **conv_kwargs)

    return tf.nn.conv2d_transpose(input,
                                  strides=strides,
                                  dilations=dilations,
                                  data_format=data_format,
                                  **conv_kwargs)
예제 #6
0
def test_cg_conv2d(*args, **kwargs):
  f = swap_axes(_test_cg_svgp(*args, **kwargs), 0, -1)  # [L, N, H, W, S]
  mf = tf.transpose(tf.reduce_mean(f, [-3, -2, -1]))  # [N, L]
  res = f - tf.reduce_mean(f, axis=-1, keepdims=True)
  Sff = common.avg_spatial_inner_product(res, batch_dims=f.shape.ndims - 4)
  return mf, Sff/f.shape[-1]  # [L, N, N]
예제 #7
0
def _linear_multioutput(Z: inducing_variables.MultioutputInducingVariables,
                        u: TensorLike,
                        f: TensorLike,
                        *,
                        L: TensorLike = None,
                        diag: TensorLike = None,
                        basis: AbstractBasis = None,
                        multioutput_axis: int = "default",
                        **kwargs):
    assert tuple(u.shape) == tuple(f.shape)
    if multioutput_axis == "default":
        multioutput_axis = None if (basis is None) else 0

    # Prepare diagonal term
    if diag is None:  # used by <GPflow.conditionals>
        diag = default_jitter()
    if isinstance(diag, float):
        diag = tf.convert_to_tensor(diag, dtype=f.dtype)
    diag = tf.expand_dims(diag, axis=-1)  # ([L] or []) + ([M] or []) + [1]

    # Extract "features" of Z
    if basis is None:
        if isinstance(Z, inducing_variables.InducingVariables):
            feat = inducing_to_tensor(Z)  # [L, M, D] or [M, D]
        else:
            feat = Z
    elif isinstance(Z, inducing_variables.SharedIndependentInducingVariables):
        feat = basis(Z)
    else:
        feat = basis(Z,
                     multioutput_axis=0)  # first axis of Z is output-specific

    # Compute error term and matrix square root $Cov(u, u)^{1/2}$
    err = swap_axes(u - f, -3, -1)  # [L, M, S]
    err -= tf.sqrt(diag) * tf.random.normal(err.shape, dtype=err.dtype)
    M, D = feat.shape[-2:]
    if L is None:
        if D < M:
            feat_iDiag = feat * tf.math.reciprocal(diag)
            S = tf.matmul(feat_iDiag, feat,
                          transpose_a=True)  # [L, D, D] or [D, D]
            L = tf.linalg.cholesky(S + tf.eye(S.shape[-1], dtype=S.dtype))
        else:
            K = tf.matmul(feat, feat, transpose_b=True)  # [L, M, M] or [M, M]
            K = tf.linalg.set_diag(K, tf.linalg.diag_part(K) + diag[..., 0])
            L = tf.linalg.cholesky(K)
    else:
        assert L.shape[-1] == min(M, D)  # TODO: improve me

    # Solve for $Cov(u, u)^{-1}(u - f(Z))$
    if D < M:
        feat_iDiag = feat * tf.math.reciprocal(diag)
        weights = tf.linalg.adjoint(
            tf.linalg.cholesky_solve(
                L, tf.matmul(feat_iDiag, err, transpose_a=True)))
    else:
        iK_err = tf.linalg.cholesky_solve(L, err)  # [L, S, M]
        weights = tf.matmul(iK_err, feat, transpose_a=True)  # [L, S, D]

    return MultioutputDenseSampler(
        basis=basis,
        weights=swap_axes(weights, -3, -2),  # [S, L, D]
        multioutput_axis=multioutput_axis,
        **kwargs)