Skip to content

Commit

Permalink
Merge pull request #231 from SciML/fm/uwi
Browse files Browse the repository at this point in the history
Streamlining inits to WeightInitializers v1
  • Loading branch information
MartinuzziFrancesco authored Dec 31, 2024
2 parents a79dd1a + 126306d commit dcbf85e
Show file tree
Hide file tree
Showing 65 changed files with 105 additions and 94 deletions.
Empty file modified .JuliaFormatter.toml
100644 → 100755
Empty file.
Empty file modified .buildkite/documentation.yml
100644 → 100755
Empty file.
Empty file modified .buildkite/pipeline.yml
100644 → 100755
Empty file.
Empty file modified .github/dependabot.yml
100644 → 100755
Empty file.
Empty file modified .github/workflows/CompatHelper.yml
100644 → 100755
Empty file.
Empty file modified .github/workflows/Downgrade.yml
100644 → 100755
Empty file.
Empty file modified .github/workflows/FormatCheck.yml
100644 → 100755
Empty file.
Empty file modified .github/workflows/Invalidations.yml
100644 → 100755
Empty file.
Empty file modified .github/workflows/TagBot.yml
100644 → 100755
Empty file.
Empty file modified .github/workflows/Tests.yml
100644 → 100755
Empty file.
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified .typos.toml
100644 → 100755
Empty file.
Empty file modified CITATION.bib
100644 → 100755
Empty file.
Empty file modified LICENSE
100644 → 100755
Empty file.
14 changes: 8 additions & 6 deletions Project.toml
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
name = "ReservoirComputing"
uuid = "7c2d2b1e-3dd4-11ea-355a-8f6a8116e294"
authors = ["Francesco Martinuzzi"]
version = "0.10.4"
version = "0.10.5"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
CellularAutomata = "878138dc-5b27-11ea-1a71-cb95d38d6b29"
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
NNlib = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
WeightInitializers = "d49dbf32-c5c2-4618-8acc-27bb2598ef2d"

[weakdeps]
Expand All @@ -30,23 +30,25 @@ Aqua = "0.8"
CellularAutomata = "0.0.2"
DifferentialEquations = "7"
Distances = "0.10"
Distributions = "0.25.36"
LIBSVM = "0.8"
LinearAlgebra = "1.10"
MLJLinearModels = "0.9.2, 0.10"
NNlib = "0.8.4, 0.9"
Optim = "1"
PartialFunctions = "1.2"
Random = "1.10"
Reexport = "1.2.2"
SafeTestsets = "0.1"
Statistics = "1.10"
StatsBase = "0.34.4"
Test = "1"
WeightInitializers = "0.1.6"
WeightInitializers = "1.0.4"
julia = "1.10"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
LIBSVM = "b1bec4e5-fd48-53fe-b0cb-9723c09d164b"
MLJLinearModels = "6ee0df7b-362f-4a72-a706-9e79364fb692"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
6 changes: 0 additions & 6 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
<p align="center">
<img width="400px" src="docs/src/assets/logo.png"/>
</p>

<div align="center">

[![Join the chat at https://julialang.zulipchat.com #sciml-bridged](https://img.shields.io/static/v1?label=Zulip&message=chat&color=9558b2&labelColor=389826)](https://julialang.zulipchat.com/#narrow/stream/279055-sciml-bridged)
[![Global Docs](https://img.shields.io/badge/docs-SciML-blue.svg)](https://docs.sciml.ai/ReservoirComputing/stable/)
[![arXiv](https://img.shields.io/badge/arXiv-2204.05117-00b300.svg)](https://arxiv.org/abs/2204.05117)

[![codecov](https://codecov.io/gh/SciML/ReservoirComputing.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/SciML/ReservoirComputing.jl)
[![Build Status](https://github.com/SciML/ReservoirComputing.jl/workflows/CI/badge.svg)](https://github.com/SciML/ReservoirComputing.jl/actions?query=workflow%3ACI)
[![Build status](https://badge.buildkite.com/db8f91b89a10ad79bbd1d9fdb1340e6f6602a1c0ed9496d4d0.svg)](https://buildkite.com/julialang/reservoircomputing-dot-jl)

[![ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor%27s%20Guide-blueviolet)](https://github.com/SciML/ColPrac)
[![SciML Code Style](https://img.shields.io/static/v1?label=code%20style&message=SciML&color=9558b2&labelColor=389826)](https://github.com/SciML/SciMLStyle)

</div>

# ReservoirComputing.jl
ReservoirComputing.jl provides an efficient, modular and easy to use implementation of Reservoir Computing models such as Echo State Networks (ESNs). For information on using this package please refer to the [stable documentation](https://docs.sciml.ai/ReservoirComputing/stable/). Use the [in-development documentation](https://docs.sciml.ai/ReservoirComputing/dev/) to take a look at at not yet released features.

## Quick Example

To illustrate the workflow of this library we will showcase how it is possible to train an ESN to learn the dynamics of the Lorenz system. As a first step we will need to gather the data. For the `Generative` prediction we need the target data to be one step ahead of the training data:
Expand Down
Empty file modified docs/Project.toml
100644 → 100755
Empty file.
Empty file modified docs/make.jl
100644 → 100755
Empty file.
Empty file modified docs/pages.jl
100644 → 100755
Empty file.
Empty file modified docs/src/api/esn.md
100644 → 100755
Empty file.
Empty file modified docs/src/api/esn_drivers.md
100644 → 100755
Empty file.
Empty file modified docs/src/api/predict.md
100644 → 100755
Empty file.
Empty file modified docs/src/api/reca.md
100644 → 100755
Empty file.
Empty file modified docs/src/api/states.md
100644 → 100755
Empty file.
Empty file modified docs/src/api/training.md
100644 → 100755
Empty file.
Empty file modified docs/src/assets/favicon.ico
100644 → 100755
Empty file.
Empty file modified docs/src/assets/logo.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/src/esn_tutorials/change_layers.md
100644 → 100755
Empty file.
Empty file modified docs/src/esn_tutorials/data/santafe_laser.txt
100644 → 100755
Empty file.
Empty file modified docs/src/esn_tutorials/deep_esn.md
100644 → 100755
Empty file.
Empty file modified docs/src/esn_tutorials/different_drivers.md
100644 → 100755
Empty file.
Empty file modified docs/src/esn_tutorials/different_training.md
100644 → 100755
Empty file.
Empty file modified docs/src/esn_tutorials/hybrid.md
100644 → 100755
Empty file.
Empty file modified docs/src/esn_tutorials/lorenz_basic.md
100644 → 100755
Empty file.
Empty file modified docs/src/general/different_training.md
100644 → 100755
Empty file.
Empty file modified docs/src/general/predictive_generative.md
100644 → 100755
Empty file.
Empty file modified docs/src/general/states_variation.md
100644 → 100755
Empty file.
Empty file modified docs/src/index.md
100644 → 100755
Empty file.
Empty file modified docs/src/reca_tutorials/5bitinput.txt
100644 → 100755
Empty file.
Empty file modified docs/src/reca_tutorials/5bitoutput.txt
100644 → 100755
Empty file.
Empty file modified docs/src/reca_tutorials/reca.md
100644 → 100755
Empty file.
Empty file modified ext/RCLIBSVMExt.jl
100644 → 100755
Empty file.
Empty file modified ext/RCMLJLinearModelsExt.jl
100644 → 100755
Empty file.
82 changes: 44 additions & 38 deletions src/ReservoirComputing.jl
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,15 @@ module ReservoirComputing
using Adapt
using CellularAutomata
using Distances
using Distributions
using LinearAlgebra
using NNlib
using Optim
using PartialFunctions
using Random
using Reexport: Reexport, @reexport
using Statistics
using WeightInitializers

export NLADefault, NLAT1, NLAT2, NLAT3
export StandardStates, ExtendedStates, PaddedStates, PaddedExtendedStates
export StandardRidge
export scaled_rand, weighted_init, informed_init, minimal_init
export rand_sparse, delay_line, delay_line_backward, cycle_jumps, simple_cycle, pseudo_svd
export RNN, MRNN, GRU, GRUParams, FullyGated, Minimal
export train
export ESN
export HybridESN, KnowledgeModel
export DeepESN
export RECA
export RandomMapping, RandomMaps
export Generative, Predictive, OutputLayer
using StatsBase: sample
using WeightInitializers: DeviceAgnostic, PartialFunction, Utils
@reexport using WeightInitializers

#define global types
abstract type AbstractReservoirComputer end
Expand Down Expand Up @@ -104,34 +91,39 @@ function Predictive(prediction_data)
Predictive(prediction_data, prediction_len)
end

__partial_apply(fn, inp) = fn$inp

#fallbacks for initializers
#fallbacks for initializers #eventually to remove once migrated to WeightInitializers.jl
for initializer in (:rand_sparse, :delay_line, :delay_line_backward, :cycle_jumps,
:simple_cycle, :pseudo_svd,
:scaled_rand, :weighted_init, :informed_init, :minimal_init)
NType = ifelse(initializer === :rand_sparse, Real, Number)
@eval function ($initializer)(dims::Integer...; kwargs...)
return $initializer(WeightInitializers._default_rng(), Float32, dims...; kwargs...)
end
@eval function ($initializer)(rng::AbstractRNG, dims::Integer...; kwargs...)
return $initializer(rng, Float32, dims...; kwargs...)
end
@eval function ($initializer)(::Type{T},
dims::Integer...; kwargs...) where {T <: $NType}
return $initializer(WeightInitializers._default_rng(), T, dims...; kwargs...)
end
@eval function ($initializer)(rng::AbstractRNG; kwargs...)
return __partial_apply($initializer, (rng, (; kwargs...)))
@eval begin
function ($initializer)(dims::Integer...; kwargs...)
return $initializer(Utils.default_rng(), Float32, dims...; kwargs...)
end
function ($initializer)(rng::AbstractRNG, dims::Integer...; kwargs...)
return $initializer(rng, Float32, dims...; kwargs...)
end
function ($initializer)(::Type{T}, dims::Integer...; kwargs...) where {T <: Number}
return $initializer(Utils.default_rng(), T, dims...; kwargs...)
end

# Partial application
function ($initializer)(rng::AbstractRNG; kwargs...)
return PartialFunction.Partial{Nothing}($initializer, rng, kwargs)
end
function ($initializer)(::Type{T}; kwargs...) where {T <: Number}
return PartialFunction.Partial{T}($initializer, nothing, kwargs)
end
function ($initializer)(rng::AbstractRNG, ::Type{T}; kwargs...) where {T <: Number}
return PartialFunction.Partial{T}($initializer, rng, kwargs)
end
function ($initializer)(; kwargs...)
return PartialFunction.Partial{Nothing}($initializer, nothing, kwargs)
end
end
@eval function ($initializer)(rng::AbstractRNG,
::Type{T}; kwargs...) where {T <: $NType}
return __partial_apply($initializer, ((rng, T), (; kwargs...)))
end
@eval ($initializer)(; kwargs...) = __partial_apply(
$initializer, (; kwargs...))
end


#general
include("states.jl")
include("predict.jl")
Expand All @@ -158,4 +150,18 @@ if !isdefined(Base, :get_extension)
include("../ext/RCLIBSVMExt.jl")
end

export NLADefault, NLAT1, NLAT2, NLAT3
export StandardStates, ExtendedStates, PaddedStates, PaddedExtendedStates
export StandardRidge
export scaled_rand, weighted_init, informed_init, minimal_init
export rand_sparse, delay_line, delay_line_backward, cycle_jumps, simple_cycle, pseudo_svd
export RNN, MRNN, GRU, GRUParams, FullyGated, Minimal
export train
export ESN
export HybridESN, KnowledgeModel
export DeepESN
export RECA, sample
export RandomMapping, RandomMaps
export Generative, Predictive, OutputLayer

end #module
2 changes: 1 addition & 1 deletion src/esn/deepesn.jl
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function DeepESN(train_data,
nla_type = NLADefault(),
states_type = StandardStates(),
washout::Int = 0,
rng = WeightInitializers._default_rng(),
rng = Utils.default_rng(),
T = Float64,
matrix_type = typeof(train_data))
if states_type isa AbstractPaddedStates
Expand Down
2 changes: 1 addition & 1 deletion src/esn/esn.jl
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function ESN(train_data,
nla_type = NLADefault(),
states_type = StandardStates(),
washout = 0,
rng = WeightInitializers._default_rng(),
rng = Utils.default_rng(),
T = Float32,
matrix_type = typeof(train_data))
if states_type isa AbstractPaddedStates
Expand Down
44 changes: 25 additions & 19 deletions src/esn/esn_input_layers.jl
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ function scaled_rand(rng::AbstractRNG,
dims::Integer...;
scaling = T(0.1)) where {T <: Number}
res_size, in_size = dims
layer_matrix = T.(rand(rng, Uniform(-scaling, scaling), res_size, in_size))
layer_matrix = (DeviceAgnostic.rand(rng, T, res_size, in_size) .- T(0.5)) .*
(T(2) * scaling)
return layer_matrix
end

Expand Down Expand Up @@ -65,13 +66,12 @@ function weighted_init(rng::AbstractRNG,
scaling = T(0.1)) where {T <: Number}
approx_res_size, in_size = dims
res_size = Int(floor(approx_res_size / in_size) * in_size)
layer_matrix = zeros(T, res_size, in_size)
layer_matrix = DeviceAgnostic.zeros(rng, T, res_size, in_size)
q = floor(Int, res_size / in_size)

for i in 1:in_size
layer_matrix[((i - 1) * q + 1):((i) * q), i] = rand(rng,
Uniform(-scaling, scaling),
q)
layer_matrix[((i - 1) * q + 1):((i) * q), i] = (DeviceAgnostic.rand(rng, T, q) .-
T(0.5)) .* (T(2) * scaling)
end

return layer_matrix
Expand Down Expand Up @@ -113,25 +113,28 @@ function informed_init(rng::AbstractRNG, ::Type{T}, dims::Integer...;
throw(DimensionMismatch("in_size must be greater than model_in_size"))
end

input_matrix = zeros(res_size, in_size)
zero_connections = zeros(in_size)
input_matrix = DeviceAgnostic.zeros(rng, T, res_size, in_size)
zero_connections = DeviceAgnostic.zeros(rng, T, in_size)
num_for_state = floor(Int, res_size * gamma)
num_for_model = floor(Int, res_size * (1 - gamma))

for i in 1:num_for_state
idxs = findall(Bool[zero_connections .== input_matrix[i, :]
for i in 1:size(input_matrix, 1)])
random_row_idx = idxs[rand(rng, 1:end)]
random_clm_idx = range(1, state_size, step = 1)[rand(rng, 1:end)]
input_matrix[random_row_idx, random_clm_idx] = rand(rng, Uniform(-scaling, scaling))
random_row_idx = idxs[DeviceAgnostic.rand(rng, T, 1:end)]
random_clm_idx = range(1, state_size, step = 1)[DeviceAgnostic.rand(rng, T, 1:end)]
input_matrix[random_row_idx, random_clm_idx] = (DeviceAgnostic.rand(rng, T) -
T(0.5)) .* (T(2) * scaling)
end

for i in 1:num_for_model
idxs = findall(Bool[zero_connections .== input_matrix[i, :]
for i in 1:size(input_matrix, 1)])
random_row_idx = idxs[rand(rng, 1:end)]
random_clm_idx = range(state_size + 1, in_size, step = 1)[rand(rng, 1:end)]
input_matrix[random_row_idx, random_clm_idx] = rand(rng, Uniform(-scaling, scaling))
random_row_idx = idxs[DeviceAgnostic.rand(rng, T, 1:end)]
random_clm_idx = range(state_size + 1, in_size, step = 1)[DeviceAgnostic.rand(
rng, T, 1:end)]
input_matrix[random_row_idx, random_clm_idx] = (DeviceAgnostic.rand(rng, T) -
T(0.5)) .* (T(2) * scaling)
end

return input_matrix
Expand Down Expand Up @@ -196,11 +199,14 @@ function _create_bernoulli(p::Number,
weight::Number,
rng::AbstractRNG,
::Type{T}) where {T <: Number}
input_matrix = zeros(T, res_size, in_size)
input_matrix = DeviceAgnostic.zeros(rng, T, res_size, in_size)
for i in 1:res_size
for j in 1:in_size
rand(rng, Bernoulli(p)) ? (input_matrix[i, j] = weight) :
(input_matrix[i, j] = -weight)
if DeviceAgnostic.rand(rng, T) < p
input_matrix[i, j] = weight
else
input_matrix[i, j] = -weight
end
end
end
return input_matrix
Expand All @@ -216,16 +222,16 @@ function _create_irrational(irrational::Irrational,
setprecision(BigFloat, Int(ceil(log2(10) * (res_size * in_size + start + 1))))
ir_string = string(BigFloat(irrational)) |> collect
deleteat!(ir_string, findall(x -> x == '.', ir_string))
ir_array = zeros(length(ir_string))
input_matrix = zeros(T, res_size, in_size)
ir_array = DeviceAgnostic.zeros(rng, T, length(ir_string))
input_matrix = DeviceAgnostic.zeros(rng, T, res_size, in_size)

for i in 1:length(ir_string)
ir_array[i] = parse(Int, ir_string[i])
end

for i in 1:res_size
for j in 1:in_size
random_number = rand(rng, T)
random_number = DeviceAgnostic.rand(rng, T)
input_matrix[i, j] = random_number < 0.5 ? -weight : weight
end
end
Expand Down
Empty file modified src/esn/esn_predict.jl
100644 → 100755
Empty file.
Empty file modified src/esn/esn_reservoir_drivers.jl
100644 → 100755
Empty file.
Loading

2 comments on commit dcbf85e

@MartinuzziFrancesco
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/122210

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.10.5 -m "<description of version>" dcbf85e1e4825192de4683127f8f7a819af97144
git push origin v0.10.5

Also, note the warning: Version 0.10.5 skips over 0.10.4
This can be safely ignored. However, if you want to fix this you can do so. Call register() again after making the fix. This will update the Pull request.

Please sign in to comment.