Skip to content

Commit

Permalink
delete renormalizaton for geometric harmonics
Browse files Browse the repository at this point in the history
  • Loading branch information
HaneWall committed Jun 2, 2024
1 parent 7e3597f commit d7808df
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 35 deletions.
14 changes: 7 additions & 7 deletions examples/scurve_geometric_harmonics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using Manyfold, Random, MLJ, GMT
rng = MersenneTwister(1)

ε_1 = 0.4
ε_2 = 0.8
ε_2 = 0.05

kernel_dmap = GaussianKernel(ε_1)
kernel_GH = GaussianKernel(ε_2)
Expand All @@ -22,12 +22,12 @@ rng_common = 123
X_train, X_test = partition(X', 0.2, rng=rng_common)

ψ_train_col = transpose(ψ_train)
# ψ_test_col = transpose(ψ_test) .* [1.1, 1]
ψ_test_col_bound = [1.1, 1] .* transpose(Matrix(GMT.concavehull(ψ_test, 0.05)))
ψ_test_col = transpose(ψ_test)
# ψ_test_col_bound = [1.01, 1] .* transpose(Matrix(GMT.concavehull(ψ_test, 0.05)))

test = 0.22 * ones(Float64, 2, 100)
test[2, :] = collect(range(-0.1, 0.1, length=100))
geom_all = fit(GeometricHarmonics, ψ_train_col, X_train, kernel_GH; d=100, α=0.0, alg=:eigen)
# test = 0.22 * ones(Float64, 2, 100)
# test[2, :] = collect(range(-0.1, 0.1, length=100))
geom_all = fit(GeometricHarmonics, ψ_train_col, X_train, kernel_GH; d=500, alg=:eigen)

X_pred_all = Manyfold.predict(geom_all, ψ_test_col_bound)
X_pred_all = Manyfold.predict(geom_all, ψ_train_col)

12 changes: 6 additions & 6 deletions examples/swiss_roll_geometric_harmonics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using Manyfold, Random, MLJ
rng = MersenneTwister(1)

ε_1 = 1.5
ε_2 = 0.2
ε_2 = 0.1


kernel_dmap = GaussianKernel(ε_1)
Expand All @@ -14,20 +14,20 @@ n = 13000
noise = 0.03
X, X_label = swiss_roll(n, noise; segments=n, rng=rng)

dmap = fit(DiffusionMap, X, kernel_dmap; α=1.0, d=10, alg=:kry_eigen, conj=true)
dmap = fit(DiffusionMap, X, kernel_dmap; α=1.0, d=16, alg=:kry_eigen, conj=true)
# we can see by eyes for now, that the coordinates 1 and 5 are the non-harmonic ones
ψ_embedding = copy(dmap.Map[:, [1, 5]])


rng_common = 123
ψ_train, ψ_test = partition(ψ_embedding, 0.3, rng=rng_common)
X_train, X_test = partition(X', 0.3, rng=rng_common)
ψ_train, ψ_test = partition(ψ_embedding, 0.15, rng=rng_common)
X_train, X_test = partition(X', 0.15, rng=rng_common)

ψ_train_col = transpose(ψ_train)
ψ_test_col = transpose(ψ_test) .* [1.08, 1.0]
ψ_test_col = transpose(ψ_test)


geom_all = fit(GeometricHarmonics, ψ_train_col, X_train, kernel_GH; d=50, α=1.0, alg=:eigen)
geom_all = fit(GeometricHarmonics, ψ_train_col, X_train, kernel_GH; d=61, alg=:eigen)


X_pred_all = Manyfold.predict(geom_all, ψ_test_col)
44 changes: 22 additions & 22 deletions src/GeometricHarmonics.jl
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
"""
GeometricHarmonics{T<:Real}
Is an object that allows us jump between the ambient space and latent space.
From the "restriction" standpoint this is an alternative to the natural
struct GeometricHarmonics{T<:Real}
Is an object that allows us to jump between the ambient and latent space.
From the "restriction" standpoint this is an alternative to the natural
Nyström extension. From the "lifting" standpoint this is an alternative
to k-nearest neighbors.
to the k-nearest neighbors approach.
We do not care about the direction here (restriction or lifting)!
In later prediction processes we always map the following way:
GH: X-->Y.
GH: F_1^(D_1 × N) --> F_2(D_2 × N), X_train |-> Y_train
(N-samples are column wise)
Generally speaking GeometricHarmonics were introduced by Coifman himself.
[https://doi.org/10.1016/j.acha.2005.07.005]
Over the years many adaptations arised and nowadays GeometricHarmonics can also
be used to lift from the embedded latent space to the high dimensional ambient space
via so-called Latent Harmonics (double diffusion Map).
via so-called Latent Harmonics (double diffusion Map)
[https://doi.org/10.1016/j.jcp.2023.112072]
d ... dimensions of the eigenspace (usually one has to take into account many)
α ... renormalization parameter ∈ [0, 1]
X_train ... training data from the domain
Y_train ... training data of the image(X_train)
k ... kernel function that is used to create kernelmatrices
Expand All @@ -25,7 +28,6 @@ Map ... Y_train map projections on GeometricHarmonics
"""
struct GeometricHarmonics{T<:Real}
d::Integer
α::T
X_train::AbstractMatrix{T}
Y_train::AbstractMatrix{T}
k::Kernel
Expand All @@ -40,47 +42,45 @@ end
"""
fit()
Fits a GeometricHarmonics model to interpolate a map from X_train data space to Y_target data space.
Fits a GeometricHarmonics model to interpolate a map from X_train data space to Y_train data space.
This approach does not really care about the dimensions and can be used for Lifting and Restriction.
However one should be careful at comparing the restriction to Nyström, since we only restrict to
the choosen embedding but not all eigenfunctions of the diffusion map.
"""
function fit(::Type{GeometricHarmonics}, X_train::AbstractMatrix{T}, Y_train::AbstractMatrix{T}, kernel::S;
α::Real=1.0, d=10, alg=:eigen) where {S<:Kernel,T<:Real}
d::Integer=10, alg=:eigen) where {S<:Kernel,T<:Real}
K_new = KernelFunctions.kernelmatrix(kernel, ColVecs(X_train))
if !(isapprox(α, 0))
p⁻ᵅ = Diagonal(1.0 ./ (vec(sum(K_new, dims=2)))) .^ (α)
lmul!(p⁻ᵅ, K_new)
normalize_to_right_stochastic!(K_new)
end
#the first eigenvector/value is important in this case
Λs, Vs = decompose(K_new, d; skipfirst=false, alg)
Map = Vs * Λs^(-1) * transpose(Vs) * Y_train
return GeometricHarmonics{T}(d, α, X_train, Y_train, kernel, K_new, Λs, Vs, Map)
return GeometricHarmonics{T}(d, X_train, Y_train, kernel, K_new, Λs, Vs, Map)
end


"""
predict(GH::GeometricHarmonics, X_oos)
Uses the learned GeometricHarmonics model to fit new out of sample data X_oos to predict
on Y living space.
on Y_train living space.
"""
function predict(GH::GeometricHarmonics, X_oos)
K_new = KernelFunctions.kernelmatrix(GH.k, ColVecs(X_oos), ColVecs(GH.X_train))
if !(isapprox(GH.α, 0))
normalize_to_right_stochastic!(K_new)
end
return K_new * GH.Map
end


"""
struct MultiScaleGeometricHarmonics
Introduction of multiscale GeometricHarmonics.
"""
struct MultiScaleGeometricHarmonics{T<:Real}
d::Integer
α::T
X_train::AbstractMatrix{T}
Y_train::AbstractMatrix{T}
error::T
δ::T
k::Kernel
# following quantities will we determined and are not free to choose
d::Integer
K::AbstractMatrix{T}
Λs::AbstractMatrix{T}
Vs::AbstractMatrix{T}
Expand Down

0 comments on commit d7808df

Please sign in to comment.