From daf9dc53a8b2e0a55500bdd014b46a027a4c549c Mon Sep 17 00:00:00 2001 From: Romeo Valentin Date: Fri, 19 Jul 2024 11:59:41 +0200 Subject: [PATCH 1/4] Simplify cache workflow --- .github/workflows/CI.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b360663..60036bd 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,16 +22,7 @@ jobs: - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} - - uses: actions/cache@v3 - env: - cache-name: cache-artifacts - with: - path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} - restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test- - ${{ runner.os }}- + - uses: julia-actions/cache@v2 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 From 71fc5cdb57ef5d57ddd11a3b96077bee50ebd21a Mon Sep 17 00:00:00 2001 From: Romeo Valentin Date: Wed, 17 Jul 2024 11:47:44 +0200 Subject: [PATCH 2/4] Disable some slow paths in sparse coding --- src/matching_pursuit.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/matching_pursuit.jl b/src/matching_pursuit.jl index 2215479..7843e07 100644 --- a/src/matching_pursuit.jl +++ b/src/matching_pursuit.jl @@ -245,8 +245,8 @@ products[t+1] = dictionary' * (residual[t] - dictionary[idx] * a) products_abs = abs.(products) # prealloc for i in 1:max_iter - !isfinite(norm(residual)) && @show norm(residual), residual - !isfinite(norm_data) && @show norm_data + # @assert(norm(residual)) && @show norm(residual), residual + # @assert(isfinite(norm_data)) if norm(residual)/norm_data < rtol return sparsevec(xdict, n_atoms) end @@ -261,7 +261,7 @@ products[t+1] = dictionary' * (residual[t] - dictionary[idx] * a) a = products[maxindex] atom = @view dictionary[:, maxindex] - @assert norm(atom) ≈ 1. norm(atom) + # @assert norm(atom) ≈ 1. norm(atom) residual .-= a .* atom products .-= a .* @view DtD[:, maxindex] From 32c1359b24389b8b3c3442bb02904c4c54f617e2 Mon Sep 17 00:00:00 2001 From: Romeo Valentin Date: Wed, 17 Jul 2024 19:26:51 +0000 Subject: [PATCH 3/4] Enable setting `reltol` and `abstol` to `nothing` We had some strange cases where we "converged" in the norm all the way to zero, but were still making progress in the nnz. --- src/KSVD.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/KSVD.jl b/src/KSVD.jl index 23209af..7e37318 100644 --- a/src/KSVD.jl +++ b/src/KSVD.jl @@ -91,8 +91,8 @@ function ksvd(Y::AbstractMatrix{T}, n_atoms::Int, max_nnz=n_atoms÷10; # termination conditions maxiters::Int=100, #: The maximum number of iterations to perform. Defaults to 100. maxtime::Union{Nothing, <:Real}=nothing,# : The maximum time for solving the nonlinear system of equations. Defaults to nothing which means no time limit. Note that setting a time limit does have a small overhead. - abstol::Number=real(oneunit(T)) * (eps(real(one(T))))^(4 // 5), #: The absolute tolerance. Defaults to real(oneunit(T)) * (eps(real(one(T))))^(1 // 2). - reltol::Number=real(oneunit(T)) * (eps(real(one(T))))^(4 // 5), #: The relative tolerance. Defaults to real(oneunit(T)) * (eps(real(one(T))))^(1 // 2). + abstol::Union{Nothing, <:Real}=real(oneunit(T)) * (eps(real(one(T))))^(4 // 5), #: The absolute tolerance. Defaults to real(oneunit(T)) * (eps(real(one(T))))^(1 // 2). + reltol::Union{Nothing, <:Real}=real(oneunit(T)) * (eps(real(one(T))))^(4 // 5), #: The relative tolerance. Defaults to real(oneunit(T)) * (eps(real(one(T))))^(1 // 2). nnz_per_col_target::Number=0.0, # tracing options show_trace::Bool=false, @@ -152,7 +152,7 @@ function ksvd(Y::AbstractMatrix{T}, n_atoms::Int, max_nnz=n_atoms÷10; termination_condition = :maxiter; break elseif !isnothing(maxtime) && (time() - tic) > maxtime termination_condition = :maxtime; break - elseif length(norm_results) > 1 && isapprox(norm_results[end], norm_results[end-1]; atol=abstol, rtol=reltol) + elseif (!isnothing(abstol) && !isnothing(reltol)) && length(norm_results) > 1 && isapprox(norm_results[end], norm_results[end-1]; atol=abstol, rtol=reltol) termination_condition = :converged; break elseif !isempty(nnz_per_col_results) && last(nnz_per_col_results) <= nnz_per_col_target termination_condition = :nnz_per_col_target; break From 94d43a87354de3ef4ddd93bf30fabc817aab229e Mon Sep 17 00:00:00 2001 From: Romeo Valentin Date: Wed, 17 Jul 2024 19:28:00 +0000 Subject: [PATCH 4/4] Allow passing a `D_init` --- src/KSVD.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/KSVD.jl b/src/KSVD.jl index 7e37318..812238a 100644 --- a/src/KSVD.jl +++ b/src/KSVD.jl @@ -88,6 +88,7 @@ function ksvd(Y::AbstractMatrix{T}, n_atoms::Int, max_nnz=n_atoms÷10; ksvd_update_method = BatchedParallelKSVD{false, T}(; shuffle_indices=true, batch_size_per_thread=1), sparse_coding_method = ParallelMatchingPursuit(; max_nnz, rtol=5e-2), minibatch_size=nothing, + D_init::Union{Nothing, <:AbstractMatrix{T}} = nothing, # termination conditions maxiters::Int=100, #: The maximum number of iterations to perform. Defaults to 100. maxtime::Union{Nothing, <:Real}=nothing,# : The maximum time for solving the nonlinear system of equations. Defaults to nothing which means no time limit. Note that setting a time limit does have a small overhead. @@ -104,7 +105,7 @@ function ksvd(Y::AbstractMatrix{T}, n_atoms::Int, max_nnz=n_atoms÷10; # D is a dictionary matrix that contains atoms for columns. @timeit_debug timer "Init dict" begin - D = init_dictionary(T, emb_dim, n_atoms) # size(D) == (n, K) + D = (isnothing(D_init) ? init_dictionary(T, emb_dim, n_atoms) : D_init) # size(D) == (n, K) @assert all(≈(1.0), norm.(eachcol(D))) end X = sparse_coding(sparse_coding_method, Y, D; timer)