Skip to content

Commit d381a68

Browse files
willtebbuttgithub-actions[bot]st--theogf
authored
Multi-Output helper function (#345)
* Add helper function * Docs * Update src/mokernels/moinput.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Relax type constraint Co-authored-by: st-- <[email protected]> * Split into two methods * Update docs * Update src/mokernels/moinput.jl Co-authored-by: st-- <[email protected]> * Update src/mokernels/moinput.jl Co-authored-by: st-- <[email protected]> * Move consistency tests to test * Tweak wording * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update runtests.jl * Apply suggestions from code review Co-authored-by: st-- <[email protected]> * Update test/mokernels/moinput.jl Co-authored-by: st-- <[email protected]> * Bump patch Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: st-- <[email protected]> Co-authored-by: Théo Galy-Fajou <[email protected]>
1 parent a439a4b commit d381a68

File tree

6 files changed

+134
-6
lines changed

6 files changed

+134
-6
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "KernelFunctions"
22
uuid = "ec8451be-7e33-11e9-00cf-bbf324bd1392"
3-
version = "0.10.9"
3+
version = "0.10.10"
44

55
[deps]
66
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"

docs/src/api.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ For an explanation of this design choice, see [the design notes on multi-output
5858
An input to a multi-output `Kernel` should be a `Tuple{T, Int}`, whose first element specifies a location in the domain of the multi-output GP, and whose second element specifies which output the inputs corresponds to.
5959
The type of collections of inputs for multi-output GPs is therefore `AbstractVector{<:Tuple{T, Int}}`.
6060

61-
KernelFunctions.jl provides the following type or situations in which all outputs are observed all of the time:
61+
KernelFunctions.jl provides the following helper function for situations in which all outputs are observed all of the time:
62+
```@docs
63+
prepare_isotopic_multi_output_data(x::AbstractVector, y::ColVecs)
64+
prepare_isotopic_multi_output_data(x::AbstractVector, y::RowVecs)
65+
```
66+
67+
The input types that it constructs can also be constructed manually:
6268
```@docs
6369
MOInput
6470
```
@@ -68,7 +74,7 @@ type enables specialised implementations of e.g. [`kernelmatrix`](@ref) for
6874

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

71-
## Utilities
77+
## Generic Utilities
7278

7379
KernelFunctions also provides miscellaneous utility functions.
7480
```@docs

src/KernelFunctions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export spectral_mixture_kernel, spectral_mixture_product_kernel
3636

3737
export ColVecs, RowVecs
3838

39-
export MOInput
39+
export MOInput, prepare_isotopic_multi_output_data
4040
export IndependentMOKernel,
4141
LatentFactorMOKernel, IntrinsicCoregionMOKernel, LinearMixingModelKernel
4242

src/mokernels/moinput.jl

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,94 @@ See [Inputs for Multiple Outputs](@ref) in the docs for more info.
103103
and removed in version 0.12.
104104
"""
105105
const MOInput = MOInputIsotopicByOutputs
106+
107+
"""
108+
prepare_isotopic_multi_output_data(x::AbstractVector, y::ColVecs)
109+
110+
Utility functionality to convert a collection of `N = length(x)` inputs `x`, and a
111+
vector-of-vectors `y` (efficiently represented by a `ColVecs`) into a format suitable for
112+
use with multi-output kernels.
113+
114+
`y[n]` is the vector-valued output corresponding to the input `x[n]`.
115+
Consequently, it is necessary that `length(x) == length(y)`.
116+
117+
For example, if outputs are initially stored in a `num_outputs × N` matrix:
118+
```julia
119+
julia> x = [1.0, 2.0, 3.0];
120+
121+
julia> Y = [1.1 2.1 3.1; 1.2 2.2 3.2]
122+
2×3 Matrix{Float64}:
123+
1.1 2.1 3.1
124+
1.2 2.2 3.2
125+
126+
julia> inputs, outputs = prepare_isotopic_multi_output_data(x, ColVecs(Y));
127+
128+
julia> inputs
129+
6-element KernelFunctions.MOInputIsotopicByFeatures{Float64, Vector{Float64}}:
130+
(1.0, 1)
131+
(1.0, 2)
132+
(2.0, 1)
133+
(2.0, 2)
134+
(3.0, 1)
135+
(3.0, 2)
136+
137+
julia> outputs
138+
6-element Vector{Float64}:
139+
1.1
140+
1.2
141+
2.1
142+
2.2
143+
3.1
144+
3.2
145+
```
146+
"""
147+
function prepare_isotopic_multi_output_data(x::AbstractVector, y::ColVecs)
148+
length(x) == length(y) || throw(ArgumentError("length(x) not equal to length(y)."))
149+
return MOInputIsotopicByFeatures(x, size(y.X, 1)), vec(y.X)
150+
end
151+
152+
"""
153+
prepare_isotopic_multi_output_data(x::AbstractVector, y::RowVecs)
154+
155+
Utility functionality to convert a collection of `N = length(x)` inputs `x` and output
156+
vectors `y` (efficiently represented by a `RowVecs`) into a format suitable for
157+
use with multi-output kernels.
158+
159+
`y[n]` is the vector-valued output corresponding to the input `x[n]`.
160+
Consequently, it is necessary that `length(x) == length(y)`.
161+
162+
For example, if outputs are initial stored in an `N × num_outputs` matrix:
163+
```jldoctest
164+
julia> x = [1.0, 2.0, 3.0];
165+
166+
julia> Y = [1.1 1.2; 2.1 2.2; 3.1 3.2]
167+
3×2 Matrix{Float64}:
168+
1.1 1.2
169+
2.1 2.2
170+
3.1 3.2
171+
172+
julia> inputs, outputs = prepare_isotopic_multi_output_data(x, RowVecs(Y));
173+
174+
julia> inputs
175+
6-element KernelFunctions.MOInputIsotopicByOutputs{Float64, Vector{Float64}}:
176+
(1.0, 1)
177+
(2.0, 1)
178+
(3.0, 1)
179+
(1.0, 2)
180+
(2.0, 2)
181+
(3.0, 2)
182+
183+
julia> outputs
184+
6-element Vector{Float64}:
185+
1.1
186+
2.1
187+
3.1
188+
1.2
189+
2.2
190+
3.2
191+
```
192+
"""
193+
function prepare_isotopic_multi_output_data(x::AbstractVector, y::RowVecs)
194+
length(x) == length(y) || throw(ArgumentError("length(x) not equal to length(y)."))
195+
return MOInputIsotopicByOutputs(x, size(y.X, 2)), vec(y.X)
196+
end

test/mokernels/moinput.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,35 @@
4444
@test ibf[7] == (x[3], 1)
4545
@test all([(x_, i) for x_ in x for i in 1:3] .== ibf)
4646
end
47+
48+
@testset "prepare_isotopic_multi_output_data" begin
49+
@testset "ColVecs" begin
50+
N = 5
51+
P = 3
52+
53+
x = randn(N)
54+
y = ColVecs(randn(P, N))
55+
56+
x_canon, y_canon = prepare_isotopic_multi_output_data(x, y)
57+
58+
@test x_canon isa KernelFunctions.MOInputIsotopicByFeatures
59+
@test length(x_canon) == N * P
60+
@test y_canon isa AbstractVector{<:Real}
61+
@test length(y_canon) == length(x_canon)
62+
end
63+
@testset "RowVecs" begin
64+
N = 5
65+
P = 3
66+
67+
x = randn(N)
68+
y = RowVecs(randn(N, P))
69+
70+
x_canon, y_canon = prepare_isotopic_multi_output_data(x, y)
71+
72+
@test x_canon isa KernelFunctions.MOInputIsotopicByOutputs
73+
@test length(x_canon) == N * P
74+
@test y_canon isa AbstractVector{<:Real}
75+
@test length(y_canon) == length(x_canon)
76+
end
77+
end
4778
end

test/runtests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ include("test_utils.jl")
183183
KernelFunctions;
184184
doctestfilters=[
185185
r"{([a-zA-Z0-9]+,\s?)+[a-zA-Z0-9]+}",
186-
r"(Array{[a-zA-Z0-9]+,\s?1}|\s?Vector{[a-zA-Z0-9]+})",
187-
r"(Array{[a-zA-Z0-9]+,\s?2}|\s?Matrix{[a-zA-Z0-9]+})",
186+
r"(\s?Array{[a-zA-Z0-9]+,\s?1}|\s?Vector{[a-zA-Z0-9]+})",
187+
r"(\s?Array{[a-zA-Z0-9]+,\s?2}|\s?Matrix{[a-zA-Z0-9]+})",
188188
],
189189
)
190190
end

0 commit comments

Comments
 (0)