From 5c854ee39006dc8fe3a8477807ace6bf61d90194 Mon Sep 17 00:00:00 2001 From: ST John Date: Tue, 11 Jan 2022 16:23:28 +0200 Subject: [PATCH 1/3] switch SVM example to half-moon dataset --- examples/support-vector-machine/script.jl | 40 +++++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/examples/support-vector-machine/script.jl b/examples/support-vector-machine/script.jl index f2824d4d4..97202b72a 100644 --- a/examples/support-vector-machine/script.jl +++ b/examples/support-vector-machine/script.jl @@ -8,39 +8,43 @@ using LinearAlgebra using Plots using Random -## Set plotting theme -theme(:wong) - ## Set seed Random.seed!(1234); -# Number of samples: -N = 100; +# ## Generate half-moon dataset -# Select randomly between two classes: -y_train = rand([-1, 1], N); +# Number of samples per class: +nin = nout = 50; -# Random attributes for both classes: -X = Matrix{Float64}(undef, 2, N) -rand!(MvNormal(randn(2), I), view(X, :, y_train .== 1)) -rand!(MvNormal(randn(2), I), view(X, :, y_train .== -1)); -x_train = ColVecs(X); +# Generate data +## based on SciKit-Learn's sklearn.datasets.make_moons function +class1x = cos.(range(0, π; length=nout)) +class1y = sin.(range(0, π; length=nout)) +class2x = 1 .- cos.(range(0, π; length=nin)) +class2y = 1 .- sin.(range(0, π; length=nin)) .- 0.5 +X = hcat(vcat(class1x, class2x), vcat(class1y, class2y)) +X .+= 0.1randn(size(X)) +x_train = RowVecs(X); +y_train = vcat(fill(-1, nout), fill(1, nin)); -# Create a 2D grid: +# Create a 100×100 2D grid for evaluation: test_range = range(floor(Int, minimum(X)), ceil(Int, maximum(X)); length=100) x_test = ColVecs(mapreduce(collect, hcat, Iterators.product(test_range, test_range))); # Create kernel function: -k = SqExponentialKernel() ∘ ScaleTransform(2.0) +k = SqExponentialKernel() ∘ ScaleTransform(1.5) # [LIBSVM](https://github.com/JuliaML/LIBSVM.jl) can make use of a pre-computed kernel matrix. # KernelFunctions.jl can be used to produce that. -# Precomputed matrix for training (corresponds to linear kernel) +# +# Precomputed matrix for training model = svmtrain(kernelmatrix(k, x_train), y_train; kernel=LIBSVM.Kernel.Precomputed) # Precomputed matrix for prediction -y_pr, _ = svmpredict(model, kernelmatrix(k, x_train, x_test)); +y_pred, _ = svmpredict(model, kernelmatrix(k, x_train, x_test)); # Compute prediction on a grid: -contourf(test_range, test_range, y_pr) -scatter!(X[1, :], X[2, :]; color=y_train, lab="data", widen=false) +plot(lim=extrema(test_range)) +contourf!(test_range, test_range, y_pred; levels=1, color=cgrad(:redsblues), alpha=0.7) +scatter!(X[y_train.==-1, 1], X[y_train.==-1, 2]; color=:red, label="class 1", widen=false) +scatter!(X[y_train.==+1, 1], X[y_train.==+1, 2]; color=:blue, label="class 2", widen=false) From a64d1eb4054a0d7ab0ca3adece47d95bb9784d7c Mon Sep 17 00:00:00 2001 From: st-- Date: Tue, 11 Jan 2022 15:27:27 +0100 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- examples/support-vector-machine/script.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/support-vector-machine/script.jl b/examples/support-vector-machine/script.jl index 97202b72a..7de11ac47 100644 --- a/examples/support-vector-machine/script.jl +++ b/examples/support-vector-machine/script.jl @@ -44,7 +44,11 @@ model = svmtrain(kernelmatrix(k, x_train), y_train; kernel=LIBSVM.Kernel.Precomp y_pred, _ = svmpredict(model, kernelmatrix(k, x_train, x_test)); # Compute prediction on a grid: -plot(lim=extrema(test_range)) +plot(; lim=extrema(test_range)) contourf!(test_range, test_range, y_pred; levels=1, color=cgrad(:redsblues), alpha=0.7) -scatter!(X[y_train.==-1, 1], X[y_train.==-1, 2]; color=:red, label="class 1", widen=false) -scatter!(X[y_train.==+1, 1], X[y_train.==+1, 2]; color=:blue, label="class 2", widen=false) +scatter!( + X[y_train .== -1, 1], X[y_train .== -1, 2]; color=:red, label="class 1", widen=false +) +scatter!( + X[y_train .== +1, 1], X[y_train .== +1, 2]; color=:blue, label="class 2", widen=false +) From b69e8e11d7ce2dbc6580e2542da1334251e7f462 Mon Sep 17 00:00:00 2001 From: ST John Date: Tue, 11 Jan 2022 16:50:27 +0200 Subject: [PATCH 3/3] improve writing --- examples/support-vector-machine/script.jl | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/support-vector-machine/script.jl b/examples/support-vector-machine/script.jl index 7de11ac47..4c3861e86 100644 --- a/examples/support-vector-machine/script.jl +++ b/examples/support-vector-machine/script.jl @@ -1,5 +1,8 @@ # # Support Vector Machine # +# In this notebook we show how you can use KernelFunctions.jl to generate +# kernel matrices for classification with a support vector machine, as +# implemented by LIBSVM. using Distributions using KernelFunctions @@ -16,21 +19,23 @@ Random.seed!(1234); # Number of samples per class: nin = nout = 50; -# Generate data -## based on SciKit-Learn's sklearn.datasets.make_moons function +# We generate data based on SciKit-Learn's sklearn.datasets.make_moons function: + class1x = cos.(range(0, π; length=nout)) class1y = sin.(range(0, π; length=nout)) class2x = 1 .- cos.(range(0, π; length=nin)) class2y = 1 .- sin.(range(0, π; length=nin)) .- 0.5 X = hcat(vcat(class1x, class2x), vcat(class1y, class2y)) X .+= 0.1randn(size(X)) -x_train = RowVecs(X); +x_train = RowVecs(X) y_train = vcat(fill(-1, nout), fill(1, nin)); # Create a 100×100 2D grid for evaluation: test_range = range(floor(Int, minimum(X)), ceil(Int, maximum(X)); length=100) x_test = ColVecs(mapreduce(collect, hcat, Iterators.product(test_range, test_range))); +# ## SVM model +# # Create kernel function: k = SqExponentialKernel() ∘ ScaleTransform(1.5) @@ -43,12 +48,8 @@ model = svmtrain(kernelmatrix(k, x_train), y_train; kernel=LIBSVM.Kernel.Precomp # Precomputed matrix for prediction y_pred, _ = svmpredict(model, kernelmatrix(k, x_train, x_test)); -# Compute prediction on a grid: -plot(; lim=extrema(test_range)) +# Visualize prediction on a grid: +plot(; lim=extrema(test_range), aspect_ratio=1) contourf!(test_range, test_range, y_pred; levels=1, color=cgrad(:redsblues), alpha=0.7) -scatter!( - X[y_train .== -1, 1], X[y_train .== -1, 2]; color=:red, label="class 1", widen=false -) -scatter!( - X[y_train .== +1, 1], X[y_train .== +1, 2]; color=:blue, label="class 2", widen=false -) +scatter!(X[y_train .== -1, 1], X[y_train .== -1, 2]; color=:red, label="class 1") +scatter!(X[y_train .== +1, 1], X[y_train .== +1, 2]; color=:blue, label="class 2")