diff --git a/examples/support-vector-machine/script.jl b/examples/support-vector-machine/script.jl index f2824d4d4..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 @@ -8,39 +11,45 @@ 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 + +# Number of samples per class: +nin = nout = 50; -# Select randomly between two classes: -y_train = rand([-1, 1], N); +# We generate data based on SciKit-Learn's sklearn.datasets.make_moons function: -# 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); +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))); +# ## SVM model +# # 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) +# 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") +scatter!(X[y_train .== +1, 1], X[y_train .== +1, 2]; color=:blue, label="class 2")