Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matrixkernel convenience functions and related performance improvements #363

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

Crown421
Copy link
Member

Summary
Following up from #354 , this pull request contains the matrixkernel convenience function, some additional tests, a small fix, and performance improvements that came up along the way.

Proposed changes

  • Adding matrixkernel
  • Include changes discussed in Some improvement and additions to MO kernels #354
  • Fix for helper method in fbm kernel
  • Performance improvement for lmm kernelmatrix
  • Fix specialized implementation for slfm to work with both MOInput types
  • Related tests

What alternatives have you considered?

@@ -43,6 +43,8 @@ end
_fbm(modX, modY, modXY, h) = (modX^h + modY^h - modXY^h) / 2

_mod(x::AbstractVector{<:Real}) = abs2.(x)
_mod(x::AbstractVector{<:AbstractVector{<:Real}}) = sum.(abs2, x)
# two lines above could be combined into the second (dispatching on general AbstractVectors), but this (somewhat) more performant
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this new line needed for ?

Suggested change
# two lines above could be combined into the second (dispatching on general AbstractVectors), but this (somewhat) more performant
# two lines above could be combined into the second (dispatching on general AbstractVectors), but this is (somewhat) more performant

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many other kernels work on arrays of arrays, but the fbm kernels errors as it could not find a method for _mod. I can try to recreate the example that I let me to add the line.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'd be great! Sounds like something that should be included in the test suite (maybe for all kernels?).
It also seems quite orthogonal to the matrixkernel addition, in which case it'd be helpful if you could move that out to a separate branch/PR as well :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for the delay, the error appears when doing

k = FBMKernel()
xs = [rand(5) for _ in 1:4]
kernelmatrix(k, xs)

which produces:
ERROR: LoadError: MethodError: no method matching _mod(::Array{Array{Float64,1},1})
This is needed during one of the matrixkernel calls. I can segment the fix into a separate pull request, but it is needed for this one. It would be easier for me if it could just be added via this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's very tempting to just keep things together in a single PR from the author's point of view, but I do highly recommend splitting it up - then e.g. it's easier for different people to review the different (smaller) PRs, it's easier to say "ok I'll spend ten minutes reviewing a ten-line PR" instead of thinking "oh when will i ever find enough time to review a several hundred lines PR", and so on!

src/mokernels/mokernel.jl Outdated Show resolved Hide resolved
src/mokernels/mokernel.jl Outdated Show resolved Hide resolved
test/mokernels/intrinsiccoregion.jl Outdated Show resolved Hide resolved
Crown421 and others added 2 commits September 16, 2021 11:48
Co-authored-by: st-- <st--@users.noreply.github.com>
@@ -80,6 +80,13 @@ type enables specialised implementations of e.g. [`kernelmatrix`](@ref) for

To find out more about the background, read this [review of kernels for vector-valued functions](https://arxiv.org/pdf/1106.6251.pdf).

If you are interested in the matrix-kernel interpretation, Kernelfunction provides a convenience function that computes the resulting kernel for a pair of inputs directly.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If you are interested in the matrix-kernel interpretation, Kernelfunction provides a convenience function that computes the resulting kernel for a pair of inputs directly.
If you are interested in the matrix-kernel interpretation, KernelFunctions provides a convenience function that computes the resulting kernel for a pair of inputs directly.

matrixkernel
```
<!-- Add when exporting IsotopicOutputs -->
<!-- One way to look at this is that applying `matrixkernel` pairwise to a list of inputs results in a block matrix, which when flattened is the same is the `kernelmatrix` computed when providing the same list of inputs as `MOInputIsotopicByOutputs`. -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"flattened" = "reshape from [N,N] array of [Q,Q] arrays to [NQ, NQ] array"? would it be worth being more explicit here?

@@ -15,6 +15,8 @@
@test repr(k) == "Fractional Brownian Motion Kernel (h = $(h))"
test_ADs(FBMKernel; ADs=[:ReverseDiff])

# ToDo: needs tests for _mod
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not specifically for _mod itself (though of course an equivalence of _mod([1, 2, 3]) == _mod([[1], [2], [3]]) would be good, but also for FBMKernel on higher-dimensional inputs

@@ -43,6 +43,8 @@ end
_fbm(modX, modY, modXY, h) = (modX^h + modY^h - modXY^h) / 2

_mod(x::AbstractVector{<:Real}) = abs2.(x)
_mod(x::AbstractVector{<:AbstractVector{<:Real}}) = sum.(abs2, x)
# two lines above could be combined into the second (dispatching on general AbstractVectors), but this (somewhat) more performant
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's very tempting to just keep things together in a single PR from the author's point of view, but I do highly recommend splitting it up - then e.g. it's easier for different people to review the different (smaller) PRs, it's easier to say "ok I'll spend ten minutes reviewing a ten-line PR" instead of thinking "oh when will i ever find enough time to review a several hundred lines PR", and so on!

Comment on lines +66 to +72
function kernelmatrix2(k::LinearMixingModelKernel, X, Y)
K = [kernelmatrix(ki, X.x, Y.x) for ki in k.K]
L = size(k.H, 2)
return reduce(
hcat, [reduce(vcat, [sum(k.H[:, i] .* (K .* k.H[:, j])) for i in 1:L]) for j in 1:L]
)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For ease of reviewing, it would be great if you could move the performance improvements into a separate PR!

function matrixkernel(k::MOKernel, x, y)
return throw(
ArgumentError(
"This kernel does not have a specific matrixkernel implementation, you can call `matrixkernel(k, x, y, out_dim)`",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"This kernel does not have a specific matrixkernel implementation, you can call `matrixkernel(k, x, y, out_dim)`",
"For a $(nameof(typeof(k)), you must explicitly specify the requested output dimension: call `matrixkernel(k, x, y, out_dim)`",

Comment on lines +28 to +34
function _kernelmatrix_kron_helper(::MOInputIsotopicByFeatures, Kfeatures, Koutputs)
return kron(Kfeatures, Koutputs)
end

function _kernelmatrix_kron_helper(::MOInputIsotopicByOutputs, Kfeatures, Koutputs)
return kron(Koutputs, Kfeatures)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not be part of this PR?

@@ -4,3 +4,31 @@
Abstract type for kernels with multiple outpus.
"""
abstract type MOKernel <: Kernel end

"""
matrixkernel(k::MOKernel, x, y)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
matrixkernel(k::MOKernel, x, y)
matrixkernel(k::MOKernel, x, y[, out_dim])

& explanation below?

@@ -45,7 +58,7 @@ function kernelmatrix(k::LatentFactorMOKernel, x::MOInput, y::MOInput)
H = [gi.(x.x, permutedims(y.x)) for gi in k.g]

# Weighted latent kernel matrix ((N*out_dim) x (N*out_dim))
W_H = sum(kron(Wi, Hi) for (Wi, Hi) in zip(W, H))
W_H = sum(_kernelmatrix_kron_helper(x, Hi, Wi) for (Wi, Hi) in zip(W, H))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this work if x and y have different types?

Comment on lines +36 to +39
# function matrixkernel(k::LatentFactorMOKernel, x, y)
# return matrixkernel(k, x, y, size(k.A, 1))
# end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# function matrixkernel(k::LatentFactorMOKernel, x, y)
# return matrixkernel(k, x, y, size(k.A, 1))
# end

but would be great to check the implementation for correctness by comparing against this!

@Crown421 Crown421 changed the title Matrixkernel convenience functions and related performancec improvements Matrixkernel convenience functions and related performance improvements Sep 24, 2021
@Crown421
Copy link
Member Author

As suggested, I am splitting this again into a few smaller PRs, not in the least because in doing so smaller bits spawned more larger issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants