From 005eaf49dcb45f7add7f62fecdac0f3354054767 Mon Sep 17 00:00:00 2001 From: Sebastian Flassbeck Date: Mon, 1 Apr 2024 15:24:50 -0400 Subject: [PATCH 1/5] update interface of proxLLROverlapping! --- src/proximalMaps/ProxLLR.jl | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/proximalMaps/ProxLLR.jl b/src/proximalMaps/ProxLLR.jl index f65815ef..2d666e77 100644 --- a/src/proximalMaps/ProxLLR.jl +++ b/src/proximalMaps/ProxLLR.jl @@ -153,22 +153,11 @@ end """ -proxLLROverlapping!(x::Vector{T}, λ=1e-6; kargs...) where T +proxLLROverlapping!(reg::LLRRegularization, x, λ) -proximal map for LLR regularization with fully overlapping blocks - -# Arguments -* `x::Vector{T}` - Vector to apply proximal map to -* `λ` - regularization parameter -* `shape::Tuple{Int}=[]` - dimensions of the image -* `blockSize::NTuple{Int}=ntuple(_ -> 2, N)` - size of patches to perform singular value thresholding on +performs the proximal map for LLR regularization using singular-value-thresholding with fully overlapping blocks """ -function proxLLROverlapping!( - x::Vector{T}, - λ; - shape::NTuple{N,TI}, - blockSize::NTuple{N,TI} = ntuple(_ -> 2, N), - ) where {T,N,TI<:Integer} +function proxLLROverlapping!(reg::LLRRegularization{TR, N, TI}, x::AbstractArray{Tc}, λ::T) where {TR, N, TI, T, Tc <: Union{T, Complex{T}}} x = reshape(x, tuple(shape..., length(x) ÷ prod(shape))) @@ -178,7 +167,7 @@ function proxLLROverlapping!( ext = mod.(shape, blockSize) pad = mod.(blockSize .- ext, blockSize) if any(pad .!= 0) - xp = zeros(T, (shape .+ pad)..., K) + xp = zeros(Tc, (shape .+ pad)..., K) xp[CartesianIndices(x)] .= x else xp = copy(x) @@ -189,7 +178,7 @@ function proxLLROverlapping!( bthreads = BLAS.get_num_threads() try BLAS.set_num_threads(1) - xᴸᴸᴿ = [Array{T}(undef, prod(blockSize), K) for _ = 1:Threads.nthreads()] + xᴸᴸᴿ = [Array{Tc}(undef, prod(blockSize), K) for _ = 1:Threads.nthreads()] for is ∈ block_idx shift_idx = (Tuple(is)..., 0) xs = circshift(xp, shift_idx) From ed2a13283c73cb4f00ba0b4ccd97b6bcd6f931ae Mon Sep 17 00:00:00 2001 From: Sebastian Flassbeck Date: Mon, 1 Apr 2024 16:53:52 -0400 Subject: [PATCH 2/5] added prox! wrapper function to allow the use of fully overlapping blocks again. --- src/proximalMaps/ProxLLR.jl | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/proximalMaps/ProxLLR.jl b/src/proximalMaps/ProxLLR.jl index 2d666e77..abb5f25c 100644 --- a/src/proximalMaps/ProxLLR.jl +++ b/src/proximalMaps/ProxLLR.jl @@ -9,26 +9,37 @@ Regularization term implementing the proximal map for locally low rank (LLR) reg * `λ` - regularization paramter # Keywords -* `shape::Tuple{Int}=[]` - dimensions of the image -* `blockSize::Tuple{Int}=[2;2]` - size of patches to perform singular value thresholding on -* `randshift::Bool=true` - randomly shifts the patches to ensure translation invariance +* `shape::Tuple{Int}=[]` - dimensions of the image +* `blockSize::Tuple{Int}=[2;2]` - size of patches to perform singular value thresholding on +* `randshift::Bool=true` - randomly shifts the patches to ensure translation invariance +* `fullyOverlapping::Bool=false` - choose between fully overlapping block or non-overlapping blocks """ struct LLRRegularization{T, N, TI} <: AbstractParameterizedRegularization{T} where {N, TI<:Integer} λ::T shape::NTuple{N,TI} blockSize::NTuple{N,TI} randshift::Bool + fullyOverlapping::Bool L::Int64 end -LLRRegularization(λ; shape::NTuple{N,TI}, blockSize::NTuple{N,TI} = ntuple(_ -> 2, N), randshift::Bool = true, L::Int64 = 1, kargs...) where {N,TI<:Integer} = +LLRRegularization(λ; shape::NTuple{N,TI}, blockSize::NTuple{N,TI} = ntuple(_ -> 2, N), randshift::Bool = true, fullyOverlapping::Bool = false, L::Int64 = 1, kargs...) where {N,TI<:Integer} = LLRRegularization(λ, shape, blockSize, randshift, L) """ prox!(reg::LLRRegularization, x, λ) -performs the proximal map for LLR regularization using singular-value-thresholding +wrapper function allowing the use of both non overlapping and fully overlapping blocks """ function prox!(reg::LLRRegularization{TR, N, TI}, x::AbstractArray{Tc}, λ::T) where {TR, N, TI, T, Tc <: Union{T, Complex{T}}} + reg.fullyOverlapping ? proxLLROverlapping!(reg,x) : proxLLRNonOverlapping!(reg,x) +end + +""" + proxLLRNonOverlapping!(reg::LLRRegularization, x, λ) + +performs the proximal map for LLR regularization using singular-value-thresholding +""" +function proxLLRNonOverlapping!(reg::LLRRegularization{TR, N, TI}, x::AbstractArray{Tc}, λ::T) where {TR, N, TI, T, Tc <: Union{T, Complex{T}}} shape = reg.shape blockSize = reg.blockSize randshift = reg.randshift From c0034deb12f17af6bf757933269b746c616263de Mon Sep 17 00:00:00 2001 From: Sebastian Flassbeck Date: Wed, 3 Apr 2024 16:32:34 -0400 Subject: [PATCH 3/5] small bug fixes --- src/proximalMaps/ProxLLR.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/proximalMaps/ProxLLR.jl b/src/proximalMaps/ProxLLR.jl index abb5f25c..4e3dc49f 100644 --- a/src/proximalMaps/ProxLLR.jl +++ b/src/proximalMaps/ProxLLR.jl @@ -9,8 +9,8 @@ Regularization term implementing the proximal map for locally low rank (LLR) reg * `λ` - regularization paramter # Keywords -* `shape::Tuple{Int}=[]` - dimensions of the image -* `blockSize::Tuple{Int}=[2;2]` - size of patches to perform singular value thresholding on +* `shape::Tuple{Int}` - dimensions of the image +* `blockSize::Tuple{Int}=(2,2)` - size of patches to perform singular value thresholding on * `randshift::Bool=true` - randomly shifts the patches to ensure translation invariance * `fullyOverlapping::Bool=false` - choose between fully overlapping block or non-overlapping blocks """ @@ -23,21 +23,21 @@ struct LLRRegularization{T, N, TI} <: AbstractParameterizedRegularization{T} whe L::Int64 end LLRRegularization(λ; shape::NTuple{N,TI}, blockSize::NTuple{N,TI} = ntuple(_ -> 2, N), randshift::Bool = true, fullyOverlapping::Bool = false, L::Int64 = 1, kargs...) where {N,TI<:Integer} = - LLRRegularization(λ, shape, blockSize, randshift, L) + LLRRegularization(λ, shape, blockSize, randshift, fullyOverlapping, L) """ prox!(reg::LLRRegularization, x, λ) -wrapper function allowing the use of both non overlapping and fully overlapping blocks +performs the proximal map for LLR regularization using singular-value-thresholding """ function prox!(reg::LLRRegularization{TR, N, TI}, x::AbstractArray{Tc}, λ::T) where {TR, N, TI, T, Tc <: Union{T, Complex{T}}} - reg.fullyOverlapping ? proxLLROverlapping!(reg,x) : proxLLRNonOverlapping!(reg,x) + reg.fullyOverlapping ? proxLLROverlapping!(reg, x, λ) : proxLLRNonOverlapping!(reg, x, λ) end """ proxLLRNonOverlapping!(reg::LLRRegularization, x, λ) -performs the proximal map for LLR regularization using singular-value-thresholding +performs the proximal map for LLR regularization using singular-value-thresholding on non-overlapping blocks """ function proxLLRNonOverlapping!(reg::LLRRegularization{TR, N, TI}, x::AbstractArray{Tc}, λ::T) where {TR, N, TI, T, Tc <: Union{T, Complex{T}}} shape = reg.shape @@ -169,7 +169,9 @@ proxLLROverlapping!(reg::LLRRegularization, x, λ) performs the proximal map for LLR regularization using singular-value-thresholding with fully overlapping blocks """ function proxLLROverlapping!(reg::LLRRegularization{TR, N, TI}, x::AbstractArray{Tc}, λ::T) where {TR, N, TI, T, Tc <: Union{T, Complex{T}}} - + shape = reg.shape + blockSize = reg.blockSize + x = reshape(x, tuple(shape..., length(x) ÷ prod(shape))) block_idx = CartesianIndices(blockSize) From 691813d7ccc9673936627913c40b6d493c5cc4d2 Mon Sep 17 00:00:00 2001 From: Sebastian Flassbeck Date: Wed, 3 Apr 2024 17:26:12 -0400 Subject: [PATCH 4/5] changed the implementation of fully overlapping blocks. It now calls the non-overlapping function to avoid having a lot of repeated code. --- src/proximalMaps/ProxLLR.jl | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/proximalMaps/ProxLLR.jl b/src/proximalMaps/ProxLLR.jl index 4e3dc49f..b4c8e938 100644 --- a/src/proximalMaps/ProxLLR.jl +++ b/src/proximalMaps/ProxLLR.jl @@ -101,7 +101,7 @@ end """ norm(reg::LLRRegularization, x, λ) -returns the value of the LLR-regularization term. +returns the value of the LLR-regularization term. The norm is only implemented for 2D, non-fully overlapping blocks. """ function norm(reg::LLRRegularization, x::Vector{Tc}, λ::T) where {T, Tc <: Union{T, Complex{T}}} shape = reg.shape @@ -191,23 +191,10 @@ function proxLLROverlapping!(reg::LLRRegularization{TR, N, TI}, x::AbstractArray bthreads = BLAS.get_num_threads() try BLAS.set_num_threads(1) - xᴸᴸᴿ = [Array{Tc}(undef, prod(blockSize), K) for _ = 1:Threads.nthreads()] for is ∈ block_idx shift_idx = (Tuple(is)..., 0) xs = circshift(xp, shift_idx) - - @floop for i ∈ CartesianIndices(StepRange.(TI(0), blockSize, shape .- 1)) - @views xᴸᴸᴿ[Threads.threadid()] .= reshape(xs[i.+block_idx, :], :, K) - - ub = sqrt(norm(xᴸᴸᴿ[Threads.threadid()]' * xᴸᴸᴿ[Threads.threadid()], Inf)) #upper bound on singular values given by matrix infinity norm - if λ >= ub #save time by skipping the SVT as recommended by Ong/Lustig, IEEE 2016 - xs[i.+block_idx, :] .= 0 - else # threshold singular values - SVDec = svd!(xᴸᴸᴿ[Threads.threadid()]) - prox!(L1Regularization, SVDec.S, λ) - xs[i.+block_idx, :] .= reshape(SVDec.U * Diagonal(SVDec.S) * SVDec.Vt, blockSize..., :) - end - end + proxLLRNonOverlapping!(reg, xs, λ) x .+= circshift(xs, -1 .* shift_idx)[CartesianIndices(x)] end finally From 62ebc1eb5c767133853bbde0ac90758aee9633e4 Mon Sep 17 00:00:00 2001 From: SebastianFlassbeck <79124869+SebastianFlassbeck@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:43:09 -0400 Subject: [PATCH 5/5] fix indent --- src/proximalMaps/ProxLLR.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proximalMaps/ProxLLR.jl b/src/proximalMaps/ProxLLR.jl index b4c8e938..3092a43f 100644 --- a/src/proximalMaps/ProxLLR.jl +++ b/src/proximalMaps/ProxLLR.jl @@ -9,7 +9,7 @@ Regularization term implementing the proximal map for locally low rank (LLR) reg * `λ` - regularization paramter # Keywords -* `shape::Tuple{Int}` - dimensions of the image +* `shape::Tuple{Int}` - dimensions of the image * `blockSize::Tuple{Int}=(2,2)` - size of patches to perform singular value thresholding on * `randshift::Bool=true` - randomly shifts the patches to ensure translation invariance * `fullyOverlapping::Bool=false` - choose between fully overlapping block or non-overlapping blocks