@@ -7,14 +7,15 @@ mutable struct BregmanParams
7
7
maxIter
8
8
store_trace
9
9
antichatter
10
- quantile
11
10
alpha
12
11
spg
12
+ TD
13
+ λfunc
13
14
end
14
15
15
16
"""
16
- bregman_options(;verbose=1, optTol=1e-6, progTol=1e-8, maxIter=20
17
- store_trace=false, linesearch=false , alpha=.25, spg=false)
17
+ bregman_options(;verbose=1, optTol=1e-6, progTol=1e-8, maxIter=20,
18
+ store_trace=false, quantile=.5 , alpha=.25, spg=false)
18
19
19
20
Options structure for the bregman iteration algorithm
20
21
@@ -25,69 +26,87 @@ Options structure for the bregman iteration algorithm
25
26
- `maxIter`: maximum number of iterations (default: 20)
26
27
- `store_trace`: Whether to store the trace/history of x (default: false)
27
28
- `antichatter`: Whether to use anti-chatter step length correction
28
- - `quantile`: Thresholding level as quantile value, (default=.95 i.e thresholds 95% of the vector)
29
29
- `alpha`: Strong convexity modulus. (step length is ``α \\ frac{||r||_2^2}{||g||_2^2}``)
30
+ - `spg`: whether to use spg, default is false
31
+ - `TD`: sparsifying transform (e.g. curvelet), default is identity (LinearAlgebra.I)
32
+ - `λfunc`: a function to calculate threshold value, default is nothing
33
+ - `λ`: a pre-set threshold, will only be used if `λfunc` is not defined, default is nothing
34
+ - `quantile`: a percentage to calculate the threshold by quantile of the dual variable in 1st iteration, will only be used if neither `λfunc` nor `λ` are defined, default is .95 i.e thresholds 95% of the vector
30
35
31
36
"""
32
- bregman_options (;verbose= 1 , progTol= 1e-8 , maxIter= 20 , store_trace= false , antichatter= true , quantile= .95 , alpha= .5 , spg= false ) =
33
- BregmanParams (verbose, progTol, maxIter, store_trace, antichatter, quantile, alpha, spg)
37
+ function bregman_options (;verbose= 1 , progTol= 1e-8 , maxIter= 20 , store_trace= false , antichatter= true , alpha= .5 , spg= false , TD= LinearAlgebra. I, quantile= .95 , λ= nothing , λfunc= nothing )
38
+ if isnothing (λfunc)
39
+ if ~ isnothing (λ)
40
+ λfunc = z-> λ
41
+ else
42
+ λfunc = z-> Statistics. quantile (abs .(z), quantile)
43
+ end
44
+ end
45
+ return BregmanParams (verbose, progTol, maxIter, store_trace, antichatter, alpha, spg, TD, λfunc)
46
+ end
34
47
35
48
"""
36
- bregman(A, TD, x, b, options)
49
+ bregman(A, x, b, options)
37
50
38
51
Linearized bregman iteration for the system
39
52
40
53
``\\ frac{1}{2} ||TD \\ x||_2^2 + λ ||TD \\ x||_1 \\ \\ \\ s.t Ax = b``
41
54
42
55
For example, for sparsity promoting denoising (i.e LSRTM)
43
56
44
- # Arguments
57
+ # Required arguments
45
58
46
- - `TD`: curvelet transform
47
- - `A`: Forward operator (J or preconditioned J for LSRTM)
48
- - `b`: observed data
59
+ - `A`: Forward operator (e.g. J or preconditioned J for LSRTM)
49
60
- `x`: Initial guess
61
+ - `b`: observed data
62
+
63
+ # Non-required arguments
64
+
65
+ - `options`: bregman options, default is bregman_options(); options.TD provides the sparsifying transform (e.g. curvelet)
50
66
"""
51
- function bregman (A, TD, x:: Array{T } , b, options) where {T }
67
+ function bregman (A, x:: AbstractVector{T1 } , b:: AbstractVector{T2} , options:: BregmanParams = bregman_options ()) where {T1 <: Number , T2 <: Number }
52
68
# residual function wrapper
53
69
function obj (x)
54
70
d = A* x
55
71
fun = .5 * norm (d - b)^ 2
56
72
grad = A' * (d - b)
57
73
return fun, grad
58
74
end
59
-
60
- return bregman (obj, x, options, TD)
75
+ return bregman (obj, x, options)
76
+ end
77
+
78
+ function bregman (A, TD, x:: AbstractVector{T1} , b:: AbstractVector{T2} , options:: BregmanParams = bregman_options ()) where {T1<: Number , T2<: Number }
79
+ @warn " deprecation warning: please put TD in options (BregmanParams) for version > 0.1.7; now overwritting TD in BregmanParams"
80
+ options. TD = TD
81
+ return bregman (A, x, b, options)
61
82
end
62
83
63
84
"""
64
- bregman(fun, TD, x, b , options)
85
+ bregman(funobj, x , options)
65
86
66
87
Linearized bregman iteration for the system
67
88
68
89
``\\ frac{1}{2} ||TD \\ x||_2^2 + λ ||TD \\ x||_1 \\ \\ \\ s.t Ax = b``
69
90
70
- For example, for sparsity promoting denoising (i.e LSRTM)
91
+ # Required arguments
71
92
72
- # Arguments
73
-
74
- - `TD`: curvelet transform
75
- - `fun`: residual function, return the tuple (``f = \\ frac{1}{2}||Ax - b||_2``, ``g = A^T(Ax - b)``)
76
- - `b`: observed data
93
+ - `funobj`: a function that calculates the objective value (`0.5 * norm(Ax-b)^2`) and the gradient (`A'(Ax-b)`)
77
94
- `x`: Initial guess
78
95
96
+ # Non-required arguments
97
+
98
+ - `options`: bregman options, default is bregman_options(); options.TD provides the sparsifying transform (e.g. curvelet)
79
99
"""
80
- function bregman (funobj:: Function , x:: AbstractArray {T} , options:: BregmanParams , TD = nothing ) where {T}
100
+ function bregman (funobj:: Function , x:: AbstractVector {T} , options:: BregmanParams = bregman_options () ) where {T}
81
101
# Output Parameter Settings
82
102
if options. verbose > 0
83
103
@printf (" Running linearized bregman...\n " );
84
104
@printf (" Progress tolerance: %.2e\n " ,options. progTol)
85
105
@printf (" Maximum number of iterations: %d\n " ,options. maxIter)
86
106
@printf (" Anti-chatter correction: %d\n " ,options. antichatter)
87
107
end
88
- isnothing (TD) && (TD = LinearAlgebra. I)
89
- # Intitalize variables
90
- z = TD* x
108
+ # Initialize variables
109
+ z = options. TD* x
91
110
d = similar (z)
92
111
options. spg && (gold = similar (x); xold= similar (x))
93
112
if options. antichatter
@@ -96,8 +115,6 @@ function bregman(funobj::Function, x::AbstractArray{T}, options::BregmanParams,
96
115
97
116
# Result structure
98
117
sol = breglog (x, z)
99
- # Initialize λ
100
- λ = abs (T (0 ))
101
118
102
119
# Output Log
103
120
if options. verbose > 0
@@ -108,60 +125,45 @@ function bregman(funobj::Function, x::AbstractArray{T}, options::BregmanParams,
108
125
for i= 1 : options. maxIter
109
126
f, g = funobj (x)
110
127
# Preconditionned ipdate direction
111
- d .= - TD* g
128
+ d .= - options . TD* g
112
129
# Step length
113
130
t = (options. spg && i> 1 ) ? T (dot (x- xold, x- xold)/ dot (x- xold, g- gold)) : T (options. alpha* f/ norm (d)^ 2 )
114
131
t = abs (t)
115
132
mul! (d, d, t)
116
133
117
134
# Anti-chatter
118
135
if options. antichatter
136
+ @assert isreal (z) " we currently do not support anti-chatter for complex numbers"
119
137
@. tk = tk - sign (d)
120
- # Chatter correction
121
- inds_z = findall (abs .(z) .> λ)
122
- @views d[inds_z] .*= abs .(tk[inds_z])/ i
138
+ # Chatter correction after 1st iteration
139
+ if i > 1
140
+ inds_z = findall (abs .(z) .> sol. λ)
141
+ @views d[inds_z] .*= abs .(tk[inds_z])/ i
142
+ end
123
143
end
124
144
# Update z variable
125
145
@. z = z + d
126
146
# Get λ at first iteration
127
- i == 1 && (λ = abs ( T ( quantile ( abs .(z), options. quantile ))))
147
+ ( i == 1 ) && (sol . λ = abs .( T .( options. λfunc (z ))))
128
148
# Save curent state
129
149
options. spg && (gold .= g; xold .= x)
130
150
# Update x
131
- x = TD' * soft_thresholding (z, λ)
151
+ x = options . TD' * soft_thresholding (z, sol . λ)
132
152
133
- obj_fun = λ * norm (z, 1 ) + .5 * norm (z, 2 )^ 2
134
- if options. verbose > 0
135
- @printf (" %10d %15.5e %15.5e %15.5e %15.5e \n " ,i, t, obj_fun, f, λ)
136
- end
153
+ obj_fun = norm (sol. λ .* z, 1 ) + .5 * norm (z, 2 )^ 2
154
+ (options. verbose > 0 ) && (@printf (" %10d %15.5e %15.5e %15.5e %15.5e \n " ,i, t, obj_fun, f, maximum (sol. λ)))
137
155
norm (x - sol. x) < options. progTol && (@printf (" Step size below progTol\n " ); break ;)
138
156
update! (sol; iter= i, ϕ= obj_fun, residual= f, x= x, z= z, g= g, store_trace= options. store_trace)
139
157
end
140
158
return sol
141
159
end
142
160
143
- # Utility functions
144
- """
145
- Simplified Quantile from Statistics.jl since we only need simplified version of it.
146
- """
147
- function quantile (u:: AbstractVector , p:: Real )
148
- 0 <= p <= 1 || throw (ArgumentError (" input probability out of [0,1] range" ))
149
- n = length (u)
150
- v = sort (u; alg= Base. QuickSort)
151
-
152
- m = 1 - p
153
- aleph = n* p + oftype (p, m)
154
- j = clamp (trunc (Int, aleph), 1 , n- 1 )
155
- γ = clamp (aleph - j, 0 , 1 )
156
-
157
- n == 1 ? a = v[1 ] : a = v[j]
158
- n == 1 ? b = v[1 ] : b = v[j+ 1 ]
159
-
160
- (isfinite (a) && isfinite (b)) ? q = a + γ* (b- a) : q = (1 - γ)* a + γ* b
161
- return q
161
+ function bregman (funobj:: Function , x:: AbstractVector{T} , options:: BregmanParams , TD) where {T}
162
+ @warn " deprecation warning: please put TD in options (BregmanParams) for version > 0.1.7; now overwritting TD in BregmanParams"
163
+ options. TD = TD
164
+ return bregman (funobj, x, options)
162
165
end
163
166
164
-
165
167
"""
166
168
Bregman result structure
167
169
"""
@@ -170,6 +172,7 @@ mutable struct BregmanIterations
170
172
z
171
173
g
172
174
ϕ
175
+ λ
173
176
residual
174
177
ϕ_trace
175
178
r_trace
@@ -189,6 +192,6 @@ function update!(r::BregmanIterations; x=nothing, z=nothing, ϕ=nothing, residua
189
192
(~ isnothing (residual) && length (r. r_trace) == iter- 1 ) && (push! (r. r_trace, residual))
190
193
end
191
194
192
- function breglog (init_x, init_z; f0= 0 , obj0= 0 )
193
- return BregmanIterations (1 * init_x, 1 * init_z, 0 * init_z, f0, obj0, Vector {} (), Vector {} (), Vector {} (), Vector {} ())
194
- end
195
+ function breglog (init_x, init_z; lambda0 = 0 , f0= 0 , obj0= 0 )
196
+ return BregmanIterations (1 * init_x, 1 * init_z, 0 * init_z, f0, lambda0, obj0, Vector {} (), Vector {} (), Vector {} (), Vector {} ())
197
+ end
0 commit comments