Skip to content

Commit 319a9aa

Browse files
added tests for inits
1 parent e21ea8a commit 319a9aa

File tree

3 files changed

+47
-43
lines changed

3 files changed

+47
-43
lines changed

src/ReservoirComputing.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export StandardStates, ExtendedStates, PaddedStates, PaddedExtendedStates
4040
export StandardRidge
4141
export scaled_rand, weighted_init, informed_init, minimal_init, chebyshev_mapping
4242
export rand_sparse, delay_line, delay_line_backward, cycle_jumps,
43-
simple_cycle, pseudo_svd, chaotic_init
43+
simple_cycle, pseudo_svd, chaotic_init
4444
export RNN, MRNN, GRU, GRUParams, FullyGated, Minimal
4545
export train
4646
export ESN, HybridESN, KnowledgeModel, DeepESN

src/esn/esn_inits.jl

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,7 @@ function _create_irrational(irrational::Irrational, start::Int, res_size::Int,
282282
return T.(input_matrix)
283283
end
284284

285-
286285
"""
287-
288286
chebyshev_mapping([rng], [T], dims...;
289287
amplitude=one(T), sine_divisor=one(T),
290288
chebyshev_parameter=one(T), return_sparse=true)
@@ -297,21 +295,24 @@ via the Chebyshev mapping. The first row is defined as:
297295
w(1, j) = amplitude * sin(j * π / (sine_divisor * n_cols))
298296
```
299297
300-
for j = 1, 2, …, n_cols (with n_cols typically equal to K+1, where K is the number of input layer neurons).
298+
for j = 1, 2, …, n_cols (with n_cols typically equal to K+1, where K is the number of input layer neurons).
301299
Subsequent rows are generated by applying the mapping:
300+
302301
```math
303302
w(i+1, j) = cos(chebyshev_parameter * acos(w(i, j)))
304303
```
305304
306305
# Arguments
306+
307307
- `rng`: Random number generator. Default is `Utils.default_rng()`
308308
from WeightInitializers.
309309
- `T`: Type of the elements in the reservoir matrix.
310310
Default is `Float32`.
311311
- `dims`: Dimensions of the matrix. Should follow `res_size x in_size`. Here, res_size is assumed to be K+1.
312312
313-
# Keyword arguments
314-
- `amplitude`: Scaling factor used to initialize the first row.
313+
# Keyword arguments
314+
315+
- `amplitude`: Scaling factor used to initialize the first row.
315316
This parameter adjusts the amplitude of the sine function. Default value is one.
316317
- `sine_divisor`: Divisor applied in the sine function's phase. Default value is one.
317318
- `chebyshev_parameter`: Control parameter for the Chebyshev mapping in
@@ -334,7 +335,6 @@ julia> input_matrix = chebyshev_mapping(10, 3)
334335
0.866025 0.866025 -4.37114f-8
335336
0.866025 0.866025 -4.37114f-8
336337
0.866025 0.866025 -4.37114f-8
337-
338338
```
339339
340340
[^xie2024]: Xie, Minzhi, Qianxue Wang, and Simin Yu.
@@ -343,25 +343,25 @@ julia> input_matrix = chebyshev_mapping(10, 3)
343343
Neural Processing Letters 56.1 (2024): 30.
344344
"""
345345
function chebyshev_mapping(rng::AbstractRNG, ::Type{T}, dims::Integer...;
346-
amplitude::AbstractFloat = one(T), sine_divisor::AbstractFloat = one(T),
347-
chebyshev_parameter::AbstractFloat = one(T),
348-
return_sparse::Bool = false) where {T <: Number}
346+
amplitude::AbstractFloat=one(T), sine_divisor::AbstractFloat=one(T),
347+
chebyshev_parameter::AbstractFloat=one(T),
348+
return_sparse::Bool=false) where {T <: Number}
349349
input_matrix = DeviceAgnostic.zeros(rng, T, dims...)
350350
n_rows, n_cols = dims[1], dims[2]
351-
351+
352352
for idx_cols in 1:n_cols
353353
input_matrix[1, idx_cols] = amplitude * sin(idx_cols * pi / (sine_divisor * n_cols))
354354
end
355355
for idx_rows in 2:n_rows
356356
for idx_cols in 1:n_cols
357-
input_matrix[idx_rows, idx_cols] = cos(chebyshev_parameter * acos(input_matrix[idx_rows - 1, idx_cols]))
357+
input_matrix[idx_rows, idx_cols] = cos(chebyshev_parameter * acos(input_matrix[
358+
idx_rows - 1, idx_cols]))
358359
end
359360
end
360361

361362
return return_sparse ? sparse(input_matrix) : input_matrix
362363
end
363364

364-
365365
### reservoirs
366366

367367
"""
@@ -752,22 +752,21 @@ function get_sparsity(M, dim)
752752
return size(M[M .!= 0], 1) / (dim * dim - size(M[M .!= 0], 1)) #nonzero/zero elements
753753
end
754754

755-
756755
function digital_chaotic_adjacency(rng::AbstractRNG, bit_precision::Integer;
757-
extra_edge_probability::AbstractFloat = 0.1)
758-
matrix_order = 2^(2 * bit_precision)
759-
adjacency_matrix = zeros(Int, matrix_order, matrix_order)
760-
for row_index in 1:(matrix_order - 1)
761-
adjacency_matrix[row_index, row_index + 1] = 1
762-
end
763-
adjacency_matrix[matrix_order, 1] = 1
764-
for row_index in 1:matrix_order, column_index in 1:matrix_order
765-
if row_index != column_index && rand(rng) < extra_edge_probability
766-
adjacency_matrix[row_index, column_index] = 1
767-
end
768-
end
769-
770-
return adjacency_matrix
756+
extra_edge_probability::AbstractFloat=0.1)
757+
matrix_order = 2^(2 * bit_precision)
758+
adjacency_matrix = zeros(Int, matrix_order, matrix_order)
759+
for row_index in 1:(matrix_order - 1)
760+
adjacency_matrix[row_index, row_index + 1] = 1
761+
end
762+
adjacency_matrix[matrix_order, 1] = 1
763+
for row_index in 1:matrix_order, column_index in 1:matrix_order
764+
if row_index != column_index && rand(rng) < extra_edge_probability
765+
adjacency_matrix[row_index, column_index] = 1
766+
end
767+
end
768+
769+
return adjacency_matrix
771770
end
772771

773772
"""
@@ -779,17 +778,19 @@ Construct a chaotic reservoir matrix using a digital chaotic system [^xie2024].
779778
780779
The matrix topology is derived from a strongly connected adjacency
781780
matrix based on a digital chaotic system operating at finite precision.
782-
If the requested matrix order does not exactly match a valid order the
781+
If the requested matrix order does not exactly match a valid order the
783782
closest valid order is used.
784783
785784
# Arguments
785+
786786
- `rng`: Random number generator. Default is `Utils.default_rng()`
787787
from WeightInitializers.
788788
- `T`: Type of the elements in the reservoir matrix.
789789
Default is `Float32`.
790790
- `dims`: Dimensions of the reservoir matrix.
791791
792792
# Keyword arguments
793+
793794
- `extra_edge_probability`: Probability of adding extra random edges in
794795
the adjacency matrix to enhance connectivity. Default is 0.1.
795796
- `desired_spectral_radius`: The target spectral radius for the
@@ -812,8 +813,7 @@ julia> res_matrix = chaotic_init(8, 8)
812813
⋅ -0.600945 ⋅ ⋅
813814
⋅ ⋅ 0.132667 2.21354
814815
⋅ -2.60383 ⋅ -2.90391
815-
-0.578156 ⋅ ⋅ ⋅
816-
816+
-0.578156 ⋅ ⋅ ⋅
817817
```
818818
819819
[^xie2024]: Xie, Minzhi, Qianxue Wang, and Simin Yu.
@@ -822,9 +822,8 @@ julia> res_matrix = chaotic_init(8, 8)
822822
Neural Processing Letters 56.1 (2024): 30.
823823
"""
824824
function chaotic_init(rng::AbstractRNG, ::Type{T}, dims::Integer...;
825-
extra_edge_probability::AbstractFloat = T(0.1), spectral_radius::AbstractFloat = one(T),
826-
return_sparse_matrix::Bool = true) where {T <: Number}
827-
825+
extra_edge_probability::AbstractFloat=T(0.1), spectral_radius::AbstractFloat=one(T),
826+
return_sparse_matrix::Bool=true) where {T <: Number}
828827
requested_order = first(dims)
829828
if length(dims) > 1 && dims[2] != requested_order
830829
@warn """\n
@@ -833,10 +832,11 @@ function chaotic_init(rng::AbstractRNG, ::Type{T}, dims::Integer...;
833832
end
834833
d_estimate = log2(requested_order) / 2
835834
d_floor = max(floor(Int, d_estimate), 1)
836-
d_ceil = ceil(Int, d_estimate)
835+
d_ceil = ceil(Int, d_estimate)
837836
candidate_order_floor = 2^(2 * d_floor)
838-
candidate_order_ceil = 2^(2 * d_ceil)
839-
chosen_bit_precision = abs(candidate_order_floor - requested_order) <= abs(candidate_order_ceil - requested_order) ? d_floor : d_ceil
837+
candidate_order_ceil = 2^(2 * d_ceil)
838+
chosen_bit_precision = abs(candidate_order_floor - requested_order) <=
839+
abs(candidate_order_ceil - requested_order) ? d_floor : d_ceil
840840
actual_matrix_order = 2^(2 * chosen_bit_precision)
841841
if actual_matrix_order != requested_order
842842
@warn """\n
@@ -846,8 +846,10 @@ function chaotic_init(rng::AbstractRNG, ::Type{T}, dims::Integer...;
846846
"""
847847
end
848848

849-
random_weight_matrix = T(2) * rand(rng, T, actual_matrix_order, actual_matrix_order) .- T(1)
850-
adjacency_matrix = digital_chaotic_adjacency(rng, chosen_bit_precision; extra_edge_probability = extra_edge_probability)
849+
random_weight_matrix = T(2) * rand(rng, T, actual_matrix_order, actual_matrix_order) .-
850+
T(1)
851+
adjacency_matrix = digital_chaotic_adjacency(
852+
rng, chosen_bit_precision; extra_edge_probability=extra_edge_probability)
851853
reservoir_matrix = random_weight_matrix .* adjacency_matrix
852854
current_spectral_radius = maximum(abs, eigvals(reservoir_matrix))
853855
if current_spectral_radius != 0

test/esn/test_inits.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using ReservoirComputing, LinearAlgebra, Random, SparseArrays
22

3-
const res_size = 30
4-
const in_size = 3
3+
const res_size = 16
4+
const in_size = 4
55
const radius = 1.0
66
const sparsity = 0.1
77
const weight = 0.2
@@ -24,13 +24,15 @@ reservoir_inits = [
2424
delay_line_backward,
2525
cycle_jumps,
2626
simple_cycle,
27-
pseudo_svd
27+
pseudo_svd,
28+
chaotic_init
2829
]
2930
input_inits = [
3031
scaled_rand,
3132
weighted_init,
3233
minimal_init,
33-
minimal_init(; sampling_type=:irrational)
34+
minimal_init(; sampling_type=:irrational),
35+
chebyshev_mapping
3436
]
3537

3638
@testset "Reservoir Initializers" begin

0 commit comments

Comments
 (0)