|
1 | 1 | @testset "ucme.jl" begin |
2 | | - @testset "UCME: Two-dimensional example" begin |
3 | | - # three test locations |
| 2 | + @testset "UCME: Binary examples" begin |
| 3 | + # categorical distributions |
4 | 4 | ucme = UCME( |
5 | 5 | SqExponentialKernel() ⊗ WhiteKernel(), |
6 | 6 | [[1.0, 0], [0.5, 0.5], [0.0, 1]], |
7 | 7 | [1, 1, 2], |
8 | 8 | ) |
9 | | - |
10 | | - # two predictions |
11 | 9 | @test iszero(@inferred(ucme([[1, 0], [0, 1]], [1, 2]))) |
12 | 10 | @test @inferred(ucme([[1, 0], [0, 1]], [1, 1])) ≈ (exp(-2) + exp(-0.5) + 1) / 12 |
13 | 11 | @test @inferred(ucme([[1, 0], [0, 1]], [2, 1])) ≈ (1 - exp(-1))^2 / 6 |
14 | 12 | @test @inferred(ucme([[1, 0], [0, 1]], [2, 2])) ≈ (exp(-2) + exp(-0.5) + 1) / 12 |
| 13 | + |
| 14 | + # probabilities |
| 15 | + ucme = UCME( |
| 16 | + (SqExponentialKernel() ∘ ScaleTransform(sqrt(2))) ⊗ WhiteKernel(), |
| 17 | + [1.0, 0.5, 0.0], |
| 18 | + [true, true, false], |
| 19 | + ) |
| 20 | + @test iszero(@inferred(ucme([1, 0], [true, false]))) |
| 21 | + @test @inferred(ucme([1, 0], [true, true])) ≈ (exp(-2) + exp(-0.5) + 1) / 12 |
| 22 | + @test @inferred(ucme([1, 0], [false, true])) ≈ (1 - exp(-1))^2 / 6 |
| 23 | + @test @inferred(ucme([1, 0], [false, false])) ≈ (exp(-2) + exp(-0.5) + 1) / 12 |
15 | 24 | end |
16 | 25 |
|
17 | 26 | @testset "UCME: Basic properties" begin |
18 | 27 | estimates = Vector{Float64}(undef, 1_000) |
19 | 28 |
|
20 | | - for ntest in (1, 5, 10), nclasses in (2, 10, 100) |
21 | | - dist = Dirichlet(nclasses, 1.0) |
| 29 | + for ntest in (1, 5, 10) |
| 30 | + # categorical distributions |
| 31 | + for nclasses in (2, 10, 100) |
| 32 | + dist = Dirichlet(nclasses, 1.0) |
| 33 | + |
| 34 | + testpredictions = [rand(dist) for _ in 1:ntest] |
| 35 | + testtargets = rand(1:nclasses, ntest) |
| 36 | + ucme = UCME( |
| 37 | + (ExponentialKernel() ∘ ScaleTransform(0.1)) ⊗ WhiteKernel(), |
| 38 | + testpredictions, |
| 39 | + testtargets, |
| 40 | + ) |
| 41 | + |
| 42 | + predictions = [Vector{Float64}(undef, nclasses) for _ in 1:20] |
| 43 | + targets = Vector{Int}(undef, 20) |
22 | 44 |
|
23 | | - testpredictions = [rand(dist) for _ in 1:ntest] |
24 | | - testtargets = rand(1:nclasses, ntest) |
| 45 | + for i in 1:length(estimates) |
| 46 | + rand!.(Ref(dist), predictions) |
| 47 | + targets .= rand.(Categorical.(predictions)) |
| 48 | + |
| 49 | + estimates[i] = ucme(predictions, targets) |
| 50 | + end |
| 51 | + |
| 52 | + @test all(x > zero(x) for x in estimates) |
| 53 | + end |
| 54 | + |
| 55 | + # probabilities |
| 56 | + testpredictions = rand(ntest) |
| 57 | + testtargets = rand(Bool, ntest) |
25 | 58 | ucme = UCME( |
26 | 59 | (ExponentialKernel() ∘ ScaleTransform(0.1)) ⊗ WhiteKernel(), |
27 | 60 | testpredictions, |
28 | 61 | testtargets, |
29 | 62 | ) |
30 | 63 |
|
31 | | - predictions = [Vector{Float64}(undef, nclasses) for _ in 1:20] |
32 | | - targets = Vector{Int}(undef, 20) |
| 64 | + predictions = Vector{Float64}(undef, 20) |
| 65 | + targets = Vector{Bool}(undef, 20) |
33 | 66 |
|
34 | 67 | for i in 1:length(estimates) |
35 | | - rand!.(Ref(dist), predictions) |
36 | | - targets .= rand.(Categorical.(predictions)) |
| 68 | + rand!(predictions) |
| 69 | + map!(targets, predictions) do p |
| 70 | + return rand() < p |
| 71 | + end |
37 | 72 |
|
38 | 73 | estimates[i] = ucme(predictions, targets) |
39 | 74 | end |
40 | 75 |
|
41 | 76 | @test all(x > zero(x) for x in estimates) |
42 | 77 | end |
43 | 78 | end |
| 79 | + |
| 80 | + # alternative implementation of white kernel |
| 81 | + struct WhiteKernel2 <: Kernel end |
| 82 | + (::WhiteKernel2)(x, y) = x == y |
| 83 | + |
| 84 | + # alternative implementation TensorProductKernel |
| 85 | + struct TensorProduct2{K1<:Kernel,K2<:Kernel} <: Kernel |
| 86 | + kernel1::K1 |
| 87 | + kernel2::K2 |
| 88 | + end |
| 89 | + function (kernel::TensorProduct2)((x1, x2), (y1, y2)) |
| 90 | + return kernel.kernel1(x1, y1) * kernel.kernel2(x2, y2) |
| 91 | + end |
| 92 | + |
| 93 | + @testset "binary classification" begin |
| 94 | + # probabilities and boolean targets |
| 95 | + p, testp = rand(2) |
| 96 | + y, testy = rand(Bool, 2) |
| 97 | + scale = rand() |
| 98 | + kernel = SqExponentialKernel() ∘ ScaleTransform(scale) |
| 99 | + val = unsafe_ucme_eval(kernel ⊗ WhiteKernel(), p, y, testp, testy) |
| 100 | + @test unsafe_ucme_eval(kernel ⊗ WhiteKernel2(), p, y, testp, testy) ≈ val |
| 101 | + @test unsafe_ucme_eval(TensorProduct2(kernel, WhiteKernel()), p, y, testp, testy) ≈ |
| 102 | + val |
| 103 | + @test unsafe_ucme_eval(TensorProduct2(kernel, WhiteKernel2()), p, y, testp, testy) ≈ |
| 104 | + val |
| 105 | + |
| 106 | + # corresponding values and kernel for full categorical distribution |
| 107 | + pfull = [p, 1 - p] |
| 108 | + yint = 2 - y |
| 109 | + testpfull = [testp, 1 - testp] |
| 110 | + testyint = 2 - testy |
| 111 | + kernelfull = SqExponentialKernel() ∘ ScaleTransform(scale / sqrt(2)) |
| 112 | + |
| 113 | + @test unsafe_ucme_eval( |
| 114 | + kernelfull ⊗ WhiteKernel(), pfull, yint, testpfull, testyint |
| 115 | + ) ≈ val |
| 116 | + @test unsafe_ucme_eval( |
| 117 | + kernelfull ⊗ WhiteKernel2(), pfull, yint, testpfull, testyint |
| 118 | + ) ≈ val |
| 119 | + @test unsafe_ucme_eval( |
| 120 | + TensorProduct2(kernelfull, WhiteKernel()), pfull, yint, testpfull, testyint |
| 121 | + ) ≈ val |
| 122 | + @test unsafe_ucme_eval( |
| 123 | + TensorProduct2(kernelfull, WhiteKernel2()), pfull, yint, testpfull, testyint |
| 124 | + ) ≈ val |
| 125 | + end |
| 126 | + |
| 127 | + @testset "multi-class classification" begin |
| 128 | + n = 10 |
| 129 | + p = rand(n) |
| 130 | + p ./= sum(p) |
| 131 | + y = rand(1:n) |
| 132 | + testp = rand(n) |
| 133 | + testp ./= sum(testp) |
| 134 | + testy = rand(1:n) |
| 135 | + |
| 136 | + kernel = SqExponentialKernel() ∘ ScaleTransform(rand()) |
| 137 | + val = unsafe_ucme_eval(kernel ⊗ WhiteKernel(), p, y, testp, testy) |
| 138 | + |
| 139 | + @test unsafe_ucme_eval(kernel ⊗ WhiteKernel2(), p, y, testp, testy) ≈ val |
| 140 | + @test unsafe_ucme_eval(TensorProduct2(kernel, WhiteKernel()), p, y, testp, testy) ≈ |
| 141 | + val |
| 142 | + @test unsafe_ucme_eval(TensorProduct2(kernel, WhiteKernel2()), p, y, testp, testy) ≈ |
| 143 | + val |
| 144 | + end |
44 | 145 | end |
0 commit comments