From e414aa2c7292be72b42c9fbdcdc588dd61f5c2fc Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Wed, 12 Jun 2024 09:34:13 +1200 Subject: [PATCH] add a copy of mnist to extended examples (formerly "full tutorials") --- .gitignore | 1 + docs/make.jl | 16 +- docs/src/extended_examples/MNIST.md | 100 - .../src/extended_examples/MNIST/Manifest.toml | 2319 +++++++++++++++++ docs/src/extended_examples/MNIST/Project.toml | 11 + docs/src/extended_examples/MNIST/README.md | 19 + docs/src/extended_examples/MNIST/generate.jl | 5 + docs/src/extended_examples/MNIST/loss.png | Bin 0 -> 22198 bytes .../extended_examples/MNIST/notebook.ipynb | 2103 +++++++++++++++ docs/src/extended_examples/MNIST/notebook.jl | 290 +++ docs/src/extended_examples/MNIST/notebook.md | 352 +++ .../MNIST/notebook.unexecuted.ipynb | 724 +++++ docs/src/extended_examples/MNIST/weights.png | Bin 0 -> 35741 bytes docs/src/generate.jl | 4 +- 14 files changed, 5835 insertions(+), 109 deletions(-) delete mode 100644 docs/src/extended_examples/MNIST.md create mode 100644 docs/src/extended_examples/MNIST/Manifest.toml create mode 100644 docs/src/extended_examples/MNIST/Project.toml create mode 100644 docs/src/extended_examples/MNIST/README.md create mode 100644 docs/src/extended_examples/MNIST/generate.jl create mode 100644 docs/src/extended_examples/MNIST/loss.png create mode 100644 docs/src/extended_examples/MNIST/notebook.ipynb create mode 100644 docs/src/extended_examples/MNIST/notebook.jl create mode 100644 docs/src/extended_examples/MNIST/notebook.md create mode 100644 docs/src/extended_examples/MNIST/notebook.unexecuted.ipynb create mode 100644 docs/src/extended_examples/MNIST/weights.png diff --git a/.gitignore b/.gitignore index 2872cb6c..a72a86ff 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ sandbox/ docs/build /examples/mnist/mnist_machine* +*.jls \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index 0f7fe4d1..bc0ad3f0 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -36,18 +36,18 @@ makedocs( ], "Workflow Examples" => Any[ "Incremental Training"=> - "workflow examples/Incremental Training/notebook.md", + "workflow_examples/Incremental Training/notebook.md", "Hyperparameter Tuning"=> - "workflow examples/Hyperparameter Tuning/notebook.md", + "workflow_examples/Hyperparameter Tuning/notebook.md", "Neural Architecture Search"=> - "workflow examples/Basic Neural Architecture Search/notebook.md", - "Model Composition"=>"workflow examples/Composition/notebook.md", - "Model Comparison"=>"workflow examples/Comparison/notebook.md", - "Early Stopping"=>"workflow examples/Early Stopping/notebook.md", - "Live Training"=>"workflow examples/Live Training/notebook.md", + "workflow_examples/Basic Neural Architecture Search/notebook.md", + "Model Composition"=>"workflow_examples/Composition/notebook.md", + "Model Comparison"=>"workflow_examples/Comparison/notebook.md", + "Early Stopping"=>"workflow_examples/Early Stopping/notebook.md", + "Live Training"=>"workflow_examples/Live Training/notebook.md", ], # "Tutorials"=>Any[ - # "Spam Detection with RNNs"=>"full tutorials/Spam Detection with RNNs/notebook.md" + # "Spam Detection with RNNs"=>"extended_examples/Spam Detection with RNNs/notebook.md" # ], "Contributing" => "contributing.md"], doctest = false, diff --git a/docs/src/extended_examples/MNIST.md b/docs/src/extended_examples/MNIST.md deleted file mode 100644 index 2183f547..00000000 --- a/docs/src/extended_examples/MNIST.md +++ /dev/null @@ -1,100 +0,0 @@ -## Image Classification Example -An expanded version of this example, with early stopping and -snapshots, is available [here](/examples/mnist). - -We define a builder that builds a chain with six alternating -convolution and max-pool layers, and a final dense layer, which we -apply to the MNIST image dataset. - -First we define a generic builder (working for any image size, color -or gray): - -```julia -using MLJ -using Flux -using MLDatasets - -# helper function -function flatten(x::AbstractArray) - return reshape(x, :, size(x)[end]) -end - -import MLJFlux -mutable struct MyConvBuilder - filter_size::Int - channels1::Int - channels2::Int - channels3::Int -end - -function MLJFlux.build(b::MyConvBuilder, rng, n_in, n_out, n_channels) - - k, c1, c2, c3 = b.filter_size, b.channels1, b.channels2, b.channels3 - - mod(k, 2) == 1 || error("`filter_size` must be odd. ") - - # padding to preserve image size on convolution: - p = div(k - 1, 2) - - front = Chain( - Conv((k, k), n_channels => c1, pad=(p, p), relu), - MaxPool((2, 2)), - Conv((k, k), c1 => c2, pad=(p, p), relu), - MaxPool((2, 2)), - Conv((k, k), c2 => c3, pad=(p, p), relu), - MaxPool((2 ,2)), - flatten, - ) - d = Flux.outputsize(front, (n_in..., n_channels, 1)) |> first - return Chain(front, Dense(d, n_out)) -end -``` -Next, we load some of the MNIST data and check scientific types -conform to those is the table above: - -```julia -N = 500 -Xraw, yraw = MNIST(split=:train)[:]; -Xraw = Xraw[:,:,1:N]; -yraw = yraw[1:N]; - -scitype(Xraw) -``` -```julia -scitype(yraw) -``` - -Inputs should have element scitype `GrayImage`: - -```julia -X = coerce(Xraw, GrayImage); -``` - -For classifiers, target must have element scitype `<: Finite`: - -```julia -y = coerce(yraw, Multiclass); -``` - -Instantiating an image classifier model: - -```julia -ImageClassifier = @load ImageClassifier -clf = ImageClassifier( - builder=MyConvBuilder(3, 16, 32, 32), - epochs=10, - loss=Flux.crossentropy, - ) -``` - -And evaluating the accuracy of the model on a 30% holdout set: - -```julia -mach = machine(clf, X, y) - -evaluate!( - mach, - resampling=Holdout(rng=123, fraction_train=0.7), - measure=misclassification_rate, - ) -``` diff --git a/docs/src/extended_examples/MNIST/Manifest.toml b/docs/src/extended_examples/MNIST/Manifest.toml new file mode 100644 index 00000000..29c5e94b --- /dev/null +++ b/docs/src/extended_examples/MNIST/Manifest.toml @@ -0,0 +1,2319 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.10.3" +manifest_format = "2.0" +project_hash = "3049fd46149696b9ac7df5214242bc2535d0a10e" + +[[deps.ARFFFiles]] +deps = ["CategoricalArrays", "Dates", "Parsers", "Tables"] +git-tree-sha1 = "e8c8e0a2be6eb4f56b1672e46004463033daa409" +uuid = "da404889-ca92-49ff-9e8b-0aa6b4d38dc8" +version = "1.4.1" + +[[deps.AbstractFFTs]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" +uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" +version = "1.5.0" +weakdeps = ["ChainRulesCore", "Test"] + + [deps.AbstractFFTs.extensions] + AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + AbstractFFTsTestExt = "Test" + +[[deps.Adapt]] +deps = ["LinearAlgebra", "Requires"] +git-tree-sha1 = "6a55b747d1812e699320963ffde36f1ebdda4099" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "4.0.4" +weakdeps = ["StaticArrays"] + + [deps.Adapt.extensions] + AdaptStaticArraysExt = "StaticArrays" + +[[deps.AliasTables]] +deps = ["PtrArrays", "Random"] +git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff" +uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8" +version = "1.1.3" + +[[deps.ArgCheck]] +git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4" +uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197" +version = "2.3.0" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.1" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.Atomix]] +deps = ["UnsafeAtomics"] +git-tree-sha1 = "c06a868224ecba914baa6942988e2f2aade419be" +uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458" +version = "0.1.0" + +[[deps.AtomsBase]] +deps = ["LinearAlgebra", "PeriodicTable", "Printf", "Requires", "StaticArrays", "Unitful", "UnitfulAtomic"] +git-tree-sha1 = "995c2b6b17840cd87b722ce9c6cdd72f47bab545" +uuid = "a963bdd2-2df7-4f54-a1ee-49d51e6be12a" +version = "0.3.5" + +[[deps.BFloat16s]] +deps = ["LinearAlgebra", "Printf", "Random", "Test"] +git-tree-sha1 = "2c7cc21e8678eff479978a0a2ef5ce2f51b63dff" +uuid = "ab4f0b2a-ad5b-11e8-123f-65d77653426b" +version = "0.5.0" + +[[deps.BSON]] +git-tree-sha1 = "4c3e506685c527ac6a54ccc0c8c76fd6f91b42fb" +uuid = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0" +version = "0.3.9" + +[[deps.BangBang]] +deps = ["Compat", "ConstructionBase", "InitialValues", "LinearAlgebra", "Requires", "Setfield", "Tables"] +git-tree-sha1 = "7aa7ad1682f3d5754e3491bb59b8103cae28e3a3" +uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66" +version = "0.3.40" + + [deps.BangBang.extensions] + BangBangChainRulesCoreExt = "ChainRulesCore" + BangBangDataFramesExt = "DataFrames" + BangBangStaticArraysExt = "StaticArrays" + BangBangStructArraysExt = "StructArrays" + BangBangTypedTablesExt = "TypedTables" + + [deps.BangBang.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" + TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.Baselet]] +git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e" +uuid = "9718e550-a3fa-408a-8086-8db961cd8217" +version = "0.1.1" + +[[deps.BitFlags]] +git-tree-sha1 = "2dc09997850d68179b69dafb58ae806167a32b1b" +uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" +version = "0.1.8" + +[[deps.BufferedStreams]] +git-tree-sha1 = "4ae47f9a4b1dc19897d3743ff13685925c5202ec" +uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d" +version = "1.2.1" + +[[deps.Bzip2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "9e2a6b69137e6969bab0152632dcb3bc108c8bdd" +uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" +version = "1.0.8+1" + +[[deps.CEnum]] +git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" +uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" +version = "0.5.0" + +[[deps.CSV]] +deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"] +git-tree-sha1 = "6c834533dc1fabd820c1db03c839bf97e45a3fab" +uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +version = "0.10.14" + +[[deps.CUDA]] +deps = ["AbstractFFTs", "Adapt", "BFloat16s", "CEnum", "CUDA_Driver_jll", "CUDA_Runtime_Discovery", "CUDA_Runtime_jll", "Crayons", "DataFrames", "ExprTools", "GPUArrays", "GPUCompiler", "KernelAbstractions", "LLVM", "LLVMLoopInfo", "LazyArtifacts", "Libdl", "LinearAlgebra", "Logging", "NVTX", "Preferences", "PrettyTables", "Printf", "Random", "Random123", "RandomNumbers", "Reexport", "Requires", "SparseArrays", "StaticArrays", "Statistics"] +git-tree-sha1 = "b8c28cb78014f7ae81a652ce1524cba7667dea5c" +uuid = "052768ef-5323-5732-b1bb-66c8b64840ba" +version = "5.3.5" + + [deps.CUDA.extensions] + ChainRulesCoreExt = "ChainRulesCore" + EnzymeCoreExt = "EnzymeCore" + SpecialFunctionsExt = "SpecialFunctions" + + [deps.CUDA.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" + +[[deps.CUDA_Driver_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"] +git-tree-sha1 = "dc172b558adbf17952001e15cf0d6364e6d78c2f" +uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc" +version = "0.8.1+0" + +[[deps.CUDA_Runtime_Discovery]] +deps = ["Libdl"] +git-tree-sha1 = "38f830504358e9972d2a0c3e5d51cb865e0733df" +uuid = "1af6417a-86b4-443c-805f-a4643ffb695f" +version = "0.2.4" + +[[deps.CUDA_Runtime_jll]] +deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "4ca7d6d92075906c2ce871ea8bba971fff20d00c" +uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2" +version = "0.12.1+0" + +[[deps.CUDNN_jll]] +deps = ["Artifacts", "CUDA_Runtime_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "cbf7d75f8c58b147bdf6acea2e5bc96cececa6d4" +uuid = "62b44479-cb7b-5706-934f-f13b2eb2e645" +version = "9.0.0+1" + +[[deps.Cairo_jll]] +deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "a2f1c8c668c8e3cb4cca4e57a8efdb09067bb3fd" +uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a" +version = "1.18.0+2" + +[[deps.Calculus]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad" +uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9" +version = "0.5.1" + +[[deps.CategoricalArrays]] +deps = ["DataAPI", "Future", "Missings", "Printf", "Requires", "Statistics", "Unicode"] +git-tree-sha1 = "1568b28f91293458345dabba6a5ea3f183250a61" +uuid = "324d7699-5711-5eae-9e2f-1d82baa6b597" +version = "0.10.8" +weakdeps = ["JSON", "RecipesBase", "SentinelArrays", "StructTypes"] + + [deps.CategoricalArrays.extensions] + CategoricalArraysJSONExt = "JSON" + CategoricalArraysRecipesBaseExt = "RecipesBase" + CategoricalArraysSentinelArraysExt = "SentinelArrays" + CategoricalArraysStructTypesExt = "StructTypes" + +[[deps.CategoricalDistributions]] +deps = ["CategoricalArrays", "Distributions", "Missings", "OrderedCollections", "Random", "ScientificTypes"] +git-tree-sha1 = "926862f549a82d6c3a7145bc7f1adff2a91a39f0" +uuid = "af321ab8-2d2e-40a6-b165-3d674595d28e" +version = "0.1.15" + + [deps.CategoricalDistributions.extensions] + UnivariateFiniteDisplayExt = "UnicodePlots" + + [deps.CategoricalDistributions.weakdeps] + UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" + +[[deps.ChainRules]] +deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "SparseInverseSubset", "Statistics", "StructArrays", "SuiteSparse"] +git-tree-sha1 = "291821c1251486504f6bae435227907d734e94d2" +uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2" +version = "1.66.0" + +[[deps.ChainRulesCore]] +deps = ["Compat", "LinearAlgebra"] +git-tree-sha1 = "575cd02e080939a33b6df6c5853d14924c08e35b" +uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +version = "1.23.0" +weakdeps = ["SparseArrays"] + + [deps.ChainRulesCore.extensions] + ChainRulesCoreSparseArraysExt = "SparseArrays" + +[[deps.Chemfiles]] +deps = ["AtomsBase", "Chemfiles_jll", "DocStringExtensions", "PeriodicTable", "Unitful", "UnitfulAtomic"] +git-tree-sha1 = "82fe5e341c793cb51149d993307da9543824b206" +uuid = "46823bd8-5fb3-5f92-9aa0-96921f3dd015" +version = "0.10.41" + +[[deps.Chemfiles_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "f3743181e30d87c23d9c8ebd493b77f43d8f1890" +uuid = "78a364fa-1a3c-552a-b4bb-8fa0f9c1fcca" +version = "0.10.4+0" + +[[deps.CodecZlib]] +deps = ["TranscodingStreams", "Zlib_jll"] +git-tree-sha1 = "59939d8a997469ee05c4b4944560a820f9ba0d73" +uuid = "944b1d66-785c-5afd-91f1-9de20f533193" +version = "0.7.4" + +[[deps.ColorSchemes]] +deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] +git-tree-sha1 = "4b270d6465eb21ae89b732182c20dc165f8bf9f2" +uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" +version = "3.25.0" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.5" + +[[deps.ColorVectorSpace]] +deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] +git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249" +uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" +version = "0.10.0" +weakdeps = ["SpecialFunctions"] + + [deps.ColorVectorSpace.extensions] + SpecialFunctionsExt = "SpecialFunctions" + +[[deps.Colors]] +deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] +git-tree-sha1 = "362a287c3aa50601b0bc359053d5c2468f0e7ce0" +uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" +version = "0.12.11" + +[[deps.Combinatorics]] +git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860" +uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" +version = "1.0.2" + +[[deps.CommonSubexpressions]] +deps = ["MacroTools", "Test"] +git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7" +uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" +version = "0.3.0" + +[[deps.Compat]] +deps = ["TOML", "UUIDs"] +git-tree-sha1 = "b1c55339b7c6c350ee89f2c1604299660525b248" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.15.0" +weakdeps = ["Dates", "LinearAlgebra"] + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.1.1+0" + +[[deps.CompositionsBase]] +git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad" +uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b" +version = "0.1.2" + + [deps.CompositionsBase.extensions] + CompositionsBaseInverseFunctionsExt = "InverseFunctions" + + [deps.CompositionsBase.weakdeps] + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.ComputationalResources]] +git-tree-sha1 = "52cb3ec90e8a8bea0e62e275ba577ad0f74821f7" +uuid = "ed09eef8-17a6-5b46-8889-db040fac31e3" +version = "0.3.2" + +[[deps.ConcurrentUtilities]] +deps = ["Serialization", "Sockets"] +git-tree-sha1 = "6cbbd4d241d7e6579ab354737f4dd95ca43946e1" +uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" +version = "2.4.1" + +[[deps.Conda]] +deps = ["Downloads", "JSON", "VersionParsing"] +git-tree-sha1 = "51cab8e982c5b598eea9c8ceaced4b58d9dd37c9" +uuid = "8f4d0f93-b110-5947-807f-2305c1781a2d" +version = "1.10.0" + +[[deps.ConstructionBase]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "260fd2400ed2dab602a7c15cf10c1933c59930a2" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.5.5" + + [deps.ConstructionBase.extensions] + ConstructionBaseIntervalSetsExt = "IntervalSets" + ConstructionBaseStaticArraysExt = "StaticArrays" + + [deps.ConstructionBase.weakdeps] + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.ContextVariablesX]] +deps = ["Compat", "Logging", "UUIDs"] +git-tree-sha1 = "25cc3803f1030ab855e383129dcd3dc294e322cc" +uuid = "6add18c4-b38d-439d-96f6-d6bc489c04c5" +version = "0.1.3" + +[[deps.Contour]] +git-tree-sha1 = "439e35b0b36e2e5881738abc8857bd92ad6ff9a8" +uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" +version = "0.6.3" + +[[deps.Crayons]] +git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.1.1" + +[[deps.DataAPI]] +git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.16.0" + +[[deps.DataDeps]] +deps = ["HTTP", "Libdl", "Reexport", "SHA", "Scratch", "p7zip_jll"] +git-tree-sha1 = "8ae085b71c462c2cb1cfedcb10c3c877ec6cf03f" +uuid = "124859b0-ceae-595e-8997-d05f6a7a8dfe" +version = "0.7.13" + +[[deps.DataFrames]] +deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +git-tree-sha1 = "04c738083f29f86e62c8afc341f0967d8717bdb8" +uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +version = "1.6.1" + +[[deps.DataStructures]] +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.18.20" + +[[deps.DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.DefineSingletons]] +git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c" +uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52" +version = "0.1.2" + +[[deps.DelimitedFiles]] +deps = ["Mmap"] +git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae" +uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" +version = "1.9.1" + +[[deps.DiffResults]] +deps = ["StaticArraysCore"] +git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621" +uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" +version = "1.1.0" + +[[deps.DiffRules]] +deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"] +git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272" +uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" +version = "1.15.1" + +[[deps.Distances]] +deps = ["LinearAlgebra", "Statistics", "StatsAPI"] +git-tree-sha1 = "66c4c81f259586e8f002eacebc177e1fb06363b0" +uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" +version = "0.10.11" +weakdeps = ["ChainRulesCore", "SparseArrays"] + + [deps.Distances.extensions] + DistancesChainRulesCoreExt = "ChainRulesCore" + DistancesSparseArraysExt = "SparseArrays" + +[[deps.Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" + +[[deps.Distributions]] +deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "22c595ca4146c07b16bcf9c8bea86f731f7109d2" +uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" +version = "0.25.108" + + [deps.Distributions.extensions] + DistributionsChainRulesCoreExt = "ChainRulesCore" + DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsTestExt = "Test" + + [deps.Distributions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.DocStringExtensions]] +deps = ["LibGit2"] +git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.3" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.DualNumbers]] +deps = ["Calculus", "NaNMath", "SpecialFunctions"] +git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566" +uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74" +version = "0.6.8" + +[[deps.EarlyStopping]] +deps = ["Dates", "Statistics"] +git-tree-sha1 = "98fdf08b707aaf69f524a6cd0a67858cefe0cfb6" +uuid = "792122b4-ca99-40de-a6bc-6742525f08b6" +version = "0.3.0" + +[[deps.EpollShim_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8e9441ee83492030ace98f9789a654a6d0b1f643" +uuid = "2702e6a9-849d-5ed8-8c21-79e8b8f9ee43" +version = "0.0.20230411+0" + +[[deps.ExceptionUnwrapping]] +deps = ["Test"] +git-tree-sha1 = "dcb08a0d93ec0b1cdc4af184b26b591e9695423a" +uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4" +version = "0.1.10" + +[[deps.Expat_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1c6317308b9dc757616f0b5cb379db10494443a7" +uuid = "2e619515-83b5-522b-bb60-26c02a35a201" +version = "2.6.2+0" + +[[deps.ExprTools]] +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" +uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" +version = "0.1.10" + +[[deps.FFMPEG]] +deps = ["FFMPEG_jll"] +git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8" +uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" +version = "0.4.1" + +[[deps.FFMPEG_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "PCRE2_jll", "Zlib_jll", "libaom_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] +git-tree-sha1 = "466d45dc38e15794ec7d5d63ec03d776a9aff36e" +uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" +version = "4.4.4+1" + +[[deps.FLoops]] +deps = ["BangBang", "Compat", "FLoopsBase", "InitialValues", "JuliaVariables", "MLStyle", "Serialization", "Setfield", "Transducers"] +git-tree-sha1 = "ffb97765602e3cbe59a0589d237bf07f245a8576" +uuid = "cc61a311-1640-44b5-9fba-1b764f453329" +version = "0.2.1" + +[[deps.FLoopsBase]] +deps = ["ContextVariablesX"] +git-tree-sha1 = "656f7a6859be8673bf1f35da5670246b923964f7" +uuid = "b9860ae5-e623-471e-878b-f6a53c775ea6" +version = "0.1.1" + +[[deps.FileIO]] +deps = ["Pkg", "Requires", "UUIDs"] +git-tree-sha1 = "82d8afa92ecf4b52d78d869f038ebfb881267322" +uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +version = "1.16.3" + +[[deps.FilePathsBase]] +deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"] +git-tree-sha1 = "9f00e42f8d99fdde64d40c8ea5d14269a2e2c1aa" +uuid = "48062228-2e41-5def-b9a4-89aafe57970f" +version = "0.9.21" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" + +[[deps.FillArrays]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "0653c0a2396a6da5bc4766c43041ef5fd3efbe57" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "1.11.0" +weakdeps = ["PDMats", "SparseArrays", "Statistics"] + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStatisticsExt = "Statistics" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.5" + +[[deps.Flux]] +deps = ["Adapt", "ChainRulesCore", "Compat", "Functors", "LinearAlgebra", "MLUtils", "MacroTools", "NNlib", "OneHotArrays", "Optimisers", "Preferences", "ProgressLogging", "Random", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "Zygote"] +git-tree-sha1 = "a5475163b611812d073171583982c42ea48d22b0" +uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c" +version = "0.14.15" + + [deps.Flux.extensions] + FluxAMDGPUExt = "AMDGPU" + FluxCUDAExt = "CUDA" + FluxCUDAcuDNNExt = ["CUDA", "cuDNN"] + FluxMetalExt = "Metal" + + [deps.Flux.weakdeps] + AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + Metal = "dde4c033-4e86-420c-a63e-0dd931031962" + cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd" + +[[deps.Fontconfig_jll]] +deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Zlib_jll"] +git-tree-sha1 = "db16beca600632c95fc8aca29890d83788dd8b23" +uuid = "a3f928ae-7b40-5064-980b-68af3947d34b" +version = "2.13.96+0" + +[[deps.Format]] +git-tree-sha1 = "9c68794ef81b08086aeb32eeaf33531668d5f5fc" +uuid = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8" +version = "1.3.7" + +[[deps.ForwardDiff]] +deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] +git-tree-sha1 = "cf0fe81336da9fb90944683b8c41984b08793dad" +uuid = "f6369f11-7733-5829-9624-2563aa707210" +version = "0.10.36" +weakdeps = ["StaticArrays"] + + [deps.ForwardDiff.extensions] + ForwardDiffStaticArraysExt = "StaticArrays" + +[[deps.FreeType2_jll]] +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "5c1d8ae0efc6c2e7b1fc502cbe25def8f661b7bc" +uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7" +version = "2.13.2+0" + +[[deps.FriBidi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1ed150b39aebcc805c26b93a8d0122c940f64ce2" +uuid = "559328eb-81f9-559d-9380-de523a88c83c" +version = "1.0.14+0" + +[[deps.Functors]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "d3e63d9fa13f8eaa2f06f64949e2afc593ff52c2" +uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196" +version = "0.4.10" + +[[deps.Future]] +deps = ["Random"] +uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" + +[[deps.GLFW_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"] +git-tree-sha1 = "ff38ba61beff76b8f4acad8ab0c97ef73bb670cb" +uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89" +version = "3.3.9+0" + +[[deps.GPUArrays]] +deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"] +git-tree-sha1 = "38cb19b8a3e600e509dc36a6396ac74266d108c1" +uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7" +version = "10.1.1" + +[[deps.GPUArraysCore]] +deps = ["Adapt"] +git-tree-sha1 = "ec632f177c0d990e64d955ccc1b8c04c485a0950" +uuid = "46192b85-c4d5-4398-a991-12ede77f4527" +version = "0.1.6" + +[[deps.GPUCompiler]] +deps = ["ExprTools", "InteractiveUtils", "LLVM", "Libdl", "Logging", "Scratch", "TimerOutputs", "UUIDs"] +git-tree-sha1 = "1600477fba37c9fc067b9be21f5e8101f24a8865" +uuid = "61eb1bfa-7361-4325-ad38-22787b887f55" +version = "0.26.4" + +[[deps.GR]] +deps = ["Artifacts", "Base64", "DelimitedFiles", "Downloads", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Preferences", "Printf", "Random", "Serialization", "Sockets", "TOML", "Tar", "Test", "p7zip_jll"] +git-tree-sha1 = "ddda044ca260ee324c5fc07edb6d7cf3f0b9c350" +uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" +version = "0.73.5" + +[[deps.GR_jll]] +deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "FreeType2_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Qt6Base_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "278e5e0f820178e8a26df3184fcb2280717c79b1" +uuid = "d2c73de3-f751-5644-a686-071e5b155ba9" +version = "0.73.5+0" + +[[deps.GZip]] +deps = ["Libdl", "Zlib_jll"] +git-tree-sha1 = "0085ccd5ec327c077ec5b91a5f937b759810ba62" +uuid = "92fee26a-97fe-5a0c-ad85-20a5f3185b63" +version = "0.6.2" + +[[deps.Gettext_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046" +uuid = "78b55507-aeef-58d4-861c-77aaff3498b1" +version = "0.21.0+0" + +[[deps.Glib_jll]] +deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE2_jll", "Zlib_jll"] +git-tree-sha1 = "7c82e6a6cd34e9d935e9aa4051b66c6ff3af59ba" +uuid = "7746bdde-850d-59dc-9ae8-88ece973131d" +version = "2.80.2+0" + +[[deps.Glob]] +git-tree-sha1 = "97285bbd5230dd766e9ef6749b80fc617126d496" +uuid = "c27321d9-0574-5035-807b-f59d2c89b15c" +version = "1.3.1" + +[[deps.Graphite2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011" +uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472" +version = "1.3.14+0" + +[[deps.Grisu]] +git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2" +uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe" +version = "1.0.2" + +[[deps.HDF5]] +deps = ["Compat", "HDF5_jll", "Libdl", "MPIPreferences", "Mmap", "Preferences", "Printf", "Random", "Requires", "UUIDs"] +git-tree-sha1 = "e856eef26cf5bf2b0f95f8f4fc37553c72c8641c" +uuid = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" +version = "0.17.2" + + [deps.HDF5.extensions] + MPIExt = "MPI" + + [deps.HDF5.weakdeps] + MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" + +[[deps.HDF5_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "LibCURL_jll", "Libdl", "MPICH_jll", "MPIPreferences", "MPItrampoline_jll", "MicrosoftMPI_jll", "OpenMPI_jll", "OpenSSL_jll", "TOML", "Zlib_jll", "libaec_jll"] +git-tree-sha1 = "82a471768b513dc39e471540fdadc84ff80ff997" +uuid = "0234f1f7-429e-5d53-9886-15a909be8d59" +version = "1.14.3+3" + +[[deps.HTTP]] +deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] +git-tree-sha1 = "d1d712be3164d61d1fb98e7ce9bcbc6cc06b45ed" +uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" +version = "1.10.8" + +[[deps.HarfBuzz_jll]] +deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"] +git-tree-sha1 = "129acf094d168394e80ee1dc4bc06ec835e510a3" +uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566" +version = "2.8.1+1" + +[[deps.Hwloc_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "ca0f6bf568b4bfc807e7537f081c81e35ceca114" +uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8" +version = "2.10.0+0" + +[[deps.HypergeometricFunctions]] +deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] +git-tree-sha1 = "f218fe3736ddf977e0e772bc9a586b2383da2685" +uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" +version = "0.3.23" + +[[deps.IJulia]] +deps = ["Base64", "Conda", "Dates", "InteractiveUtils", "JSON", "Libdl", "Logging", "Markdown", "MbedTLS", "Pkg", "Printf", "REPL", "Random", "SoftGlobalScope", "Test", "UUIDs", "ZMQ"] +git-tree-sha1 = "47ac8cc196b81001a711f4b2c12c97372338f00c" +uuid = "7073ff75-c697-5162-941a-fcdaad2a7d2a" +version = "1.24.2" + +[[deps.IRTools]] +deps = ["InteractiveUtils", "MacroTools"] +git-tree-sha1 = "950c3717af761bc3ff906c2e8e52bd83390b6ec2" +uuid = "7869d1d1-7146-5819-86e3-90919afe41df" +version = "0.4.14" + +[[deps.ImageBase]] +deps = ["ImageCore", "Reexport"] +git-tree-sha1 = "eb49b82c172811fd2c86759fa0553a2221feb909" +uuid = "c817782e-172a-44cc-b673-b171935fbb9e" +version = "0.1.7" + +[[deps.ImageCore]] +deps = ["ColorVectorSpace", "Colors", "FixedPointNumbers", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "PrecompileTools", "Reexport"] +git-tree-sha1 = "b2a7eaa169c13f5bcae8131a83bc30eff8f71be0" +uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" +version = "0.10.2" + +[[deps.ImageShow]] +deps = ["Base64", "ColorSchemes", "FileIO", "ImageBase", "ImageCore", "OffsetArrays", "StackViews"] +git-tree-sha1 = "3b5344bcdbdc11ad58f3b1956709b5b9345355de" +uuid = "4e3cecfd-b093-5904-9786-8bbb286a6a31" +version = "0.3.8" + +[[deps.InitialValues]] +git-tree-sha1 = "4da0f88e9a39111c2fa3add390ab15f3a44f3ca3" +uuid = "22cec73e-a1b8-11e9-2c92-598750a2cf9c" +version = "0.3.1" + +[[deps.InlineStrings]] +deps = ["Parsers"] +git-tree-sha1 = "9cc2baf75c6d09f9da536ddf58eb2f29dedaf461" +uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" +version = "1.4.0" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.InternedStrings]] +deps = ["Random", "Test"] +git-tree-sha1 = "eb05b5625bc5d821b8075a77e4c421933e20c76b" +uuid = "7d512f48-7fb1-5a58-b986-67e6dc259f01" +version = "0.7.0" + +[[deps.InvertedIndices]] +git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038" +uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" +version = "1.3.0" + +[[deps.IrrationalConstants]] +git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" +uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" +version = "0.2.2" + +[[deps.IterationControl]] +deps = ["EarlyStopping", "InteractiveUtils"] +git-tree-sha1 = "e663925ebc3d93c1150a7570d114f9ea2f664726" +uuid = "b3c1a2ee-3fec-4384-bf48-272ea71de57c" +version = "0.5.4" + +[[deps.IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[deps.JLD2]] +deps = ["FileIO", "MacroTools", "Mmap", "OrderedCollections", "Pkg", "PrecompileTools", "Reexport", "Requires", "TranscodingStreams", "UUIDs", "Unicode"] +git-tree-sha1 = "bdbe8222d2f5703ad6a7019277d149ec6d78c301" +uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +version = "0.4.48" + +[[deps.JLFzf]] +deps = ["Pipe", "REPL", "Random", "fzf_jll"] +git-tree-sha1 = "a53ebe394b71470c7f97c2e7e170d51df21b17af" +uuid = "1019f520-868f-41f5-a6de-eb00f4b6a39c" +version = "0.1.7" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.5.0" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.4" + +[[deps.JSON3]] +deps = ["Dates", "Mmap", "Parsers", "PrecompileTools", "StructTypes", "UUIDs"] +git-tree-sha1 = "eb3edce0ed4fa32f75a0a11217433c31d56bd48b" +uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" +version = "1.14.0" + + [deps.JSON3.extensions] + JSON3ArrowExt = ["ArrowTypes"] + + [deps.JSON3.weakdeps] + ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd" + +[[deps.JpegTurbo_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "c84a835e1a09b289ffcd2271bf2a337bbdda6637" +uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" +version = "3.0.3+0" + +[[deps.JuliaNVTXCallbacks_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "af433a10f3942e882d3c671aacb203e006a5808f" +uuid = "9c1d0b0a-7046-5b2e-a33f-ea22f176ac7e" +version = "0.2.1+0" + +[[deps.JuliaVariables]] +deps = ["MLStyle", "NameResolution"] +git-tree-sha1 = "49fb3cb53362ddadb4415e9b73926d6b40709e70" +uuid = "b14d175d-62b4-44ba-8fb7-3064adc8c3ec" +version = "0.2.4" + +[[deps.KernelAbstractions]] +deps = ["Adapt", "Atomix", "InteractiveUtils", "LinearAlgebra", "MacroTools", "PrecompileTools", "Requires", "SparseArrays", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"] +git-tree-sha1 = "db02395e4c374030c53dc28f3c1d33dec35f7272" +uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c" +version = "0.9.19" + + [deps.KernelAbstractions.extensions] + EnzymeExt = "EnzymeCore" + + [deps.KernelAbstractions.weakdeps] + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + +[[deps.LAME_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "170b660facf5df5de098d866564877e119141cbd" +uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d" +version = "3.100.2+0" + +[[deps.LERC_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "bf36f528eec6634efc60d7ec062008f171071434" +uuid = "88015f11-f218-50d7-93a8-a6af411a945d" +version = "3.0.0+1" + +[[deps.LLVM]] +deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Preferences", "Printf", "Requires", "Unicode"] +git-tree-sha1 = "839c82932db86740ae729779e610f07a1640be9a" +uuid = "929cbde3-209d-540e-8aea-75f648917ca0" +version = "6.6.3" +weakdeps = ["BFloat16s"] + + [deps.LLVM.extensions] + BFloat16sExt = "BFloat16s" + +[[deps.LLVMExtra_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "88b916503aac4fb7f701bb625cd84ca5dd1677bc" +uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab" +version = "0.0.29+0" + +[[deps.LLVMLoopInfo]] +git-tree-sha1 = "2e5c102cfc41f48ae4740c7eca7743cc7e7b75ea" +uuid = "8b046642-f1f6-4319-8d3c-209ddc03c586" +version = "1.0.0" + +[[deps.LLVMOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "d986ce2d884d49126836ea94ed5bfb0f12679713" +uuid = "1d63c593-3942-5779-bab2-d838dc0a180e" +version = "15.0.7+0" + +[[deps.LZO_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "70c5da094887fd2cae843b8db33920bac4b6f07d" +uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac" +version = "2.10.2+0" + +[[deps.LaTeXStrings]] +git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec" +uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +version = "1.3.1" + +[[deps.Latexify]] +deps = ["Format", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "OrderedCollections", "Requires"] +git-tree-sha1 = "e0b5cd21dc1b44ec6e64f351976f961e6f31d6c4" +uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" +version = "0.16.3" + + [deps.Latexify.extensions] + DataFramesExt = "DataFrames" + SymEngineExt = "SymEngine" + + [deps.Latexify.weakdeps] + DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" + SymEngine = "123dc426-2d89-5057-bbad-38513e3affd8" + +[[deps.LatinHypercubeSampling]] +deps = ["Random", "StableRNGs", "StatsBase", "Test"] +git-tree-sha1 = "825289d43c753c7f1bf9bed334c253e9913997f8" +uuid = "a5e1c1ea-c99a-51d3-a14d-a9a37257b02d" +version = "1.9.0" + +[[deps.LazyArtifacts]] +deps = ["Artifacts", "Pkg"] +uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" + +[[deps.LazyModules]] +git-tree-sha1 = "a560dd966b386ac9ae60bdd3a3d3a326062d3c3e" +uuid = "8cdb02fc-e678-4876-92c5-9defec4f444e" +version = "0.3.1" + +[[deps.LearnAPI]] +deps = ["InteractiveUtils", "Statistics"] +git-tree-sha1 = "ec695822c1faaaa64cee32d0b21505e1977b4809" +uuid = "92ad9a40-7767-427a-9ee6-6e577f1266cb" +version = "0.1.0" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.4.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.6.4+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.Libffi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "0b4a5d71f3e5200a7dff793393e09dfc2d874290" +uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490" +version = "3.2.2+1" + +[[deps.Libgcrypt_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll"] +git-tree-sha1 = "9fd170c4bbfd8b935fdc5f8b7aa33532c991a673" +uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4" +version = "1.8.11+0" + +[[deps.Libglvnd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"] +git-tree-sha1 = "6f73d1dd803986947b2c750138528a999a6c7733" +uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29" +version = "1.6.0+0" + +[[deps.Libgpg_error_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "fbb1f2bef882392312feb1ede3615ddc1e9b99ed" +uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8" +version = "1.49.0+0" + +[[deps.Libiconv_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "f9557a255370125b405568f9767d6d195822a175" +uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" +version = "1.17.0+0" + +[[deps.Libmount_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "0c4f9c4f1a50d8f35048fa0532dabbadf702f81e" +uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9" +version = "2.40.1+0" + +[[deps.Libtiff_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "XZ_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "2da088d113af58221c52828a80378e16be7d037a" +uuid = "89763e89-9b03-5906-acba-b20f662cd828" +version = "4.5.1+1" + +[[deps.Libuuid_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "5ee6203157c120d79034c748a2acba45b82b8807" +uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700" +version = "2.40.1+0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[deps.LogExpFunctions]] +deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] +git-tree-sha1 = "18144f3e9cbe9b15b070288eef858f71b291ce37" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.3.27" + + [deps.LogExpFunctions.extensions] + LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" + LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" + LogExpFunctionsInverseFunctionsExt = "InverseFunctions" + + [deps.LogExpFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.LoggingExtras]] +deps = ["Dates", "Logging"] +git-tree-sha1 = "c1dd6d7978c12545b4179fb6153b9250c96b0075" +uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" +version = "1.0.3" + +[[deps.MAT]] +deps = ["BufferedStreams", "CodecZlib", "HDF5", "SparseArrays"] +git-tree-sha1 = "1d2dd9b186742b0f317f2530ddcbf00eebb18e96" +uuid = "23992714-dd62-5051-b70f-ba57cb901cac" +version = "0.10.7" + +[[deps.MLDatasets]] +deps = ["CSV", "Chemfiles", "DataDeps", "DataFrames", "DelimitedFiles", "FileIO", "FixedPointNumbers", "GZip", "Glob", "HDF5", "ImageShow", "JLD2", "JSON3", "LazyModules", "MAT", "MLUtils", "NPZ", "Pickle", "Printf", "Requires", "SparseArrays", "Statistics", "Tables"] +git-tree-sha1 = "aab72207b3c687086a400be710650a57494992bd" +uuid = "eb30cadb-4394-5ae3-aed4-317e484a6458" +version = "0.7.14" + +[[deps.MLFlowClient]] +deps = ["Dates", "FilePathsBase", "HTTP", "JSON", "ShowCases", "URIs", "UUIDs"] +git-tree-sha1 = "9abb12b62debc27261c008daa13627255bf79967" +uuid = "64a0f543-368b-4a9a-827a-e71edb2a0b83" +version = "0.5.1" + +[[deps.MLJ]] +deps = ["CategoricalArrays", "ComputationalResources", "Distributed", "Distributions", "LinearAlgebra", "MLJBalancing", "MLJBase", "MLJEnsembles", "MLJFlow", "MLJIteration", "MLJModels", "MLJTuning", "OpenML", "Pkg", "ProgressMeter", "Random", "Reexport", "ScientificTypes", "StatisticalMeasures", "Statistics", "StatsBase", "Tables"] +git-tree-sha1 = "bd2072e9cd65be0a3cb841f3d8cda1d2cacfe5db" +uuid = "add582a8-e3ab-11e8-2d5e-e98b27df1bc7" +version = "0.20.5" + +[[deps.MLJBalancing]] +deps = ["MLJBase", "MLJModelInterface", "MLUtils", "OrderedCollections", "Random", "StatsBase"] +git-tree-sha1 = "f02e28f9f3c54a138db12a97a5d823e5e572c2d6" +uuid = "45f359ea-796d-4f51-95a5-deb1a414c586" +version = "0.1.4" + +[[deps.MLJBase]] +deps = ["CategoricalArrays", "CategoricalDistributions", "ComputationalResources", "Dates", "DelimitedFiles", "Distributed", "Distributions", "InteractiveUtils", "InvertedIndices", "LearnAPI", "LinearAlgebra", "MLJModelInterface", "Missings", "OrderedCollections", "Parameters", "PrettyTables", "ProgressMeter", "Random", "RecipesBase", "Reexport", "ScientificTypes", "Serialization", "StatisticalMeasuresBase", "StatisticalTraits", "Statistics", "StatsBase", "Tables"] +git-tree-sha1 = "aba2ffd56a9a97027b4102055dd9f909a6e35d12" +uuid = "a7f614a8-145f-11e9-1d2a-a57a1082229d" +version = "1.3.0" +weakdeps = ["StatisticalMeasures"] + + [deps.MLJBase.extensions] + DefaultMeasuresExt = "StatisticalMeasures" + +[[deps.MLJEnsembles]] +deps = ["CategoricalArrays", "CategoricalDistributions", "ComputationalResources", "Distributed", "Distributions", "MLJModelInterface", "ProgressMeter", "Random", "ScientificTypesBase", "StatisticalMeasuresBase", "StatsBase"] +git-tree-sha1 = "d3dd87194ec96892bb243b65225a462c7ab16e66" +uuid = "50ed68f4-41fd-4504-931a-ed422449fee0" +version = "0.4.2" + +[[deps.MLJFlow]] +deps = ["MLFlowClient", "MLJBase", "MLJModelInterface"] +git-tree-sha1 = "508bff8071d7d1902d6f1b9d1e868d58821f1cfe" +uuid = "7b7b8358-b45c-48ea-a8ef-7ca328ad328f" +version = "0.5.0" + +[[deps.MLJFlux]] +deps = ["CategoricalArrays", "ColorTypes", "ComputationalResources", "Flux", "MLJModelInterface", "Metalhead", "ProgressMeter", "Random", "Statistics", "Tables"] +git-tree-sha1 = "72935b7de07a7f6b72fd49ecc7898dac79248d46" +uuid = "094fc8d1-fd35-5302-93ea-dabda2abf845" +version = "0.4.0" + +[[deps.MLJIteration]] +deps = ["IterationControl", "MLJBase", "Random", "Serialization"] +git-tree-sha1 = "1e909ee09417ebd18559c4d9c15febff887192df" +uuid = "614be32b-d00c-4edb-bd02-1eb411ab5e55" +version = "0.6.1" + +[[deps.MLJModelInterface]] +deps = ["Random", "ScientificTypesBase", "StatisticalTraits"] +git-tree-sha1 = "d2a45e1b5998ba3fdfb6cfe0c81096d4c7fb40e7" +uuid = "e80e1ace-859a-464e-9ed9-23947d8ae3ea" +version = "1.9.6" + +[[deps.MLJModels]] +deps = ["CategoricalArrays", "CategoricalDistributions", "Combinatorics", "Dates", "Distances", "Distributions", "InteractiveUtils", "LinearAlgebra", "MLJModelInterface", "Markdown", "OrderedCollections", "Parameters", "Pkg", "PrettyPrinting", "REPL", "Random", "RelocatableFolders", "ScientificTypes", "StatisticalTraits", "Statistics", "StatsBase", "Tables"] +git-tree-sha1 = "410da88e0e6ece5467293d2c76b51b7c6df7d072" +uuid = "d491faf4-2d78-11e9-2867-c94bc002c0b7" +version = "0.16.17" + +[[deps.MLJTuning]] +deps = ["ComputationalResources", "Distributed", "Distributions", "LatinHypercubeSampling", "MLJBase", "ProgressMeter", "Random", "RecipesBase", "StatisticalMeasuresBase"] +git-tree-sha1 = "efb9ec087ab9589afad0002e69fdd9cd38ef1643" +uuid = "03970b2e-30c4-11ea-3135-d1576263f10f" +version = "0.8.6" + +[[deps.MLStyle]] +git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8" +uuid = "d8e11817-5142-5d16-987a-aa16d5891078" +version = "0.4.17" + +[[deps.MLUtils]] +deps = ["ChainRulesCore", "Compat", "DataAPI", "DelimitedFiles", "FLoops", "NNlib", "Random", "ShowCases", "SimpleTraits", "Statistics", "StatsBase", "Tables", "Transducers"] +git-tree-sha1 = "b45738c2e3d0d402dffa32b2c1654759a2ac35a4" +uuid = "f1d291b0-491e-4a28-83b9-f70985020b54" +version = "0.4.4" + +[[deps.MPICH_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "4099bb6809ac109bfc17d521dad33763bcf026b7" +uuid = "7cb0a576-ebde-5e09-9194-50597f1243b4" +version = "4.2.1+1" + +[[deps.MPIPreferences]] +deps = ["Libdl", "Preferences"] +git-tree-sha1 = "c105fe467859e7f6e9a852cb15cb4301126fac07" +uuid = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267" +version = "0.1.11" + +[[deps.MPItrampoline_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "ce0ca3dd147c43de175c5aff161315a424f4b8ac" +uuid = "f1f71cc9-e9ae-5b93-9b94-4fe0e1ad3748" +version = "5.3.3+1" + +[[deps.MacroTools]] +deps = ["Markdown", "Random"] +git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.13" + +[[deps.MappedArrays]] +git-tree-sha1 = "2dab0221fe2b0f2cb6754eaa743cc266339f527e" +uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900" +version = "0.4.2" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MbedTLS]] +deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] +git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" +uuid = "739be429-bea8-5141-9913-cc70e7f3736d" +version = "1.1.9" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.2+1" + +[[deps.Measures]] +git-tree-sha1 = "c13304c81eec1ed3af7fc20e75fb6b26092a1102" +uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e" +version = "0.3.2" + +[[deps.Metalhead]] +deps = ["Artifacts", "BSON", "ChainRulesCore", "Flux", "Functors", "JLD2", "LazyArtifacts", "MLUtils", "NNlib", "PartialFunctions", "Random", "Statistics"] +git-tree-sha1 = "5aac9a2b511afda7bf89df5044a2e0b429f83152" +uuid = "dbeba491-748d-5e0e-a39e-b530a07fa0cc" +version = "0.9.3" +weakdeps = ["CUDA"] + + [deps.Metalhead.extensions] + MetalheadCUDAExt = "CUDA" + +[[deps.MicroCollections]] +deps = ["BangBang", "InitialValues", "Setfield"] +git-tree-sha1 = "629afd7d10dbc6935ec59b32daeb33bc4460a42e" +uuid = "128add7d-3638-4c79-886c-908ea0c25c34" +version = "0.1.4" + +[[deps.MicrosoftMPI_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "f12a29c4400ba812841c6ace3f4efbb6dbb3ba01" +uuid = "9237b28f-5490-5468-be7b-bb81f5f5e6cf" +version = "10.1.4+2" + +[[deps.Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "ec4f7fbeab05d7747bdf98eb74d130a2a2ed298d" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "1.2.0" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.MosaicViews]] +deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"] +git-tree-sha1 = "7b86a5d4d70a9f5cdf2dacb3cbe6d251d1a61dbe" +uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389" +version = "0.3.4" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.1.10" + +[[deps.NNlib]] +deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Pkg", "Random", "Requires", "Statistics"] +git-tree-sha1 = "3d4617f943afe6410206a5294a95948c8d1b35bd" +uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd" +version = "0.9.17" + + [deps.NNlib.extensions] + NNlibAMDGPUExt = "AMDGPU" + NNlibCUDACUDNNExt = ["CUDA", "cuDNN"] + NNlibCUDAExt = "CUDA" + NNlibEnzymeCoreExt = "EnzymeCore" + + [deps.NNlib.weakdeps] + AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd" + +[[deps.NPZ]] +deps = ["FileIO", "ZipFile"] +git-tree-sha1 = "60a8e272fe0c5079363b28b0953831e2dd7b7e6f" +uuid = "15e1cf62-19b3-5cfa-8e77-841668bca605" +version = "0.4.3" + +[[deps.NVTX]] +deps = ["Colors", "JuliaNVTXCallbacks_jll", "Libdl", "NVTX_jll"] +git-tree-sha1 = "53046f0483375e3ed78e49190f1154fa0a4083a1" +uuid = "5da4648a-3479-48b8-97b9-01cb529c0a1f" +version = "0.3.4" + +[[deps.NVTX_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "ce3269ed42816bf18d500c9f63418d4b0d9f5a3b" +uuid = "e98f9f5b-d649-5603-91fd-7774390e6439" +version = "3.1.0+2" + +[[deps.NaNMath]] +deps = ["OpenLibm_jll"] +git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" +uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +version = "1.0.2" + +[[deps.NameResolution]] +deps = ["PrettyPrint"] +git-tree-sha1 = "1a0fa0e9613f46c9b8c11eee38ebb4f590013c5e" +uuid = "71a1bf82-56d0-4bbc-8a3c-48b961074391" +version = "0.1.5" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.OffsetArrays]] +git-tree-sha1 = "e64b4f5ea6b7389f6f046d13d4896a8f9c1ba71e" +uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +version = "1.14.0" +weakdeps = ["Adapt"] + + [deps.OffsetArrays.extensions] + OffsetArraysAdaptExt = "Adapt" + +[[deps.Ogg_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "887579a3eb005446d514ab7aeac5d1d027658b8f" +uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051" +version = "1.3.5+1" + +[[deps.OneHotArrays]] +deps = ["Adapt", "ChainRulesCore", "Compat", "GPUArraysCore", "LinearAlgebra", "NNlib"] +git-tree-sha1 = "963a3f28a2e65bb87a68033ea4a616002406037d" +uuid = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f" +version = "0.2.5" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.23+4" + +[[deps.OpenLibm_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "05823500-19ac-5b8b-9628-191a04bc5112" +version = "0.8.1+2" + +[[deps.OpenML]] +deps = ["ARFFFiles", "HTTP", "JSON", "Markdown", "Pkg", "Scratch"] +git-tree-sha1 = "6efb039ae888699d5a74fb593f6f3e10c7193e33" +uuid = "8b6db2d4-7670-4922-a472-f9537c81ab66" +version = "0.3.1" + +[[deps.OpenMPI_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "e25c1778a98e34219a00455d6e4384e017ea9762" +uuid = "fe0851c0-eecd-5654-98d4-656369965a5c" +version = "4.1.6+0" + +[[deps.OpenSSL]] +deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] +git-tree-sha1 = "38cb508d080d21dc1128f7fb04f20387ed4c0af4" +uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" +version = "1.4.3" + +[[deps.OpenSSL_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "3da7367955dcc5c54c1ba4d402ccdc09a1a3e046" +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "3.0.13+1" + +[[deps.OpenSpecFun_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.5+0" + +[[deps.Optimisers]] +deps = ["ChainRulesCore", "Functors", "LinearAlgebra", "Random", "Statistics"] +git-tree-sha1 = "6572fe0c5b74431aaeb0b18a4aa5ef03c84678be" +uuid = "3bd65402-5787-11e9-1adc-39752487f4e2" +version = "0.3.3" + +[[deps.Opus_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720" +uuid = "91d4177d-7536-5919-b921-800302f37372" +version = "1.3.2+0" + +[[deps.OrderedCollections]] +git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.6.3" + +[[deps.PCRE2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" +version = "10.42.0+1" + +[[deps.PDMats]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "949347156c25054de2db3b166c52ac4728cbad65" +uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" +version = "0.11.31" + +[[deps.PackageExtensionCompat]] +git-tree-sha1 = "fb28e33b8a95c4cee25ce296c817d89cc2e53518" +uuid = "65ce6f38-6b18-4e1d-a461-8949797d7930" +version = "1.0.2" +weakdeps = ["Requires", "TOML"] + +[[deps.PaddedViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "0fac6313486baae819364c52b4f483450a9d793f" +uuid = "5432bcbf-9aad-5242-b902-cca2824c8663" +version = "0.5.12" + +[[deps.Parameters]] +deps = ["OrderedCollections", "UnPack"] +git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" +uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a" +version = "0.12.3" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.8.1" + +[[deps.PartialFunctions]] +deps = ["MacroTools"] +git-tree-sha1 = "47b49a4dbc23b76682205c646252c0f9e1eb75af" +uuid = "570af359-4316-4cb7-8c74-252c00c2016b" +version = "1.2.0" + +[[deps.PeriodicTable]] +deps = ["Base64", "Unitful"] +git-tree-sha1 = "238aa6298007565529f911b734e18addd56985e1" +uuid = "7b2266bf-644c-5ea3-82d8-af4bbd25a884" +version = "1.2.1" + +[[deps.Pickle]] +deps = ["BFloat16s", "DataStructures", "InternedStrings", "Mmap", "Serialization", "SparseArrays", "StridedViews", "StringEncodings", "ZipFile"] +git-tree-sha1 = "e99da19b86b7e1547b423fc1721b260cfbe83acb" +uuid = "fbb45041-c46e-462f-888f-7c521cafbc2c" +version = "0.3.5" + +[[deps.Pipe]] +git-tree-sha1 = "6842804e7867b115ca9de748a0cf6b364523c16d" +uuid = "b98c9c47-44ae-5843-9183-064241ee97a0" +version = "1.3.0" + +[[deps.Pixman_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "Libdl"] +git-tree-sha1 = "35621f10a7531bc8fa58f74610b1bfb70a3cfc6b" +uuid = "30392449-352a-5448-841d-b1acce4e97dc" +version = "0.43.4+0" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.10.0" + +[[deps.PlotThemes]] +deps = ["PlotUtils", "Statistics"] +git-tree-sha1 = "1f03a2d339f42dca4a4da149c7e15e9b896ad899" +uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a" +version = "3.1.0" + +[[deps.PlotUtils]] +deps = ["ColorSchemes", "Colors", "Dates", "PrecompileTools", "Printf", "Random", "Reexport", "Statistics"] +git-tree-sha1 = "7b1a9df27f072ac4c9c7cbe5efb198489258d1f5" +uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043" +version = "1.4.1" + +[[deps.Plots]] +deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "JLFzf", "JSON", "LaTeXStrings", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "Pkg", "PlotThemes", "PlotUtils", "PrecompileTools", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "RelocatableFolders", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs", "UnicodeFun", "UnitfulLatexify", "Unzip"] +git-tree-sha1 = "442e1e7ac27dd5ff8825c3fa62fbd1e86397974b" +uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +version = "1.40.4" + + [deps.Plots.extensions] + FileIOExt = "FileIO" + GeometryBasicsExt = "GeometryBasics" + IJuliaExt = "IJulia" + ImageInTerminalExt = "ImageInTerminal" + UnitfulExt = "Unitful" + + [deps.Plots.weakdeps] + FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" + GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" + IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" + ImageInTerminal = "d8c32880-2388-543b-8c61-d9f865259254" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.PooledArrays]] +deps = ["DataAPI", "Future"] +git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3" +uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" +version = "1.4.3" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.1" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.PrettyPrint]] +git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4" +uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98" +version = "0.2.0" + +[[deps.PrettyPrinting]] +git-tree-sha1 = "142ee93724a9c5d04d78df7006670a93ed1b244e" +uuid = "54e16d92-306c-5ea0-a30b-337be88ac337" +version = "0.4.2" + +[[deps.PrettyTables]] +deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"] +git-tree-sha1 = "66b20dd35966a748321d3b2537c4584cf40387c7" +uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" +version = "2.3.2" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.ProgressLogging]] +deps = ["Logging", "SHA", "UUIDs"] +git-tree-sha1 = "80d919dee55b9c50e8d9e2da5eeafff3fe58b539" +uuid = "33c8b6b6-d38a-422a-b730-caa89a2f386c" +version = "0.1.4" + +[[deps.ProgressMeter]] +deps = ["Distributed", "Printf"] +git-tree-sha1 = "763a8ceb07833dd51bb9e3bbca372de32c0605ad" +uuid = "92933f4c-e287-5a05-a399-4b506db050ca" +version = "1.10.0" + +[[deps.PtrArrays]] +git-tree-sha1 = "f011fbb92c4d401059b2212c05c0601b70f8b759" +uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" +version = "1.2.0" + +[[deps.Qt6Base_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Vulkan_Loader_jll", "Xorg_libSM_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_cursor_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "libinput_jll", "xkbcommon_jll"] +git-tree-sha1 = "37b7bb7aabf9a085e0044307e1717436117f2b3b" +uuid = "c0090381-4147-56d7-9ebc-da0b1113ec56" +version = "6.5.3+1" + +[[deps.QuadGK]] +deps = ["DataStructures", "LinearAlgebra"] +git-tree-sha1 = "9b23c31e76e333e6fb4c1595ae6afa74966a729e" +uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" +version = "2.9.4" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.Random123]] +deps = ["Random", "RandomNumbers"] +git-tree-sha1 = "4743b43e5a9c4a2ede372de7061eed81795b12e7" +uuid = "74087812-796a-5b5d-8853-05524746bad3" +version = "1.7.0" + +[[deps.RandomNumbers]] +deps = ["Random", "Requires"] +git-tree-sha1 = "043da614cc7e95c703498a491e2c21f58a2b8111" +uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143" +version = "1.5.3" + +[[deps.RealDot]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9" +uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" +version = "0.1.0" + +[[deps.RecipesBase]] +deps = ["PrecompileTools"] +git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +version = "1.3.4" + +[[deps.RecipesPipeline]] +deps = ["Dates", "NaNMath", "PlotUtils", "PrecompileTools", "RecipesBase"] +git-tree-sha1 = "45cf9fd0ca5839d06ef333c8201714e888486342" +uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" +version = "0.6.12" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.RelocatableFolders]] +deps = ["SHA", "Scratch"] +git-tree-sha1 = "ffdaf70d81cf6ff22c2b6e733c900c3321cab864" +uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" +version = "1.0.1" + +[[deps.Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.3.0" + +[[deps.Rmath]] +deps = ["Random", "Rmath_jll"] +git-tree-sha1 = "f65dcb5fa46aee0cf9ed6274ccbd597adc49aa7b" +uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" +version = "0.7.1" + +[[deps.Rmath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "d483cd324ce5cf5d61b77930f0bbd6cb61927d21" +uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" +version = "0.4.2+0" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.ScientificTypes]] +deps = ["CategoricalArrays", "ColorTypes", "Dates", "Distributions", "PrettyTables", "Reexport", "ScientificTypesBase", "StatisticalTraits", "Tables"] +git-tree-sha1 = "75ccd10ca65b939dab03b812994e571bf1e3e1da" +uuid = "321657f4-b219-11e9-178b-2701a2544e81" +version = "3.0.2" + +[[deps.ScientificTypesBase]] +git-tree-sha1 = "a8e18eb383b5ecf1b5e6fc237eb39255044fd92b" +uuid = "30f210dd-8aff-4c5f-94ba-8e64358c1161" +version = "3.0.0" + +[[deps.Scratch]] +deps = ["Dates"] +git-tree-sha1 = "3bac05bc7e74a75fd9cba4295cde4045d9fe2386" +uuid = "6c6a2e73-6563-6170-7368-637461726353" +version = "1.2.1" + +[[deps.SentinelArrays]] +deps = ["Dates", "Random"] +git-tree-sha1 = "90b4f68892337554d31cdcdbe19e48989f26c7e6" +uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" +version = "1.4.3" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.Setfield]] +deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"] +git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac" +uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46" +version = "1.1.1" + +[[deps.ShowCases]] +git-tree-sha1 = "7f534ad62ab2bd48591bdeac81994ea8c445e4a5" +uuid = "605ecd9f-84a6-4c9e-81e2-4798472b76a3" +version = "0.1.0" + +[[deps.Showoff]] +deps = ["Dates", "Grisu"] +git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de" +uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f" +version = "1.0.3" + +[[deps.SimpleBufferStream]] +git-tree-sha1 = "874e8867b33a00e784c8a7e4b60afe9e037b74e1" +uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" +version = "1.1.0" + +[[deps.SimpleTraits]] +deps = ["InteractiveUtils", "MacroTools"] +git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" +uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" +version = "0.9.4" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.SoftGlobalScope]] +deps = ["REPL"] +git-tree-sha1 = "986ec2b6162ccb95de5892ed17832f95badf770c" +uuid = "b85f4697-e234-5449-a836-ec8e2f98b302" +version = "1.1.0" + +[[deps.SortingAlgorithms]] +deps = ["DataStructures"] +git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "1.2.1" + +[[deps.SparseArrays]] +deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.10.0" + +[[deps.SparseInverseSubset]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "52962839426b75b3021296f7df242e40ecfc0852" +uuid = "dc90abb0-5640-4711-901d-7e5b23a2fada" +version = "0.1.2" + +[[deps.SpecialFunctions]] +deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] +git-tree-sha1 = "2f5d4697f21388cbe1ff299430dd169ef97d7e14" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "2.4.0" +weakdeps = ["ChainRulesCore"] + + [deps.SpecialFunctions.extensions] + SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" + +[[deps.SplittablesBase]] +deps = ["Setfield", "Test"] +git-tree-sha1 = "e08a62abc517eb79667d0a29dc08a3b589516bb5" +uuid = "171d559e-b47b-412a-8079-5efa626c420e" +version = "0.1.15" + +[[deps.StableRNGs]] +deps = ["Random"] +git-tree-sha1 = "83e6cce8324d49dfaf9ef059227f91ed4441a8e5" +uuid = "860ef19b-820b-49d6-a774-d7a799459cd3" +version = "1.0.2" + +[[deps.StackViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "46e589465204cd0c08b4bd97385e4fa79a0c770c" +uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15" +version = "0.1.1" + +[[deps.StaticArrays]] +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "9ae599cd7529cfce7fea36cf00a62cfc56f0f37c" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.9.4" +weakdeps = ["ChainRulesCore", "Statistics"] + + [deps.StaticArrays.extensions] + StaticArraysChainRulesCoreExt = "ChainRulesCore" + StaticArraysStatisticsExt = "Statistics" + +[[deps.StaticArraysCore]] +git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" +uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" +version = "1.4.2" + +[[deps.StatisticalMeasures]] +deps = ["CategoricalArrays", "CategoricalDistributions", "Distributions", "LearnAPI", "LinearAlgebra", "MacroTools", "OrderedCollections", "PrecompileTools", "ScientificTypesBase", "StatisticalMeasuresBase", "Statistics", "StatsBase"] +git-tree-sha1 = "8b5a165b0ee2b361d692636bfb423b19abfd92b3" +uuid = "a19d573c-0a75-4610-95b3-7071388c7541" +version = "0.1.6" + + [deps.StatisticalMeasures.extensions] + LossFunctionsExt = "LossFunctions" + ScientificTypesExt = "ScientificTypes" + + [deps.StatisticalMeasures.weakdeps] + LossFunctions = "30fc2ffe-d236-52d8-8643-a9d8f7c094a7" + ScientificTypes = "321657f4-b219-11e9-178b-2701a2544e81" + +[[deps.StatisticalMeasuresBase]] +deps = ["CategoricalArrays", "InteractiveUtils", "MLUtils", "MacroTools", "OrderedCollections", "PrecompileTools", "ScientificTypesBase", "Statistics"] +git-tree-sha1 = "17dfb22e2e4ccc9cd59b487dce52883e0151b4d3" +uuid = "c062fc1d-0d66-479b-b6ac-8b44719de4cc" +version = "0.1.1" + +[[deps.StatisticalTraits]] +deps = ["ScientificTypesBase"] +git-tree-sha1 = "30b9236691858e13f167ce829490a68e1a597782" +uuid = "64bff920-2084-43da-a3e6-9bb72801c0c9" +version = "3.2.0" + +[[deps.Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.10.0" + +[[deps.StatsAPI]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" +uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" +version = "1.7.0" + +[[deps.StatsBase]] +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "5cf7606d6cef84b543b483848d4ae08ad9832b21" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.34.3" + +[[deps.StatsFuns]] +deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] +git-tree-sha1 = "cef0472124fab0695b58ca35a77c6fb942fdab8a" +uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" +version = "1.3.1" + + [deps.StatsFuns.extensions] + StatsFunsChainRulesCoreExt = "ChainRulesCore" + StatsFunsInverseFunctionsExt = "InverseFunctions" + + [deps.StatsFuns.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.StridedViews]] +deps = ["LinearAlgebra", "PackageExtensionCompat"] +git-tree-sha1 = "5b765c4e401693ab08981989f74a36a010aa1d8e" +uuid = "4db3bf67-4bd7-4b4e-b153-31dc3fb37143" +version = "0.2.2" +weakdeps = ["CUDA"] + + [deps.StridedViews.extensions] + StridedViewsCUDAExt = "CUDA" + +[[deps.StringEncodings]] +deps = ["Libiconv_jll"] +git-tree-sha1 = "b765e46ba27ecf6b44faf70df40c57aa3a547dcb" +uuid = "69024149-9ee7-55f6-a4c4-859efe599b68" +version = "0.3.7" + +[[deps.StringManipulation]] +deps = ["PrecompileTools"] +git-tree-sha1 = "a04cabe79c5f01f4d723cc6704070ada0b9d46d5" +uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" +version = "0.3.4" + +[[deps.StructArrays]] +deps = ["ConstructionBase", "DataAPI", "Tables"] +git-tree-sha1 = "f4dc295e983502292c4c3f951dbb4e985e35b3be" +uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" +version = "0.6.18" +weakdeps = ["Adapt", "GPUArraysCore", "SparseArrays", "StaticArrays"] + + [deps.StructArrays.extensions] + StructArraysAdaptExt = "Adapt" + StructArraysGPUArraysCoreExt = "GPUArraysCore" + StructArraysSparseArraysExt = "SparseArrays" + StructArraysStaticArraysExt = "StaticArrays" + +[[deps.StructTypes]] +deps = ["Dates", "UUIDs"] +git-tree-sha1 = "ca4bccb03acf9faaf4137a9abc1881ed1841aa70" +uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" +version = "1.10.0" + +[[deps.SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[deps.SuiteSparse_jll]] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] +uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" +version = "7.2.1+1" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[deps.Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.11.1" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.TensorCore]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" +uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" +version = "0.1.1" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.TimerOutputs]] +deps = ["ExprTools", "Printf"] +git-tree-sha1 = "5a13ae8a41237cff5ecf34f73eb1b8f42fff6531" +uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" +version = "0.5.24" + +[[deps.TranscodingStreams]] +git-tree-sha1 = "5d54d076465da49d6746c647022f3b3674e64156" +uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" +version = "0.10.8" +weakdeps = ["Random", "Test"] + + [deps.TranscodingStreams.extensions] + TestExt = ["Test", "Random"] + +[[deps.Transducers]] +deps = ["Adapt", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "ConstructionBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "Setfield", "SplittablesBase", "Tables"] +git-tree-sha1 = "3064e780dbb8a9296ebb3af8f440f787bb5332af" +uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999" +version = "0.4.80" + + [deps.Transducers.extensions] + TransducersBlockArraysExt = "BlockArrays" + TransducersDataFramesExt = "DataFrames" + TransducersLazyArraysExt = "LazyArrays" + TransducersOnlineStatsBaseExt = "OnlineStatsBase" + TransducersReferenceablesExt = "Referenceables" + + [deps.Transducers.weakdeps] + BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" + DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" + LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02" + OnlineStatsBase = "925886fa-5bf2-5e8e-b522-a9147a512338" + Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e" + +[[deps.URIs]] +git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b" +uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +version = "1.5.1" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.UnPack]] +git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b" +uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" +version = "1.0.2" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.UnicodeFun]] +deps = ["REPL"] +git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf" +uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1" +version = "0.4.1" + +[[deps.Unitful]] +deps = ["Dates", "LinearAlgebra", "Random"] +git-tree-sha1 = "dd260903fdabea27d9b6021689b3cd5401a57748" +uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" +version = "1.20.0" + + [deps.Unitful.extensions] + ConstructionBaseUnitfulExt = "ConstructionBase" + InverseFunctionsUnitfulExt = "InverseFunctions" + + [deps.Unitful.weakdeps] + ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.UnitfulAtomic]] +deps = ["Unitful"] +git-tree-sha1 = "903be579194534af1c4b4778d1ace676ca042238" +uuid = "a7773ee8-282e-5fa2-be4e-bd808c38a91a" +version = "1.0.0" + +[[deps.UnitfulLatexify]] +deps = ["LaTeXStrings", "Latexify", "Unitful"] +git-tree-sha1 = "e2d817cc500e960fdbafcf988ac8436ba3208bfd" +uuid = "45397f5d-5981-4c77-b2b3-fc36d6e9b728" +version = "1.6.3" + +[[deps.UnsafeAtomics]] +git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278" +uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f" +version = "0.2.1" + +[[deps.UnsafeAtomicsLLVM]] +deps = ["LLVM", "UnsafeAtomics"] +git-tree-sha1 = "d9f5962fecd5ccece07db1ff006fb0b5271bdfdd" +uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" +version = "0.1.4" + +[[deps.Unzip]] +git-tree-sha1 = "ca0969166a028236229f63514992fc073799bb78" +uuid = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d" +version = "0.2.0" + +[[deps.VersionParsing]] +git-tree-sha1 = "58d6e80b4ee071f5efd07fda82cb9fbe17200868" +uuid = "81def892-9a0e-5fdd-b105-ffc91e053289" +version = "1.3.0" + +[[deps.Vulkan_Loader_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Wayland_jll", "Xorg_libX11_jll", "Xorg_libXrandr_jll", "xkbcommon_jll"] +git-tree-sha1 = "2f0486047a07670caad3a81a075d2e518acc5c59" +uuid = "a44049a8-05dd-5a78-86c9-5fde0876e88c" +version = "1.3.243+0" + +[[deps.Wayland_jll]] +deps = ["Artifacts", "EpollShim_jll", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "7558e29847e99bc3f04d6569e82d0f5c54460703" +uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89" +version = "1.21.0+1" + +[[deps.Wayland_protocols_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "93f43ab61b16ddfb2fd3bb13b3ce241cafb0e6c9" +uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91" +version = "1.31.0+0" + +[[deps.WeakRefStrings]] +deps = ["DataAPI", "InlineStrings", "Parsers"] +git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23" +uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" +version = "1.4.2" + +[[deps.WorkerUtilities]] +git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7" +uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" +version = "1.6.1" + +[[deps.XML2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Zlib_jll"] +git-tree-sha1 = "52ff2af32e591541550bd753c0da8b9bc92bb9d9" +uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" +version = "2.12.7+0" + +[[deps.XSLT_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"] +git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a" +uuid = "aed1982a-8fda-507f-9586-7b0439959a61" +version = "1.1.34+0" + +[[deps.XZ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "ac88fb95ae6447c8dda6a5503f3bafd496ae8632" +uuid = "ffd25f8a-64ca-5728-b0f7-c24cf3aae800" +version = "5.4.6+0" + +[[deps.Xorg_libICE_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "326b4fea307b0b39892b3e85fa451692eda8d46c" +uuid = "f67eecfb-183a-506d-b269-f58e52b52d7c" +version = "1.1.1+0" + +[[deps.Xorg_libSM_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libICE_jll"] +git-tree-sha1 = "3796722887072218eabafb494a13c963209754ce" +uuid = "c834827a-8449-5923-a945-d239c165b7dd" +version = "1.2.4+0" + +[[deps.Xorg_libX11_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] +git-tree-sha1 = "afead5aba5aa507ad5a3bf01f58f82c8d1403495" +uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc" +version = "1.8.6+0" + +[[deps.Xorg_libXau_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6035850dcc70518ca32f012e46015b9beeda49d8" +uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" +version = "1.0.11+0" + +[[deps.Xorg_libXcursor_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"] +git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd" +uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724" +version = "1.2.0+4" + +[[deps.Xorg_libXdmcp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "34d526d318358a859d7de23da945578e8e8727b7" +uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05" +version = "1.1.4+0" + +[[deps.Xorg_libXext_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "d2d1a5c49fae4ba39983f63de6afcbea47194e85" +uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3" +version = "1.3.6+0" + +[[deps.Xorg_libXfixes_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] +git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4" +uuid = "d091e8ba-531a-589c-9de9-94069b037ed8" +version = "5.0.3+4" + +[[deps.Xorg_libXi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"] +git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246" +uuid = "a51aa0fd-4e3c-5386-b890-e753decda492" +version = "1.7.10+4" + +[[deps.Xorg_libXinerama_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"] +git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123" +uuid = "d1454406-59df-5ea1-beac-c340f2130bc3" +version = "1.1.4+4" + +[[deps.Xorg_libXrandr_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"] +git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631" +uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484" +version = "1.5.2+4" + +[[deps.Xorg_libXrender_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "47e45cd78224c53109495b3e324df0c37bb61fbe" +uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" +version = "0.9.11+0" + +[[deps.Xorg_libpthread_stubs_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8fdda4c692503d44d04a0603d9ac0982054635f9" +uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74" +version = "0.1.1+0" + +[[deps.Xorg_libxcb_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"] +git-tree-sha1 = "b4bfde5d5b652e22b9c790ad00af08b6d042b97d" +uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b" +version = "1.15.0+0" + +[[deps.Xorg_libxkbfile_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "730eeca102434283c50ccf7d1ecdadf521a765a4" +uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a" +version = "1.1.2+0" + +[[deps.Xorg_xcb_util_cursor_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_jll", "Xorg_xcb_util_renderutil_jll"] +git-tree-sha1 = "04341cb870f29dcd5e39055f895c39d016e18ccd" +uuid = "e920d4aa-a673-5f3a-b3d7-f755a4d47c43" +version = "0.1.4+0" + +[[deps.Xorg_xcb_util_image_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97" +uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b" +version = "0.4.0+1" + +[[deps.Xorg_xcb_util_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"] +git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1" +uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5" +version = "0.4.0+1" + +[[deps.Xorg_xcb_util_keysyms_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00" +uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7" +version = "0.4.0+1" + +[[deps.Xorg_xcb_util_renderutil_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e" +uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e" +version = "0.3.9+1" + +[[deps.Xorg_xcb_util_wm_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67" +uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361" +version = "0.4.1+1" + +[[deps.Xorg_xkbcomp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxkbfile_jll"] +git-tree-sha1 = "330f955bc41bb8f5270a369c473fc4a5a4e4d3cb" +uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4" +version = "1.4.6+0" + +[[deps.Xorg_xkeyboard_config_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_xkbcomp_jll"] +git-tree-sha1 = "691634e5453ad362044e2ad653e79f3ee3bb98c3" +uuid = "33bec58e-1273-512f-9401-5d533626f822" +version = "2.39.0+0" + +[[deps.Xorg_xtrans_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e92a1a012a10506618f10b7047e478403a046c77" +uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10" +version = "1.5.0+0" + +[[deps.ZMQ]] +deps = ["FileWatching", "PrecompileTools", "Sockets", "ZeroMQ_jll"] +git-tree-sha1 = "8ac0d6e982660047f4ec5ae462acf4b92260f4b3" +uuid = "c2297ded-f4af-51ae-bb23-16f91089e4e1" +version = "1.2.3" + +[[deps.ZeroMQ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "libsodium_jll"] +git-tree-sha1 = "42f97fb27394378591666ab0e9cee369e6d0e1f9" +uuid = "8f1865be-045e-5c20-9c9f-bfbfb0764568" +version = "4.3.5+0" + +[[deps.ZipFile]] +deps = ["Libdl", "Printf", "Zlib_jll"] +git-tree-sha1 = "f492b7fe1698e623024e873244f10d89c95c340a" +uuid = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" +version = "0.10.1" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e678132f07ddb5bfa46857f0d7620fb9be675d3b" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.6+0" + +[[deps.Zygote]] +deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "PrecompileTools", "Random", "Requires", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"] +git-tree-sha1 = "19c586905e78a26f7e4e97f81716057bd6b1bc54" +uuid = "e88e6eb3-aa80-5325-afca-941959d7151f" +version = "0.6.70" + + [deps.Zygote.extensions] + ZygoteColorsExt = "Colors" + ZygoteDistancesExt = "Distances" + ZygoteTrackerExt = "Tracker" + + [deps.Zygote.weakdeps] + Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" + Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + +[[deps.ZygoteRules]] +deps = ["ChainRulesCore", "MacroTools"] +git-tree-sha1 = "27798139afc0a2afa7b1824c206d5e87ea587a00" +uuid = "700de1a5-db45-46bc-99cf-38207098b444" +version = "0.2.5" + +[[deps.cuDNN]] +deps = ["CEnum", "CUDA", "CUDA_Runtime_Discovery", "CUDNN_jll"] +git-tree-sha1 = "1f6a185a8da9bbbc20134b7b935981f70c9b26ad" +uuid = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd" +version = "1.3.1" + +[[deps.eudev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "gperf_jll"] +git-tree-sha1 = "431b678a28ebb559d224c0b6b6d01afce87c51ba" +uuid = "35ca27e7-8b34-5b7f-bca9-bdc33f59eb06" +version = "3.2.9+0" + +[[deps.fzf_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "a68c9655fbe6dfcab3d972808f1aafec151ce3f8" +uuid = "214eeab7-80f7-51ab-84ad-2988db7cef09" +version = "0.43.0+0" + +[[deps.gperf_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "3516a5630f741c9eecb3720b1ec9d8edc3ecc033" +uuid = "1a1c6b14-54f6-533d-8383-74cd7377aa70" +version = "3.1.1+0" + +[[deps.libaec_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "46bf7be2917b59b761247be3f317ddf75e50e997" +uuid = "477f73a3-ac25-53e9-8cc3-50b2fa2566f0" +version = "1.1.2+0" + +[[deps.libaom_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1827acba325fdcdf1d2647fc8d5301dd9ba43a9d" +uuid = "a4ae2306-e953-59d6-aa16-d00cac43593b" +version = "3.9.0+0" + +[[deps.libass_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] +git-tree-sha1 = "5982a94fcba20f02f42ace44b9894ee2b140fe47" +uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0" +version = "0.15.1+0" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.8.0+1" + +[[deps.libevdev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "141fe65dc3efabb0b1d5ba74e91f6ad26f84cc22" +uuid = "2db6ffa8-e38f-5e21-84af-90c45d0032cc" +version = "1.11.0+0" + +[[deps.libfdk_aac_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "daacc84a041563f965be61859a36e17c4e4fcd55" +uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280" +version = "2.0.2+0" + +[[deps.libinput_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "eudev_jll", "libevdev_jll", "mtdev_jll"] +git-tree-sha1 = "ad50e5b90f222cfe78aa3d5183a20a12de1322ce" +uuid = "36db933b-70db-51c0-b978-0f229ee0e533" +version = "1.18.0+0" + +[[deps.libpng_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "d7015d2e18a5fd9a4f47de711837e980519781a4" +uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" +version = "1.6.43+1" + +[[deps.libsodium_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "848ab3d00fe39d6fbc2a8641048f8f272af1c51e" +uuid = "a9144af2-ca23-56d9-984f-0d03f7b5ccf8" +version = "1.0.20+0" + +[[deps.libvorbis_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"] +git-tree-sha1 = "b910cb81ef3fe6e78bf6acee440bda86fd6ae00c" +uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a" +version = "1.3.7+1" + +[[deps.mtdev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "814e154bdb7be91d78b6802843f76b6ece642f11" +uuid = "009596ad-96f7-51b1-9f1b-5ce2d5e8a71e" +version = "1.1.6+0" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.52.0+1" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" + +[[deps.x264_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2" +uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a" +version = "2021.5.5+0" + +[[deps.x265_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9" +uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76" +version = "3.5.0+0" + +[[deps.xkbcommon_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"] +git-tree-sha1 = "9c304562909ab2bab0262639bd4f444d7bc2be37" +uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd" +version = "1.4.1+1" diff --git a/docs/src/extended_examples/MNIST/Project.toml b/docs/src/extended_examples/MNIST/Project.toml new file mode 100644 index 00000000..94a789a2 --- /dev/null +++ b/docs/src/extended_examples/MNIST/Project.toml @@ -0,0 +1,11 @@ +[deps] +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c" +IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" +MLDatasets = "eb30cadb-4394-5ae3-aed4-317e484a6458" +MLJ = "add582a8-e3ab-11e8-2d5e-e98b27df1bc7" +MLJFlux = "094fc8d1-fd35-5302-93ea-dabda2abf845" +MLJIteration = "614be32b-d00c-4edb-bd02-1eb411ab5e55" +MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd" diff --git a/docs/src/extended_examples/MNIST/README.md b/docs/src/extended_examples/MNIST/README.md new file mode 100644 index 00000000..4e6605d1 --- /dev/null +++ b/docs/src/extended_examples/MNIST/README.md @@ -0,0 +1,19 @@ +# Contents + +**Important.** This folder was updated in June 2024 but will no longer be updated. + +For the lastest version of this example see [here](/docs/src/full\ tutorials/MNIST). + +| file | description | +|:----------------------------|:---------------------------------------------------------| +| `notebook.ipynb` | Juptyer notebook (executed) | +| `notebook.unexecuted.ipynb` | Jupyter notebook (unexecuted) | +| `notebook.md` | static markdown (included in MLJFlux.jl docs) | +| `notebook.jl` | executable Julia script annotated with comments | +| `generate.jl` | *maintainers only:* execute to generate first 3 from 4th | + + +# Important + +Scripts or notebooks in this folder cannot be reliably exectued without the accompanying +Manifest.toml and Project.toml files. diff --git a/docs/src/extended_examples/MNIST/generate.jl b/docs/src/extended_examples/MNIST/generate.jl new file mode 100644 index 00000000..f68699de --- /dev/null +++ b/docs/src/extended_examples/MNIST/generate.jl @@ -0,0 +1,5 @@ +# Execute this julia file to generate the notebooks from ../notebook.jl + +joinpath(@__DIR__, "..", "..", "generate.jl") |> include +generate(@__DIR__, execute=false, pluto=false) + diff --git a/docs/src/extended_examples/MNIST/loss.png b/docs/src/extended_examples/MNIST/loss.png new file mode 100644 index 0000000000000000000000000000000000000000..c77e097ac662e2a89e624df25f64e94fec1b0c62 GIT binary patch literal 22198 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

QQPKxKVd-0oFX%gtxSfsBG|OaQ|pj-p}o*? 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 T7<>-ALtHw4*`Pwt^}&Atls+66 literal 0 HcmV?d00001 diff --git a/docs/src/extended_examples/MNIST/notebook.ipynb b/docs/src/extended_examples/MNIST/notebook.ipynb new file mode 100644 index 00000000..19274217 --- /dev/null +++ b/docs/src/extended_examples/MNIST/notebook.ipynb @@ -0,0 +1,2103 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using MLJ to classifiy the MNIST image dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m\u001b[1m Activating\u001b[22m\u001b[39m project at `~/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST`\n" + ] + } + ], + "source": [ + "using Pkg\n", + "const DIR = @__DIR__\n", + "Pkg.activate(DIR)\n", + "Pkg.instantiate()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Julia version** is assumed to be ^1.10" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "using MLJ\n", + "using Flux\n", + "import MLJFlux\n", + "import MLUtils\n", + "import MLJIteration # for `skip`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If running on a GPU, you will also need to `import CUDA` and `import cuDNN`." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "using Plots\n", + "gr(size=(600, 300*(sqrt(5)-1)));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic training" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Downloading the MNIST image dataset:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import MLDatasets: MNIST\n", + "\n", + "ENV[\"DATADEPS_ALWAYS_ACCEPT\"] = true\n", + "images, labels = MNIST(split=:train)[:];" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In MLJ, integers cannot be used for encoding categorical data, so we\n", + "must force the labels to have the `Multiclass` [scientific\n", + "type](https://juliaai.github.io/ScientificTypes.jl/dev/). For\n", + "more on this, see [Working with Categorical\n", + "Data](https://alan-turing-institute.github.io/MLJ.jl/dev/working_with_categorical_data/)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "labels = coerce(labels, Multiclass);\n", + "images = coerce(images, GrayImage);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Checking scientific types:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "@assert scitype(images) <: AbstractVector{<:Image}\n", + "@assert scitype(labels) <: AbstractVector{<:Finite}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looks good." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For general instructions on coercing image data, see [Type coercion\n", + "for image\n", + "data](https://juliaai.github.io/ScientificTypes.jl/dev/#Type-coercion-for-image-data)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "28×28 Array{Gray{Float32},2} with eltype Gray{Float32}:\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) … Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) … Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) … Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " ⋮ ⋱ \n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) … Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) … Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)\n", + " Gray{Float32}(0.0) Gray{Float32}(0.0) Gray{Float32}(0.0)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "images[1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We start by defining a suitable `Builder` object. This is a recipe\n", + "for building the neural network. Our builder will work for images of\n", + "any (constant) size, whether they be color or black and white (ie,\n", + "single or multi-channel). The architecture always consists of six\n", + "alternating convolution and max-pool layers, and a final dense\n", + "layer; the filter size and the number of channels after each\n", + "convolution layer is customisable." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "import MLJFlux\n", + "struct MyConvBuilder\n", + " filter_size::Int\n", + " channels1::Int\n", + " channels2::Int\n", + " channels3::Int\n", + "end\n", + "\n", + "function MLJFlux.build(b::MyConvBuilder, rng, n_in, n_out, n_channels)\n", + " k, c1, c2, c3 = b.filter_size, b.channels1, b.channels2, b.channels3\n", + " mod(k, 2) == 1 || error(\"`filter_size` must be odd. \")\n", + " p = div(k - 1, 2) # padding to preserve image size\n", + " init = Flux.glorot_uniform(rng)\n", + " front = Chain(\n", + " Conv((k, k), n_channels => c1, pad=(p, p), relu, init=init),\n", + " MaxPool((2, 2)),\n", + " Conv((k, k), c1 => c2, pad=(p, p), relu, init=init),\n", + " MaxPool((2, 2)),\n", + " Conv((k, k), c2 => c3, pad=(p, p), relu, init=init),\n", + " MaxPool((2 ,2)),\n", + " MLUtils.flatten)\n", + " d = Flux.outputsize(front, (n_in..., n_channels, 1)) |> first\n", + " return Chain(front, Dense(d, n_out, init=init))\n", + "end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Notes.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- There is no final `softmax` here, as this is applied by default in all MLJFLux\n", + " classifiers. Customisation of this behaviour is controlled using using the `finaliser`\n", + " hyperparameter of the classifier.\n", + "\n", + "- Instead of calculating the padding `p`, Flux can infer the required padding in each\n", + " dimension, which you enable by replacing `pad = (p, p)` with `pad = SamePad()`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now define the MLJ model." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mFor silent loading, specify `verbosity=0`. \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "import MLJFlux ✔\n" + ] + }, + { + "data": { + "text/plain": [ + "ImageClassifier(\n", + " builder = MyConvBuilder(3, 16, 32, 32), \n", + " finaliser = NNlib.softmax, \n", + " optimiser = Adam(0.001, (0.9, 0.999), 1.0e-8, IdDict{Any, Any}()), \n", + " loss = Flux.Losses.crossentropy, \n", + " epochs = 10, \n", + " batch_size = 50, \n", + " lambda = 0.0, \n", + " alpha = 0.0, \n", + " rng = 123, \n", + " optimiser_changes_trigger_retraining = false, \n", + " acceleration = CPU1{Nothing}(nothing))" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ImageClassifier = @load ImageClassifier\n", + "clf = ImageClassifier(\n", + " builder=MyConvBuilder(3, 16, 32, 32),\n", + " batch_size=50,\n", + " epochs=10,\n", + " rng=123,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add Flux options `optimiser=...` and `loss=...` in the above constructor\n", + "call. At present, `loss` must be a Flux-compatible loss, not an MLJ measure. To run on a\n", + "GPU, add to the constructor `acceleration=CUDALib()` and omit `rng`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For illustration purposes, we won't use all the data here:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "501:1000" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train = 1:500\n", + "test = 501:1000" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Binding the model with data in an MLJ machine:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "mach = machine(clf, images, labels);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Training for 10 epochs on the first 500 images:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mTraining machine(ImageClassifier(builder = MyConvBuilder(3, 16, 32, 32), …), …).\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 2.291\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 2.208\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 2.049\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 1.685\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 1.075\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 0.628\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 0.4639\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 0.361\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 0.2921\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mLoss is 0.2478\n" + ] + } + ], + "source": [ + "fit!(mach, rows=train, verbosity=2);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Inspecting:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(training_losses = Float32[2.3242702, 2.2908378, 2.20822, 2.0489829, 1.6850392, 1.0751165, 0.6279615, 0.46388212, 0.36103815, 0.29207793, 0.2478443],)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "report(mach)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(chain = Chain(Chain(Chain(Conv((3, 3), 1 => 16, relu, pad=1), MaxPool((2, 2)), Conv((3, 3), 16 => 32, relu, pad=1), MaxPool((2, 2)), Conv((3, 3), 32 => 32, relu, pad=1), MaxPool((2, 2)), flatten), Dense(288 => 10)), softmax),)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain = fitted_params(mach)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "16-element Vector{Float32}:\n", + " 0.011803599\n", + " 0.05579675\n", + " 8.461591f-5\n", + " 0.013422165\n", + " -0.001925053\n", + " 0.011568692\n", + " -0.00051727734\n", + " -0.0003228416\n", + " 0.03614383\n", + " 0.06365696\n", + " -0.0005846103\n", + " -0.004092362\n", + " 0.0036211032\n", + " 0.0031117066\n", + " 0.02764553\n", + " 0.05152524" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Flux.params(chain)[2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding 20 more epochs:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mUpdating machine(ImageClassifier(builder = MyConvBuilder(3, 16, 32, 32), …), …).\n", + "\u001b[33mOptimising neural net: 100%[=========================] Time: 0:00:40\u001b[39m\n" + ] + } + ], + "source": [ + "clf.epochs = clf.epochs + 20\n", + "fit!(mach, rows=train);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Computing an out-of-sample estimate of the loss:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.36284237158113225" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "predicted_labels = predict(mach, rows=test);\n", + "cross_entropy(predicted_labels, labels[test])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or to fit and predict, in one line:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "PerformanceEvaluation object with these fields:\n", + " model, measure, operation,\n", + " measurement, per_fold, per_observation,\n", + " fitted_params_per_fold, report_per_fold,\n", + " train_test_rows, resampling, repeats\n", + "Extract:\n", + "┌──────────────────────┬───────────┬─────────────┐\n", + "│\u001b[22m measure \u001b[0m│\u001b[22m operation \u001b[0m│\u001b[22m measurement \u001b[0m│\n", + "├──────────────────────┼───────────┼─────────────┤\n", + "│ LogLoss( │ predict │ 0.363 │\n", + "│ tol = 2.22045e-16) │ │ │\n", + "└──────────────────────┴───────────┴─────────────┘\n" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "evaluate!(mach,\n", + " resampling=Holdout(fraction_train=0.5),\n", + " measure=cross_entropy,\n", + " rows=1:1000,\n", + " verbosity=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Wrapping the MLJFlux model with iteration controls" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Any iterative MLJFlux model can be wrapped in *iteration controls*,\n", + "as we demonstrate next. For more on MLJ's `IteratedModel` wrapper,\n", + "see the [MLJ\n", + "documentation](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The \"self-iterating\" classifier, called `iterated_clf` below, is for\n", + "iterating the image classifier defined above until one of the\n", + "following stopping criterion apply:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `Patience(3)`: 3 consecutive increases in the loss\n", + "- `InvalidValue()`: an out-of-sample loss, or a training loss, is `NaN`, `Inf`, or `-Inf`\n", + "- `TimeLimit(t=5/60)`: training time has exceeded 5 minutes\n", + "\n", + "These checks (and other controls) will be applied every two epochs\n", + "(because of the `Step(2)` control). Additionally, training a\n", + "machine bound to `iterated_clf` will:\n", + "\n", + "- save a snapshot of the machine every three control cycles (every six epochs)\n", + "- record traces of the out-of-sample loss and training losses for plotting\n", + "- record mean value traces of each Flux parameter for plotting" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For a complete list of controls, see [this\n", + "table](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/#Controls-provided)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Wrapping the classifier" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some helpers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To extract Flux params from an MLJFlux machine" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "parameters(mach) = vec.(Flux.params(fitted_params(mach)));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To store the traces:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Any[]" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "losses = []\n", + "training_losses = []\n", + "parameter_means = Float32[];\n", + "epochs = []" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To update the traces:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "update_epochs (generic function with 1 method)" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "update_loss(loss) = push!(losses, loss)\n", + "update_training_loss(losses) = push!(training_losses, losses[end])\n", + "update_means(mach) = append!(parameter_means, mean.(parameters(mach)));\n", + "update_epochs(epoch) = push!(epochs, epoch)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The controls to apply:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "save_control =\n", + " MLJIteration.skip(Save(joinpath(DIR, \"mnist.jls\")), predicate=3)\n", + "\n", + "controls=[\n", + " Step(2),\n", + " Patience(3),\n", + " InvalidValue(),\n", + " TimeLimit(5/60),\n", + " save_control,\n", + " WithLossDo(),\n", + " WithLossDo(update_loss),\n", + " WithTrainingLossesDo(update_training_loss),\n", + " Callback(update_means),\n", + " WithIterationsDo(update_epochs),\n", + "];" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The \"self-iterating\" classifier:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ProbabilisticIteratedModel(\n", + " model = ImageClassifier(\n", + " builder = MyConvBuilder(3, 16, 32, 32), \n", + " finaliser = NNlib.softmax, \n", + " optimiser = Adam(0.001, (0.9, 0.999), 1.0e-8, IdDict{Any, Any}()), \n", + " loss = Flux.Losses.crossentropy, \n", + " epochs = 30, \n", + " batch_size = 50, \n", + " lambda = 0.0, \n", + " alpha = 0.0, \n", + " rng = 123, \n", + " optimiser_changes_trigger_retraining = false, \n", + " acceleration = CPU1{Nothing}(nothing)), \n", + " controls = Any[Step(2), Patience(3), InvalidValue(), TimeLimit(Dates.Millisecond(300000)), IterationControl.Skip{Save{typeof(Serialization.serialize)}, IterationControl.var\"#8#9\"{Int64}}(Save{typeof(Serialization.serialize)}(\"/Users/anthony/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST/mnist.jls\", Serialization.serialize), IterationControl.var\"#8#9\"{Int64}(3)), WithLossDo{IterationControl.var\"#20#22\"}(IterationControl.var\"#20#22\"(), false, nothing), WithLossDo{typeof(update_loss)}(update_loss, false, nothing), WithTrainingLossesDo{typeof(update_training_loss)}(update_training_loss, false, nothing), Callback{typeof(update_means)}(update_means, false, nothing, false), WithIterationsDo{typeof(update_epochs)}(update_epochs, false, nothing)], \n", + " resampling = Holdout(\n", + " fraction_train = 0.7, \n", + " shuffle = false, \n", + " rng = Random._GLOBAL_RNG()), \n", + " measure = LogLoss(tol = 2.22045e-16), \n", + " weights = nothing, \n", + " class_weights = nothing, \n", + " operation = MLJModelInterface.predict, \n", + " retrain = false, \n", + " check_measure = true, \n", + " iteration_parameter = nothing, \n", + " cache = true)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iterated_clf = IteratedModel(\n", + " clf,\n", + " controls=controls,\n", + " resampling=Holdout(fraction_train=0.7),\n", + " measure=log_loss,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Binding the wrapped model to data:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "mach = machine(iterated_clf, images, labels);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Training" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mTraining machine(ProbabilisticIteratedModel(model = ImageClassifier(builder = MyConvBuilder(3, 16, 32, 32), …), …), …).\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mNo iteration parameter specified. Using `iteration_parameter=:(epochs)`. \n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 2.2247422992833092\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 1.9681479167178544\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mSaving \"/Users/anthony/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST/mnist1.jls\". \n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 1.220910971646785\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.5940933327640742\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.46833501799372196\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mSaving \"/Users/anthony/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST/mnist2.jls\". \n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.4241402839593314\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.40840895980242126\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.404754883332919\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mSaving \"/Users/anthony/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST/mnist3.jls\". \n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.4097772917650752\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.420399235463716\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.43216415903189187\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfinal loss: 0.43216415903189187\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfinal training loss: 0.043363843\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mStop triggered by Patience(3) stopping criterion. \n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mTotal of 22 iterations. \n" + ] + } + ], + "source": [ + "fit!(mach, rows=train);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Comparison of the training and out-of-sample losses:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"/Users/anthony/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST/loss.png\"" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot(\n", + " epochs,\n", + " losses,\n", + " xlab = \"epoch\",\n", + " ylab = \"cross entropy\",\n", + " label=\"out-of-sample\",\n", + ")\n", + "plot!(epochs, training_losses, label=\"training\")\n", + "\n", + "savefig(joinpath(DIR, \"loss.png\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Evolution of weights" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "n_epochs = length(losses)\n", + "n_parameters = div(length(parameter_means), n_epochs)\n", + "parameter_means2 = reshape(copy(parameter_means), n_parameters, n_epochs)'\n", + "plot(\n", + " epochs,\n", + " parameter_means2,\n", + " title=\"Flux parameter mean weights\",\n", + " xlab = \"epoch\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note.** The higher the number in the plot legend, the deeper the layer we are\n", + "**weight-averaging." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"/Users/anthony/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST/weights.png\"" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "savefig(joinpath(DIR, \"weights.png\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Retrieving a snapshot for a prediction:" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3-element CategoricalArrays.CategoricalArray{Int64,1,UInt32}:\n", + " 7\n", + " 9\n", + " 5" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mach2 = machine(joinpath(DIR, \"mnist3.jls\"))\n", + "predict_mode(mach2, images[501:503])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Restarting training" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Mutating `iterated_clf.controls` or `clf.epochs` (which is otherwise\n", + "ignored) will allow you to restart training from where it left off." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mUpdating machine(ProbabilisticIteratedModel(model = ImageClassifier(builder = MyConvBuilder(3, 16, 32, 32), …), …), …).\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.4449181129617429\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.4575672614002921\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mSaving \"/Users/anthony/GoogleDrive/Julia/MLJ/MLJFlux/docs/src/extended_examples/MNIST/mnist1.jls\". \n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.4693455717095324\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.48012884529192995\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mloss: 0.49023152105995377\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfinal loss: 0.49023152105995377\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfinal training loss: 0.010609009\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mStop triggered by Patience(4) stopping criterion. \n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mTotal of 32 iterations. \n" + ] + }, + { + "data": { + "image/png": "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updkvzALCgrCwsIqJnaIiIgoKCioso94jd5/Tz75pMPhIKKlS5e6jlOxqfpxpkyZsmnTJiIaN27cI488snjx4rlz57733nvx8fGLFi1q2LDh/fff74pSnudXrFhRVlbmemNgYKBrQaFQVF6ufKcwNLR8drywsLAqn5ubm5ufn79w4ULXy5SUlMjIyJv72XiA3wUhEf0rlROIuv7i/KMPH6UhIuI0+rBR75atW3hxyvOhT76maJAodY0AAFfEx8efOnWqrKxMr9cT0e7du++9914iCgwMLCoqcu1T0RYql8udzisXr9nZ2ZWPc+jQIbvdLpfLXcfp1q1b5Q/6+OOPK7/s2rVr165d7Xb74MGDZ82a9dJLL23atMlisXAc53A4XnjhhVs6i/379ycmJhLRvn37XJePFZKTk/V6/axZs27pgJ7ij0FIRC+kcoJIXX9x/NGXj1QTERFj+m6Z8sgGBV++GdB3mLb9fRKXCABwWZMmTbp16zZs2LCxY8du2rTp77//njdvHhF17dr1448/Tk5OPnPmzLffftukSRMiCg8PDwwMnDRpUkJCwv333+/KTpdOnTo1aNBg9OjRw4cPX758eVFRUb9+/a71oWvXrt27d2/79u1tNtvRo0cfeOCBoKCgkJCQTz/9ND09febMmdfqO3otkyZN0mq1paWlU6dOXbBgQeVNmZmZH3744ejRowcPHmy329evXz9o0CBXavqAnwYhEb2Uxhns1PNXx7refJiqfKWqWYfw52ML5ky0nT4c1O9pJvPfnw8A1CgLFy785JNPpk2bFh0dvW3bNlcL54gRI4xG42effdasWbNvvvnm8OHDRMRx3Nq1axcvXrx9+/YuXbpUDkLG2OrVq6dMmTJ16tTGjRtv2bJFrVYT0T333FP5ItKlUaNGq1atmjx5slarfemll1x37FauXDl16tRNmzY99thjnTt3TklJIaJOnTpVPGLRpEmTwYMHu5b1ev2LL75YccD333//hx9+MJlM8+bN69y5MxGlpaW5rk2VSuXmzZunT58+bdo0hUJx1113RUVFeetHWQ27VrNyDTFhwgStVjt+/HgvHf/17c6s0+LaPnyo8spK0WounP+RYCgOGTZBFhBy559S0aDhh3DuUlchjdp+7llZWV9++SUm5vUgvV6/f//+2+4I6pqY9/Tp056tysVfniO8lnfukvVpwLqvcBRWevSTKdWhT76matb+0tR/2U4dlK46AADwOjT90XttZE7R2eNXx5pefHDFdaHrlmH9uIL/vq3v9qiu80NSlggAUMtV9C+tgfz9itBlUltZt/qsz2+OMvtV61VN24Y/P8X418rC+R+KdgkG/gEAuG3ffvvtwYPXa9P64IMPiouLfVZPjYUgLDe5naxVGOu10mG4Ogv5sPoRL04jYpc+fdFReFGi6gDA302fPn369Om39JZ169adOXO9WecWLVrkenzezyEIyzGizzJkaSGs128Oo+PqTXJFyOCXdRm98z55wXpkl0QFAoBfO3fu3Llz56qsNJvNFSsNBsP58+crb507d+599115EkwUxfPnz9vtV77sb9261TUujIvD4Th//nyVHpRmszkvL89TZ1EzIQivYESfd5SlBLGHVjvMjqpbtRm9Q4a+WvjdB4Y/l0pRHQD4r1WrVs2aNWvWrFkJCQlPPPEEEUVGRr788sspKSkDBgwgos6dO7dt27ZXr14NGjRYv369613333//kiVLiOjdd9995JFHOnXq1LNnz8jIyLVr17p2iIiIOHnyJBH169dv9OjRLVu27NatW1xcXMWz+a+//nrDhg179uw5aNCguLi4bdu2+f7cfQCdZa7CiL7oKBv2p/Oh1Y5lPXnV1SOPKpu0jHjhk7wvxvPhMaqUthLVCAASECxG66EdPvowXq5Kvovx8ooVPXv2HDVqFBFNmjSpYmVubu6xY8dkMhkRzZ8/33Vtt3LlytGjRx84cICIHA6HIAiunTds2LBjx47Y2Ng5c+a8/vrrrgFl7HZ7xfXfjh07/vrrL51O9/TTT0+dOnXGjBkbN26cM2fOvn37IiIifvjhhx9++MFHp+9zXgnCsrKy7OzskpKS1NRU1+OWbvdZs2YNY6xHjx5ardYbZdwejtHczrIn/nQ+vNrxcw9eeXUWyoIj9N0fNWz6BUEI4FechZdMu9b76MMYU8Q2kQWGXn+vMWPGuFKQiGw22/vvv3/u3Dmbzeaa4UGlUlXeuVevXrGxsUTUuXPnf//739WPNmjQIJ1OR0RdunT56quviGjt2rUPPfRQREQEEQ0cOHD06NGeOLeayPNBePLkyZYtW7Zt2zYyMvKZZ5558sknP/jggyr75Obmpqenp6WlCYLw8ssvZ2dnu37WNYSM0TedZUP+cA5c51zQTSa/uv1Y06pzybIvnYWXZCE1qGYA8Cp5/bjQYROkruIqISHlw32cPn26Y8eO//73vx9++GG73f7VV1+ZTKYqQVgxvoFcLq98m7CCKwUr72A0GjUajWslY6xiue7x/D3CsLCwgwcPrlmz5rvvvtuwYcOHH3549uzZKvt8+umn7dq1W758+f/+978WLVrMmDHD42XcIRmjeZ1lRDRwndMhXLWJyRWaNt2MW1ZKUxkA+CWFQuE2wIho48aNrVu3Hjt2bPfu3SvS8c6lpqa6phIkomPHjl28WGe7zXs+CPV6ff369V3L9evXl8lkFoulyj5ZWVmumZSJaMCAATVzHCM5Rz91kzlEeuz3qlmoy+ht3LxSdFbrUQMA4B0tW7Zcvnz5Z599tmLFiiqbUlNTs7Ozv/vuuwULFrht9rw9jz76qNFoHDBgwAcffDBixIiQkBCOq5v9K73bWeb999/v2LFjlek2iOjs2bPR0dGu5ZiYmOp9gisUFBTs379/5syZrpccxw0ePLjKJb/3yIh+7EID1gmDfhe/68xkl6fJZGH1ZeHRpj3ZquYdb+Y4Tqez+oC2fgLnLnUV0qjt517Rx6TmePjhh1Uq1f79+11P/r322msVd5RatGjx/fffL168OCgoaM6cOYsWLXI1Yz755JPNmjUjonvvvbfiecHg4OCJEye6lidMmOC6ghwyZEjFL+pmzZo99dRTRKRUKjdu3LhkyZKSkpL58+enpKT4ciBst27jLxXHcRXzOF6LFwfd/uabb1577bUNGzY0atSoyia9Xr9u3bq2bdsS0ebNm/v06VNYWOj2IEOHDj106FCLFi1cL1Uq1WuvvRYU5NO5c61OGrieC1fRzA4Cd/nnad2z0bJ1deDIiTdzhNo+APGdwLlLXYU0avu5//LLL19//XVWVpbUhUhs69atrVu3FkVx8uTJS5Ys2b59+w1DxUvOnDnTqVOnI0eO3Oob5XJ5RZeia/HWFeGPP/44fvz4tWvXVk9BIoqKirp06ZJr+eLFi9f5ltGgQYOmTZt6b/aJm6EiWtKD+q5yPPe37Mu7Za4sVN7VxfS/OXxZAR8efcMj2O12n13F1jQ4d6mrkEZtP3eFQiHVb/wa5dtvvx04cKAgCC1atFiwYIG0PxPGmJf+UnmlwXfJkiUvvvjib7/9lpycXLHS4XBUDGrXuXPnVatWuZZXr17dpUsXb5ThQWqesnryJ8rEURudritoJuM17XoaN/8qcWUAAF4zffr0EydOnDp1atmyZY0bN5a6HG/x/BXhkSNHBg4c2KFDh4ph8caOHdu0adN169b179+/tLSUiF544YWMjIyAgABBEL7//vstW7Z4vAyP0/D0v/v43isdYzc7P02XEZGuY5+LU54P6PU4kyukrg4AAG6T54MwKCjos88+q7wmICCAiJo1azZt2jTXmpSUlK1bt/7www+Msb///ru2fNHQ8pR1H99hmWP1ObFHNJMFRyhim5h3b9S0uVfq0gAA4DZ5PggjIiJcPY6qiI6OHjZsWMXLxMTEN9980+Of7m0BcvpnMvfTCaFHtIyItB37lK1diCAEAKi96uZDIV41II4tPSXYBCIidUo7Z0me/dxxqYsCAIDbhEG3b1mMljUNYmvPib1iGXGctv19xs0rg/o/I3VdAOBJp0+fnj17ttRVQLlrPWLnEQjC25EZzy04KfSKlRGRNr3XxUmjAv8xnCnVUtcFAJ7RvHnzDh06bN++/Tbea7fb5XL5jferi7x67mPGjPHSkRGEtyMznpu4w251ypQykgWEKBs3N+34Q5veS+q6AMAzGjZsOGvWrNt7b20fTOBO1NJzxz3C2xGpptRgtvpc+aA82ozeho3/k7YkAAC4PQjC2zQgnlt4snw0QlVSa9FmsZ255bF/AABAcgjC29Q/jlt+WrC4BoBlTJvey7jpF4lrAgCAW4cgvE2RamoVyladLb8o1Lbvad67STAZpK0KAABuFYLw9g2I5xacLL9NyGkDVE3bmbatlbYkAAC4VQjC29c/jluRI5gvz86r7djbsOkX8tq0VgAA4A0IwtsXrqLWoWzl5dZRZXwq4zjriX3SVgUAALcEQXhHMuO5hSevXAJqM3qjywwAQO2CILwjjzTiVuQIxsuto5q23SyHtgmGYkmLAgCAW4AgvCNhKmofzlbmlLeOciqtunkn45ZV0lYFAAA3D0F4pyr3HSUi3d3/MGb/ii4zAAC1BYLwTvVrxK06e6V1VB6dwGn0lsM7JC0KAABuFoLwTgUrqUME++WMULFG27EPuswAANQWCEIPqNJ3VHNXV+vJ/c7ifAlLAgCAm4Qg9ICHG3Grzwml9vKXTK7QtO5i/GulpEUBAMBNQRB6QJCCOtWr1jq6+VfR6bjOuwAAoCZAEHrGgKtbR+X1GvChUZYDWyUsCQAAbgaC0DMebsT9fv5K6ygRaTtilBkAgFoAQegZAXK6J4rLOn2ldVTd8h77uROOvHMSVgUAADeEIPSYAXGs8pP1TMZr2nU3/vWbhCUBAMANIQg95sGG3PoLQontyhptRm/jllWiw37tNwEAgMQQhB6jl1OXKG5ZpdZRPjRKEZNg3rNJwqoAAOD6EISelBnPFp4UKq/RZvQ2ZqPLDABAzYUg9KQHGnIbc8VC65U16tQOjvwLzotnpCsKAACuB0HoSVqeukVzyyu1jhIn03a437ZtjXRFAQDA9SAIPWxAHFtQpXW0w/32PRtFm0WqkgAA4DoQhB72jwbc5otiQaXWUVlQGN8w2bTzT+mKAgCAa0IQepiGpx7R3M+nrrooVLTtYdy0QqqSAADgOhCEnle97yjfuKVgKrPlHJWqJAAAuBYEoef1juW2XBIvmSutYkzb4T5jNi4KAQBqHASh52l4uj+W+/n01V1m0nuZ92wSLEapqgIAALcQhF4xIK5q6yinDVAltTJtWydVSQAA4BaC0Ct6x3I78q9uHSXSZvQxbsySqCIAAHAPQegVKhn1iuWWXN13VNm4ORGzndwvVVUAAFAdgtBbBsSxBSeEKiu16b0MmK0XAKAmQRB6y/0x3K5C8bxJrLxS06675cBWwVAiVVUAAFAFgtBblDLqG8stPXVVEHJqnTotw7h1tVRVAQBAFQhCL8qM56r0HaWKiZlE0e1bAADAxxCEXnRfDNtfVLV1VNEwmam01qO7pKoKAAAqQxB6kZyjvg24xSerXvzpMnqjywwAQA2BIPSuAXHcgmqto5q7ulqP7naWFEhSEgAAVIYg9K4e0exgkXjWxCqvZEq1pnVn41+/SVUVAABUQBB6l5yjBxtyy8/KqqzXZvQxbv6VhKoXiwAA4GMIQq/LjOeW5lT9Ocvrx8mCwy0Ht0pSEgAAVEAQel23+uyEgZ02uO0yg4mZAAAkhiD0Op6jPtHComp9R9WtOttzjjoKciWpCgAAXBCEvvBwrFD9yXrGyzVt7jX+tVKSkgAAwAVB6Av3RDhPlYknyqpeFGo79jVtWSU6HZJUBQAAhCD0DRmjhxu5ebKeD4viIxtY9mRLUhUAABCC0GcGxHHVZ2UiIl1GH0M2uswAAEgGQegjXaLYOZN4rLRal5nmGY5LOfbcM5JUBQAACEIf4Rg93Iir3neUOJm2XU90mQEAkApffdWMGTM6derUokWL2z5oWVnZjh07du/eXb9+/f79+1ffIScn5/vvv694+cADDzRt2vS2P662yIzjXtziHNei6pcPbcfeFz98JrD3E0yhlKQwAAB/5uaKcOHChS1btkxPT587d67JZLqNg37wwQf/+te//vvf/37zzTdudzhx4sSUKVOKLrPZbLfxKbXO3ZHsopmOllS9KJQFhSsaNTXvWi9JVQAAfs5NEP72228LFizQ6XQjRoyIiooaNWrUrl23NnneO++8s2vXriFDhlxnn8jIyEmX3cnVZy3CMXqkEVtYvXXUNcoMuswAAEjBTRAqlcoBAwasXr364MGDY8aMWbJkSatWrdq0aTN79myj0eipDy4sLHz77bc//fTTY8eOeeqYNd+1+o6qUtoJpYX2s8d9XxIAgJ9joujmAqUyi8Uybdq0CRMmOByOoKCgp5566qWXXoqIiLjhoT/66KM///wzKyur+qZt27ZNnz49KSnp2LFjCxcu/Omnn3r37u32IIMGDdqzZ09SUpLrpUKh+PDDD0NCQm746TWKwWDQ6XREJIiUtEz+v3sdSQFVf+zmPxYJJQXaB0dJUaAXVZy7H8K5S12FNHDuUldxFYVCwfNuesNUdr3NTqdz5cqVs2fPXrFihU6ne+KJJ4ho5syZ33777ZYtW2JjY2+7sjZt2lTcPkxNTZ0wYcK1gjAkJCQ1NfXhhx92veQ4LjQ0VKFQ3PZHS8JmsymV5R1h+seJy8/JXwtnVfbh03vnfzhG/sBITqXxeYFeVPnc/Q3OXeoqpIFzl7qKq3DcjR+OcB+EZ8+enTNnzpw5c3Jyctq0aTNr1qyBAwdqNBoiGj9+fOvWrRcsWPDSSy95pMq2bdu+995719oaGBhYv379Rx991COfJRWZTCaTlU9J+Gi8OHqT8827qs5QKAsOUya2tO1ar+3Yx+cFelHlc/c3OHepq5AGzl3qKm6Zm6h87rnnGjVq9MEHH/To0WPr1q1///338OHDXSlIRBERES1atCgsLLzVTxIEISsrq6SkhIhKS0sr1i9cuNBPOsu4pNdjpTY6UOy2y0wfw6b/+b4kAAB/5uaK0GAwTJky5YknnggKCnL7njlz5ly/cXLFihVvvPHGxYsXy8rK2rRp8+CDD77++ut2u/2BBx7Yvn1769atX3zxxe3bt8fFxR07dsxgMCxbtswzZ1MbMKJ+cWzBCeGt1lW/NymbtBDtNtupQ4pGyZLUBgDgh9wE4dy5c6//nsjIyOvvcM899yxYsKDipV6vJyKFQrF///74+Hgi+vzzz3fu3Hnx4sV69eq1atWq1t3zu0MD4rgn1zvfal1tA2PajN7G7F8QhAAAPuP+HqEgCCtWrNi6deupU6dCQ0OTk5P79+8fGhp6kwfV6XTVOw4xxlJSUlzLCoWiffv2t110bdc+glmctK9ITA2u2mVG2/6+3PeGB5rKOI1ektoAAPyNmyAsKip68MEHN2zYoFAoIiMji4uLS0tLx48f/9NPP3Xv3t33JdY9jGhAHFt4Qkit1mWG0+hUKe1MW1frujwiSW0AAP7GTWeZsWPH7tixY968eQaD4fTp0yUlJTt37kxKSsrMzCwuLvZ9iXXSgDjupxPun+AsH2XmRs93AgCAR7gJwmXLlr399ttDhw6Vy+WuNS1btly2bFlJScn69RgP0zPahjOHSLsL3aSdIi6FKZTWY3t8XxUAgB9yE4SMsYqRXCqEh4fXuvFcarj+cWyhu+HWiEib3suIoUcBAHzCTRD27dt30aJFVVb++eefVqu1U6dOPqnKL2TGcT9eo3VU06qL5eA20Wb1cUkAAH7ITWeZ0aNHP/bYYw8++ODQoUNjY2NdLaJffPHFhAkTTp48efLkSSKKjIyMjo72ebV1SuswxjHaWSC2Cq3ad5TT6BQNkyyHt6vTMiSpDQDAf7gJwldeeSUnJycnJ2f58uWV148bN65iefz48dcZFw1u0oA4tuCE0CrUzYhEqrR0897NCEIAAG9zE4SffvqpayC062jUqJFXyvEzA+K4R9Y4329LVS8JidRpGaW/fkuCk7jaN3AfAEAt4iYI27Zt6/s6/FPLUKaU0fZ8sU1Y1SiUBYbyoZHW4/uUTfxoIFYAAN+75vwUFotlz549y5Yt27RpU35+vi9r8ivX6TuqTssw7832cT0AAP7GfRDOmDEjKiqqRYsWDz30UKdOnerVq5eZmVlUVOTj4vyBq++o286jqrQM897NeLIeAMCr3AThvHnznn322datW8+fP3/jxo1ZWVnPP//8L7/8kpmZ6fv66ry0EKbj6e88N2knj2zA5Ar7ueO+rwoAwH+4uUc4ZcqU/v37L1iwgLHyG1d9+/a99957H3jggd27d/vV3IG+MSCeLTghtAt30ylGnZZu3rtZHtPY91UBAPgJN1eER44cGTRoUEUKuvTt2zcwMPDw4cO+KsyPDIznFlyjdVSdlmHes8nXBQEA+BM3QRgQEJCTk1NlZXFxscFgCAgI8ElV/iU5iAUo6K9L7sYdbZgsGEsdeed8XxUAgJ9wE4S9evV666231q5dW7HmwoULgwcP1ul0HSNtem8AACAASURBVDt29GFtfiQznnPfd5QxVWoH876/fF4RAIC/cBOEkyZNCg8P7969e1xcXOfOnZs3bx4XF7d27drZs2e75poHj3s0ni08KQrumkfVaemWvZt9XhEAgL9wE4SRkZHbt2//+OOPO3ToYLfbGzRo8Nxzz+3atQu9Rr0nKZCFKCn7opskVCa2sueedpbi2RUAAK9w02v08ccff+SRR8aOHev7avzZgDhu4UmhU2TVvqNMxquSW1sObNV2uE+SwgAA6jY3V4RLly41m82+L8XPPZbAFp4UnO5aR1Wp6RhiBgDAS9wEYfv27ffswfTovpYQwCLVbJO71lF1s/a24/tEK76dAAB4npsgnDp16vz58+fOnWuxWHxfkD8bEM8tcNd3lCnVirimlkPbfF8SAECd5yYIX3nllfz8/OHDh2s0mpCrnTp1yucV+pFH49nia7SOqtMyzHvQdxQAwPPcdJZ58MEHW7Vq5XZvPFDvVfF6Fq1l63PFrlFVZ2VSpaWX/O+/otPBZG7+yAAA4La5+a369NNP+74OcHE9Wd81qmrfUZk+mI+ItR7bo0pqLUlhAAB1lZum0cmTJ2/ZsqXKytLS0lGjRmFiQm/LjGOLTgoOd4PMqNMy8GQ9AIDHuQnCZcuWHT16tMpKs9k8e/bs0tJSn1TlvxrpWZye/Znrru9oi47mvdmYnhAAwLOuOUN9FXl5eUQUFBTkzWKA6Np9R/mw+pxaa8s54vuSAADqsCv3CA8cODBv3jwiOn369E8//bRv376KTQaD4ffff4+LiwsJCZGgRj/zaDy7a6lzRoaMr/YtxTVnvaJBkhR1AQDUTVeC8PTp07NnzyaisrKy33//fdOmK9PgBQYGJiYmTpw4UYIC/U+sliUEsHUXxJ7RVfuOqtMyir7/KLDPMCnqAgCom64EYa9evQoLC4koIyPj6aefHjJkiHRV+bvMeG7BCaFndNW+o4rYJoLF7Lh0lo+IkaQwAIC6x809wuzsbKSgtDLj2NJTgtFRbQNj6tQOGHcUAMCDrvl0dmlpaU5OTpVR1lJTU5VKpfer8nfRWtYpkvvphDA8seo3FVVaeumv3+q7YUosAADPcBOEFy5cGDNmzPLly8VqPfWPHz8eHx/vk8L83VPJ3Ns7nNWDUNm4uSPvnLO0UBaAjksAAB7gJgjHjBmzdu3at99+u1WrVlWu/6KionxVmL/rFcOe2UQ7C8RWoVd1mWEyXpXcxrLvL21Gb6lqAwCoS9wE4aZNm956662XXnrJ99VABY7RiCTuy0PC5x2rdplRN083/vUbghAAwCPcdJZhjMXGxvq+FKhiZBL34wmhzF51vSq5je3kAcFskKIoAIC6xk0QDhw4MCsry/elQBVRGronkvup2igzTKlWJKRZDmJ6QgAAD3DTNDps2LChQ4cOHTq0X79+VS4N0WvUx0Ylc2/ucI5Mqvp9xTUAt6Z1FymKAgCoU9wE4bPPPnvgwIEDBw589913VTah16iP3RfDns6mHfli67Crusyo09JLln0p2m1MrpCqNgCAusFNEH766aclJSVu90avUR/jGI1I5GYfEmZ2uqrLDKcNkEc1sh7brWraVqraAADqBjdB2LYtfrfWICOTuZRF9g/aywLkV61XpaWb925GEAIA3KFrTsOUk5OzYsWK2bNnO51OIjIYDAYDuilKIFJNXaK4H49X7TKjbtHJsnczpicEALhDboLQ4XCMGjWqUaNGffr0GTVqlMPhIKJp06a1atXK5+UBEdGoZO6Lg1WDkA+px+mDbKcPSVISAECd4SYI33vvvW+//XbGjBnZ2VcGdx46dOixY8cOHcKvXQn0jGFldtqeX/XiT52WgQG4AQDukJsg/PrrrydMmDB69OiYmCtz/cTGxup0uhMnTviwNijHiIYncrMOVWsdTUs3797k9i0AAHCT3AThhQsX3LaCyuVy3CaUyvAkbtFJofTqUWbkMY1JFOy5ZyQqCgCgLnAThFFRUQcOHKiy8uDBg0VFRXFxcT6pCqqKVNO99bkfqnWZUaV2sKB1FADgDrgJwszMzMmTJ2/ZsoWx8oe4z5w5M3z48MTExNatW/u2PLjiqWTuiwPVWkdT03GbEADgTrh5jvCNN97Izs5OT093Xf9lZGTs27dPo9GsXLlSJqs6EwL4TI9oZnTQ33li2/Aro8woE9IchRedxXmyoHAJawMAqL3cXBFqtdp169Z9+eWXzZs3v+uuuzQazb/+9a/du3e3b9/e9/VBBUY0IombXaXLDMepUtqZ9/0lUVEAALWemytCIpLL5SNGjBgxYoSPq4HrezKRa7rIPqXDVaPMqNPSDRuydJ3+IV1dAAC12DVHloEaqJ6autfn5h+76qJQldzGfuaIYEKHXgCA24EgrGWeSuZmXj3KDJMrlE1aWA5slaokAIBaDUFYy3SLZmYnbbl01Sgz6rR0897NUpUEAFCrIQhrGUY0slqXGVVqB+uRnaLdJlVVAAC1l1eCcNWqVePGjcvMzMzKyrrWPnPmzElPT8/IyPjmm2+8UUMdNjyRW3JKKLJeWcNp9PKYBOuRHdIVBQBQW904CIuKitauXXv69OmbP+jKlSsZY4cOHTp8+LDbHVasWDFhwoSPPvpo8uTJr7766po1a27+4BCmop4x3PdXjzKjTkXrKADA7XAThK+++uqTTz7pWj569GhSUlL37t3j4+O/+OKLmzzo1KlT//Of/zRs2PBaO3z++ecvvPBCx44d77777ueee+7zzz+/jdL92ajkqmNwq9MyzHs3k1B16BkAALg+N0H4888/t2vXzrU8ceJEnudXrVr1yiuvvPrqq0VFRR751L1797ZtWz61etu2bffs2eORw/qPrvWZ1Ul/VeoyIwuJkAWHW09VHSQWAACuz80D9RcuXEhISCAiQRBWrFjxwgsv9OjRo2vXrp9//vnOnTvvvffeO//UvLy8wMBA13JwcPClS5eutefevXs3btz45Zdful7KZLKVK1dGRkbeeQ2+ZDQaKwZu9ZTH4/jP9jpS2zsq1siS2pRt/9Me0cizH3SHvHHutQXOXeoqpIFzl7qKq6hUKp53P3RMBTeb5XK5zWYjouzs7KKiou7duxMRz/MBAQH5+fkeqSwgIMBoNLqWy8rKgoODr7VnSkpKYmLi008/7XqpUqnq16/vkRp8SRRFnU7n2WOOSqUmC+x2uSpYWb5GeVeXgq/e0g14xrMfdIe8ce61Bc5d6iqkgXOXuopb5qZptFmzZvPmzSsrK5s5c2ZYWJirDdNqtebm5oaHe2Zk5/j4+CNHjriWjxw5cp3ZnWQyWUhISPxltTEFvSRMRffHct9VGmVGXj+OZLz9/EkJqwIAqHXcBOEbb7yRlZUVEBAwf/78cePGuS4qV65cKYpiixYtbuagJpOpqKjIbrebzeaioiLX9eXRo0fffPNN1w5DhgyZOXOm2Ww2mUyzZ88eMmSI587Ij4xK5r64epQZdbP2mJUJAOCWuAnCHj167N279+uvv964ceNLL73kWqlUKmfMmBESEnIzBx03blxCQsLWrVs//vjjhISEn3/+mYjOnj1b8cjgP//5z6ZNm0ZHR0dHR7ds2XLYsGGeORs/0yWKEVH2xStdZlTNMxCEAAC3hImieOO9vMNkMjHG1Gr1dfaZMGGCVqsdP368z6ryhrKyMr1e740jT9kr7CkUv+l8eZ5IUbzw5qDwf33Mh9aU/kTeO/eaD+cudRXSwLlLXcUtc3NFuGvXroon3B0Ox+uvv96+ffuhQ4deuHDBs5+t0Wiun4JwQ8MSueWnhcKKUWYYU6W0s2B6QgCAm+YmCMeOHbty5UrX8hdffPHuu+/qdLrff//9gQce8G1tcGOhSuody3179MqdQnVahnkfhpgBALhZboLwwIED6enpruW5c+f2799/7dq1Gzdu3LFjx65du3xbHtzYqKbcrENCRQO3Mqm1/exxwVgqZU0AALWHmyCseLDv4sWLu3bt6tevHxE1atQoKirqxIkTvi4QbuSeSMaINuWWRyHj5crEVub9W6StCgCgtnAThJGRkYcOHSKiRYsWMca6du3qWl9aWiqXy31aHdyckVcPPapOS7dgAG4AgJvjZmSZfv36vfbaawcPHly0aFG3bt3q1atHRMeOHSsrK4uPj/d5hXBjTyZyb++w51tkYSoiIlWzdsWLZog2C1OopC4NAKCmc3NF+Pbbbz/22GNr1qxp06bN7NmzXSsXLlwYHx+fkpLi2/LgpgQpqG+DK6PMcGqdomGS5TCmJwQAuDE3QajRaGbMmHHw4MGsrKxGjRq5Vv7f//3f8ePHa9poqlDhqeSrusyo0jA9IQDATbnmxLyiKJ49e3bDhg0HDx60Wq3X2g1qiLsjmYzRhstdZtRpGZb9W0hwSlsVAEDN5z4If/jhhwYNGsTGxt5zzz0pKSmBgYFjxoypmC8CaqZ/JnGzL3eZkQWG8qGR1uP7pC0JAKDmc9NZZsmSJYMHD27VqtW///3vhg0bFhUVrV27ds6cObm5uUuXLvV9iXCTnkjkJu6051lk4Sqi8jnrs5VNbmqcdAAAv+UmCN9///37778/KytLJisfwfLxxx+/7777Bg8efPDgwaZNm/q2QrhZQQr6RwPu26PCi2kcEanSMvJnvRb08GjCnV0AgGtzP7LMiBEjKlLQZeDAgQEBAfv2oamtRnsqmZt9ucuMPLIBkyvs545LXBMAQM3mvtdoXl5elZUmk8lkMmk0Gp9UBbepYz0m5+jPCxVdZtB3FADgBtzPRzhx4sQdO648hVZaWjpy5EilUpmRkeHD2uB2uC4KXcvqtAzznk3S1gMAUMO5uUc4adKkTp06tWnTplWrVg0aNCgqKtq5c6fBYJg1a5ZrDFKoyR5vwr25w37JLItQk6JhsmAsdeSd48Ojpa4LAKCGcnNF2LBhw127dk2YMEGpVO7Zsyc/P/+hhx7Kzs4eOXKk7+uDWxWooAcacPNco8wwpkrtYMb0hAAA1+bmivD1119PT09/55133nnnHd8XBHduVFNu6B/Ol9I4RqROSy9b/ZO+az+piwIAqKHcXBF+/PHHJSUlvi8FPCU9gunl9McFkYiUia3suaedpUVSFwUAUEO5CcLWrVsfPnzY96WAB41I4mYdFIiIyXhVcmvLAUxPCADgnpsg/OCDD2bPnr1s2TJRFKtvhVphaGNu1TnhkpmISJWKhygAAK7JzT3CWbNmMcYeeughnU7XqFEjpVJZsWnZsmXR0eh/WAsEKuihhtzXR4VXm3PqZu2LF0wXrWamVEtdFwBAjeMmCKOjozt27Oh+b97N/lAzjUrmBv/hfDmN45RqRVxTy6Ft6hZ3S10UAECN4ybY3n33Xd/XAR7XPoIFyOn3C2K3+kydlmHesxlBCABQ3TXnI4Q6YOTlLjOqtHTLwa2i0yF1RQAANY6bIHzzzTcHDRpUZeXixYtbt27tdGKi19pkaBNuzXnhgolk+mA+ItZ6bI/UFQEA1DhugvCnn36qPqZoz549d+/evW3bNp9UBZ6hl9Mjjbh5RwVyzVmPvqMAANW4CcIzZ87Ex8dXWanX68PCwnJycnxSFXiMawxuQSR1i47mvdmER2IAAK7mJgi1Wu2ZM2eqrDQYDPn5+Wo1+t/XMu3CWZCS1p4X+bD6nFpryzkidUUAADWLmyDs0qXLRx99VFR01aBcb775plwu79Chg68KA4/5Z1L5xEyqtAw8WQ8AUIWbxycmTpzYoUOHxMTEoUOHJiQkFBQUrFixYsuWLe+8805oaKjvS4Q7NKQxN2Gb/byJC0vLKPr+o8A+w6SuCACgBnEThCkpKRs3bnzxxRenTZvm6iYaHx8/e/bsf/7znz4vDzxAJ6d+cdw3R8X/a95EsJgdl87yETFSFwUAUFO4HymmefPma9asMZlMubm5Op0uIiLCx2WBZz2VzGWudf67Oa9O7WDem63vlil1RQAANcX1HqjXaDTx8fFIwTqgTRgLUdLqc6IqDQNwAwBcBSPL+AvXcxTKxs0deeecpYVSlwMAUFMgCP3FoATujwvCBatM1bSNZd9fUpcDAFBTIAj9hU5O/eO4uUdEdVq6eW+21OUAANQUCEI/8nQKN/uQIE9qYzt5QDAbpC4HAKBGQBD6kRYhLEJFq/NUioQ0y0EMGwsAQIQg9DeuLjMYgBsAoAKC0L88lsCtzxWKEzpYDm0X7TapywEAkB6C0L/o5JQZz/33rF4e1ch6bLfU5QAASA9B6HfGNOW+PCQoUvFkPQAAEYLQDzUPYVEa2lqvo2XvZkxPCACAIPRHTyVzn50P5/RBtlMHpK4FAEBiCEJ/9FgCtylXsHZ4qPD7qc7Sohu/AQCg7kIQ+iMNT48mcHN1PTTtuud/8X+CsVTqigAAJIMg9FOjkrk5hwVt98dUKe3yZ70uWs1SVwQAIA0EoZ9qHsKitfTuTkHZ60l5bOP8r97CY4UA4J8QhP7rm86yXQVi44XO+U2fJn1IwZyJotMhdVEAAL6GIPRfiYFsaQ/Zyvtl6y9SS27sEYsq75tJJAhS1wUA4FMIQn+XGswWdJP91kcxPfXVP0+b1n8+1WzHw4UA4EcQhEBElBrMfuiuTHnmDVZ4/rOPvpi8WzCjlRQA/AOCEK5oFqHq+Oo7mdz+4M0/xP1kRxwCgD9AEMJVOJU29pn3Hij6Y0PI8u35IuIQAOo8BCFUxemCwsf8R78ta652zZre/P4iMR5xCAB1lxeD0Gw222x4NK1WkgWFhY15v/TXeQmnNszrIluNOASAussrQWixWB599NGoqKiIiIixY8eK1aY42LRpU0glS5Ys8UYZcCf4sPpho98rXvKF5eDfqcEMcQgAdZVXgnDatGnnzp27ePHiiRMnfvnll6VLl1bZweFwREVFHb+sb9++3igD7pA8qlHoyDcL50+xHt9LRIhDAKiTvBKE8+bNe/7555VKZUhIyPDhw+fNm1d9H5lMFnyZQqHwRhlw5xQNk0OfGFcw9z1bzlHXGsQhANQxXgnCEydOJCcnu5aTk5OPHz9efZ/Dhw9rNJr69es/88wzBoPhWodyOp2FhYUnLjt//rw3CobrUDZpGTxwbMGXb9pzz1SsRBwCQJ3Be/yIVqvVbDZrNBrXS51OV1xcXGWf5OTknTt3JiUlHTt27PHHH3/55Zdnzpzp9mj79+/ftGnT4sWLXS85jlu5cmVkZKTHy/aq6yR97dCwmbLnkLwvxmtHTOSCI66s5mnGXXSgMfvkIB+3l3s60Tm6iUN99d+pWn/udwDn7p9w7jWKSqWSy+XX38fzQahUKgMCAkpKSlwvi4uLIyIiquxTr169evXqEVFSUtI777wzbNiwawVh8+bN09PTx48f7/E6fUyv10tdwp3p1NtAgmHee+HPfSgLDK28pb2efoih3YXixB2y1ivlrzbnnkrmVLIrO9T6c78DOHf/hHO/IbtABjuZHKJVoGIr2QQy2MnoEG3VXhZZy3euePlMCvdkoiebMz0fhESUmpq6ffv2u+66i4i2bduWmpp6nZ1NJpNSqfRGGeBZuk59RYsxf+aE8Gc/4LQBVba2CGFLust2F4oTdwgf7HG82pz7ZxKn9srfLwCQjNlBFicV20SLk0wOKrWTxUEGh1hmJ6uT8sp4p8xpFajERjYnlVWKOrtw1UsZR3o5aXim5ChISfKrXyo40slJwzMtT3H6ipeca2vjAObZk/LKL6oxY8a88cYb7dq1Ky4u/uqrr7KysojIbrd36dJl7ty5iYmJP/30U1BQUFxc3NGjR1955ZXBgwd7owzwOH33RwWLKX/Wa+HPTGZKdfUdqsThK2ncY9Hkv9+NAWqSitAy2MnipFIbmRyixUnFtmvGW8WeRododVKxjVQyUvMUpGBKGWl5CpCTUkZ6OdPJSSUjFVEgz4IV1EhHChnp5aSWcSoZBSrKX7qiLlBBnIez7I54JQiHDBmSl5c3fPhwpVL52WefZWRkEBFjLCQkhOd5IhIEYdKkSRcvXoyMjHz++efHjBnjjTLAGwL7Plm81JY3c0L4mPeZQuV2n8px+O5OZdsIR1owSwthqcEsJZgpMJwRwK1zilRqozK7aHKQ0UHFNjI5RLODim1kdJDJQWV2sdRGJgeZHFRsE10LJTYyOESTgwx20stJJSO9nGnl5AonVywFK8vjLVDBIq6KN04nJ+XVe15fWZlDr3fzFbmGY9Wfdq9RJkyYoNVqa/s9wrKysjp1z0AUi378xFmSHzryLcbf4C70wYtlx6zafUW0p1DcVygeLxPjdCw1hDUPYanBlBbC4vSsJn019KS69ud+K3DubjcV28hgF40OMtivWi6ykskhui7FyuxkdpDBIZZUSjWjnZwiBShIxzMNTzq5K5xIw7Og8gUKkDO9nDQ8aeUUpGBqGWl4ClKSlmcanvQ3+Jfq9XOvyXAPB24dY8GP/qvgm/8UzpsUOmwCcde7xIvRUNN63D8alL+0CXSoWNxXJO4pFL88JO4rogKr2CzYlYssNZg1D2Fh7q8zAWqEEhsZHaLBTmX2qsuuYCs0yY2i02gXjQ4qs1OxjYx20eAgg50CFaSTMy1PejkFKUgrZzqedHIKUpCGZxFqahLouhlGOp4LuJxwwQqm4Ukpu3FtcHsQhHBbOC7k8X8XfPVW4Y8fhzz2It30RZ2Co+YhrHkIG5RQvqbERvuKxL2F4p5CcdFJYV+RqOQoLYQ1D2GugEwJYuh0A57lug4zOsQiq2uBDHax2EZll5dLbFRqJ6OdDHax1E6ldjLYRaOdSu0UICetnHRyFiCnADnp5Ewrp4rlSA01UAr1ApiW53Ry0sspUEFanrmWoWbCLxi4TUzGhz75ev7M8cVLZwY9cvt3eQMV1LEe61jvSpTmGMV9hbS3SFx3Xpy2XzhcIsZqWVoISwtmqcHUPITFBzBZXW1OhZtmdbpulYkGOxnsZHBQiU0scy3bqdQultrK15fZxRIbXd5NLLaSmiednHQ8C1KS65pMy7NgpWslhalY4wDSy13ruUBFefhpeRZ4E6NglZU59XrcCa9NEIRw+5hCGfrU23mf/bv0t+8D7hvkqcPGalmslnrFlmedQ6AjpeK+QnFPofjtMdpbKFw0i8lB5a2paSEsLYRF1r7b80CldjI7yOgQi61kcpDJSSU20Wh39fugUrt4+Q5Z+f0zV5iZneW9QmSMtHIKVjCdnLTlDYxM77pc4ylYwRrqytcHyLkARXnI6eWspnVZBMkhCOGOcCpt+Oj3Lk1/mSmU+q79vPERPEcpQSwliGXGl68x2Gl/kbinUNxXJP6SI+wpFM0OClKyIAWV/6dkgeXLLEhBQUoKVrAg5ZU1PL6v3xmH4GpFLO9Sb3GS2UElNtHiJNeNsRITb+OcZXYyOchoL+/EaHZSsZWMDtEVdeU9O3h2ud8HBSlYeb8PBenlLExFWp6CFKTmmatXiJYnDU96OdPL8YcIHoMghDvF6QLDx/wnb/rLnFqr7XC/Dz5RJ6f2Eax9xJVv9a6edcU2KrZSsY2KbWKJjYptlG8Rj5VSkZWKbUKxjYptVGwVS2wk56oGp2shsK4HZ5mdHALZBDJefgLa9TCZVaAi65U8swrlDYlWgUps4uWHzMjiJJNDLLUREQW463yv5EgnJ52cOCeFqVisli53ceQ0lzsxanim4SkAN8ygxkAQgge4JvLNm/4KU6o1rTr7vgBXP/L6mooVN2j5qh6crgW3wVlscz1KxZSX47By25qcI12l3+k6nskv7yY4FaEaZ8UmNU+VR54LUlzpYqSQkbbSv0VXXBGRxUlmp0hEgkglNg9sdV1IyTnS8az6I2JKWXkv/FAZ6eWk5UkpoyAF56o8SEFKGWn5m7oaq6XPk4F/QhCCZ7gm8s3//P84pUaV0lbqcm7gVoPTeLndz6XYShWP39oEMtqv7FlmFx2XtxmMDnul5yxNDrJeiUUqsl15hNfqJFOl6TsqkkbJUbCCERHHqHGAm60annNtrejEcfVWVmUrAFSHIASPcU3km//lW6FPTlAmpEldjidpedLylcLyek8MX9mtrExA70GAmg//SsGTKk3ke0TqWgAAbgqCEDzM7US+AAA1FoIQPE+d2iHwwX/mz5zgKMiVuhYAgBtAEIJXaO66V9/j0fwv/k8oLZS6FgCA60EQgrfoOvbVpvcyfv22eU821exJTgDAn6HXKHiRvlumXRdS9vuikmVf6u55QNP+Pk6lufHbAAB8CEEI3iVPaR/Svrv97LGyP5eW/va9uuXd+s4P8/Vipa4LAKAcghB8QR7TOGTwK87SImP2L5emv6xomKzv/JAysZXUdQEAIAjBh2QBwQH3D9F3f9S888/iJTNJxus69tG07c7kGPgEACSDIARfY7xc07a7pm1364n9ZWsXlK78VtO2h+6eB2WBoVKXBgD+CEEIklHGN1PGT3TknTNsWH5x8ihVs/b6rv3l9eOkrgsA/AuCECTGh0cHPTImoPfjpi2r82e/IQuO0Hd+SN28I3F4tgcAfAFBCDUCp9LqOj+k7dTXsndz2Z9LS/73X93dD2o73MeUmMoHALwLQQg1CJPx6pZ3q1vebcs5alj/c+nE+Zo29+q79JOFREhdGgDUWQhCqIkUsU1CBr/iLCkwbv714pRnFY2a4nELAPASBCHUXLLA0ID7h+i79jNt/71o8RecQqm750F16y5Mhr+3AOAx+IUCNR1TqrUZvbXpvaxHd5X9+XNJ1n+1Gb11dz/AaQNu/GYAgBtBEEItwZgysZUysZXj0lnDxqzc94armrXXd8uURzaUujIAqN0QhFDL8BExQY+MCej5mHHLqvwvxstCIgO6D1CltCfGpC4NAGolBCHUSpwuSN8tU9f5YdOOP0pWfFu0+HNV0l2qpNbKJi3QZAoAtwRBCLUY4+Xadj207Xo4Ci5YD+807VpftGAaHxqpTGylSmqliE9lvFzqmU73GgAAFs9JREFUGgGgpkMQQl3Ah0bxGVHajN4kCLZzx61HdpauWWA/8668QaIqqZUysZUipjHaTgHALQQh1C0cp4htoohtou+WKVrNttOHLId3Fi+Y5ijKUzZOUyW2UqW0kwWFSV0lANQgCEKos5hS7epoSkSutlPLkZ0l/5vLqXXKpFaqxFaqpm0whBsAIAjBL1RvOzVkryj8foo8OkGd2h5tpwD+DEEIfqZy26nNajt14HLb6SVl4+aqxFaq5DYY2hTAryAIwX8xhbKi7dRZVmQ7vs9yZGfpb/MZr3C1nSqTW3MqrdRlAoB3IQgBiIhk+mDXxBd0+Yai8e81hT9MlUfElD+MkZCGMU4B6iT8wwaoquKGomi3WY/vtR7eUfzzbGdxvqJBojymsSKmsTymMR8aiXuKAHUDghDgmphcoUq+S5V8VyCRYCi2nTlqO3fMtOMP+/KvBJNBHpNQkYvyiBjiOKnrBYDbgSAEuCmcLkiV0laV0tb1UrCY7OdP2nOOWg5vL1vzo6Mglw+NlMc2UcQ0kcc2UcQ2YXKFtAUDwE1CEALcDk6lUcY3U8Y3c70UrWb7pbOO3NO2nKOmXRvs50/wweEU2YjFpchjmyhiEphCJW3BAHAtCEIAD2BKteupDE3b7kQkOh2OvHNlR/c68nJcuSjTBfGRDRSxTRSxjRWNUjAyOEDNgSAE8Dwm4+WRDeXaEL1eT0QkOO2Xztpzjtpyjpb9ucw+fwrj5a4WVEVsY3mDJJk+WOqSAfwXghDA+ziZPLKhPLKh63qRRNFx6azt3HH72WNlf/5sP3uMKTWKmAR5TGN5/Th5RKwsLAqPagD4DP6xAfgcY3y9WL5eLLXu4lrhKMi1nz1mP3vc+Ncqx6UcZ3GeLDCUD4/hI6L58Bh5RDQfFi0LDscDGwDegCAEkB4fGsmHRqpbdCp/LTgdRZecBbmO/AuOglzLwb8duWecpQWygFA+soE8siEfGsmHRclCI/nQKEkLB6gLEIQANQ8n40Oj+NAo1/BvLqLT4SzOc+SetueesZ09Ztq1wZF7WnTY+NDyRJRHNuAjG8ojYjClBsAtQRAC1A5MxrvSUdWsQ8VKwWRwFFxwFuQ6Ci5Yjux0rF9mv3SWyWR8aNTla8coWWikPLIhnmsEuBYEIUAtxml0Ck0Tim1yZZUoOovzHHnn7HnnHJfOWY/tdeSdc5bky4LC+YgYeUQMHx4tC46QBYfLgsIwpDgAIQgB6hrGZMERsuCIqs2qBbn2S2cdl87aco4692xyFuc5i/NFQZAFR8gCQ2SBYXxwOBcYygeFyQLDucAQPNEB/gNBCFD3MRnPR8TwETFV1ot2m7O0wFlSKJQWOgouOC7mWI/udr10lhZwap0sMFQWGikLCJEFhpb/PzSSD44gTibJiQB4A4IQwH8xucJ137H6JtHpEAwlztJCZ0Gus6TAWVpoyzlaHplFlziVmg+N4ioCMiCED4viAkL44Ah01YFaB0EIAG4wGS8LDJUFhl51A9JFcDpLi5xFl5ylBc7ifGdRnvVSjmnbWmdxvrOkgNPquYBQURvkCArhtAGcNpDTBXCaAE4bwGn1Mm0ApwnATB1QoyAIAeAWcTJZUJgsKMzNJlF0lhU7S/INuWcVgl0wlgrGUkfeWcFYJhhLnMYywVgqmEo5lZbTBlT8J9PoOW0ApwvktIGcVs9pXcGpx/A64Bv4ewYAnsOYLCBYFhAsD4rUusZZdUcwGQRjiWAsE0ylgqHEaSoTjKWOnEuCoUQwlQquvDSWMrmiWjoGcFq9TBfIaQI4XSCn1DCVhlNrMeYO3AkEIQD4GqfRcRodhd9gN8FiEowlrlC8nI4ljvOnrBUrzUbRahLMRiZXMIWaU6o5jY4pVa5lptZyKg1TqJhKwylUnEbPlCqmVHMKNVNrOJWWKVR4vBLIe0GYl5e3ffv26OjotLQ0tzvYbLbs7GzGWEZGhlwu91IZAFB7cSoNp9LQTQwjJ9osgtUsWi2C2SBazaLVLFjNosUkWEyi1ewszndYzZU2WUSLSbAYRatZFAROpebUOqZQMeXl+FRqyiNTpeFUWuJ5TqkhjuNUGmKMqbSMMabWEhGn1hMRLklrO68E4dq1awcOHNixY8ddu3b17dv3s88+q7JDQUHBPffcExISIopiWVnZH3/8ERyMh5YA4DYxhUqmUNE122KvSXQ6RKtFMJeJVkuV+BRsZsFkcBTkktMpWE0kCILFRKIoWoyiKIpmIxEJ5jIiEsxGEkVOpSWOMZVGFJlJo2WcjClVxPGcUkUynilUjJczuYLxCiZXMLmC8XImVxIv5xQqYoxTuwY3KI9YIuLUOmJERJxKS4wjIqZU4b6pN3jlZ/ryyy//5z//GTly5KVLl5KSkkaNGlXlunD69OkJCQnLly8XRbFPnz6ff/75hAkTvFEJAMB1MBnPXO20d0ywGEkQBYvRaCjTyJgoCKLVTIJTsJrJ6RRsFnLYRbtVdNhFu00wGUSHTbTbRIddtFnKU5aIqDxiiUgwG0i8fGRRICLBYibBSURMoWI8T0RMrmS8goiIl3MKJRG5QpeImEzmepSFMa4iXF1JXFHzVdeynIyr9OgLU6qY7Epb3VU/IleEV2xSaSq6AQtGoyCrenHsCv5b/4n6jueD8OTJk3v37h04cCARRURE9OjRY+nSpVWCcMmSJa7kY4wNGjTok08+QRACQK3mGq+O0+g4uUZ+7Y5CHiHaLKLDQUSi3So6bEQk2u2i3UpE5HSINgsRiU6naDUTkSg4xfKUJdFuc+3v4rqWLX/hdDhslisfYbWITvuVPU2GKx/vuPxZrk0WEwlC+bLw/+3de1BU5f8H8Gf3sMtF4rIY17hfDZRYEAw2QRABF4OMLjM04x9iOoxp2RSEoQ5dTWayGYJwkATLMYaoJONSQNCOIBtCRMbdhlDu7LLAwF7Y8/3j6PntdxH19/txeIDzef3hnPOcR3g/nnWefc55znm0s8pZ/bRqFalW6RXS410ax4Cv27/eLTTewNG77GzAMxXtMQncgZbP8neEg4ODAoHA1PTu1wcnJ6fBwcHFdZycnKhtZ2fnxRVoCoWiv7+/pKSE2uVyufHx8Xz+qv5ysZhWq9Xe+6CwDbQddwo8oO3M/g4DPjLgI4Q4Riar6ubk9PT0Y4/2JYAe79JIjUq3f71bODdLkv9dT6M2sH7i0f+FORyOfle6yPJ3hEql0sDgf34sj8ebn5/Xq6NSqegJMvetQBsfH//zzz9VqrvfJgwNDUNCQqysrJY7NbOUSiVrJwRB23GnwAPajjsFHv+LtnMM9EaEiG+A+Cb61TbcZ/qICiG0dK+hh8/n63ZJ97X8HaGdnd3k5KRWq+VyuQihsbExOzv9SV+2trbj4+PU9tjYmL29/VI/zc3NbfPmzRkZGcuecyUtLCyYmCw6wewAbcedAg9oO+4UeKzRti//i448PT3Nzc2vXbuGENJqtfX19SKRSK9OWFhYbW0ttV1XVxcWFrbsMVaV8+fP446ATWFhIe4I2EDb2Ym1bSdJco22naN/+XU5fPTRR8XFxenp6TU1NW1tba2trQRBVFdXJyUlKRQKhFBra2t4ePjJkydJknzvvfckEslSjxseP358w4YNa3pESJIkQRDsvF+ysLBgaGio0WhwB8FAo9EYGxur1eqHV1131Gr1hg0b6DsarKJSqR577DGlUv9eFxsolUpzc/MH3OpatRh5fCI9Pd3FxaWhocHT0/Ps2bMEQSCEvLy8srKyqAoBAQF1dXUXL17kcDj19fVL9YIAAAAA0xgZES4jGBGuaTAihBEh28CIcC2OCGExFAAAAKy22t/W09XVdf369bKyMtxB/l84HE5QUBDuFHiQJMnOtpMkqdVqWdv2hYUF1rZdo9FA21ePvXv3PvSa4mq/NDo2Ntbb27vmnqDXo1AozMzMcKfAA9qOOwUe0HbcKfBYhW13dXUVCAQPrrPaO0IAAACAUXCPEAAAAKtBRwgAAIDVoCMEAADAatARAgAAYLXV/vjEWnfhwgX6sWJ3d/eoqCi8eZgml8t///33/v7+Z5991tbWli6/devWN998gxB6+eWXXVxcsOVj0szMzI0bN7q7u3fs2OHu7k4V9vT01NXV0XUSExOtra0xBWRQe3v7r7/+Ojk5KRQK4+PjufeWaZXJZF999dXExIRYLN66dSvekAzp7e2trq6mFiFPSkqi1l6Qy+X04nEIodDQUD8/P3wZmUK9RHNqasrLy+uFF14wNLy7muDk5OTFixflcvmePXuEQiHekI8CRoTMeuONN+rq6lpaWlpaWm7duoU7DrNIkrSxsUlPT3/ttdf6+vro8p6eHqFQOD4+Pj4+LhQKe3t7MYZkzpYtWw4fPvzmm282NzfThY2NjR988EHLPbOz+muWrgMdHR27d+/u7u4mCCItLe3FF1+kyufm5p5++mmJRMLj8WJjY8vLy/HmZIJCoQgJCWlrayMI4uzZsxEREdQX36Ghoddff50+76Ojo7iTMuLMmTPj4+N8Pj8vL08kElFtn5mZCQ4Obm5u5nK5O3furKqqwh3zEZCASRYWFr29vbhTrBylUkmSpEAgkEgkdGFqauqhQ4eo7YMHDx4+fBhPOIZRbQ8ICLh06RJdWFRUFB8fjy/USpibm1OpVNT2v//+y+Fw/vnnH5IkCwsLg4KCtFotSZIFBQXBwcE4UzJDo9HMzs5S2zMzM2ZmZvX19SRJ3rx508bGBmu0FTU/P29iYiKVSkmSzMvLCw0Npc57bm7uM888gzvdw8GIkHHffvttfn5+W1sb7iAr4b6vPqitrY2Li6O24+LiampqVjbUClnqtQ/Dw8M5OTklJSVyuXyFI60MIyMjei1W6qKokZERQqiuri42NpZaHDwuLq65uXlmZgZjTiYQBEEvv2dgYLCwsEC1HSGkUqny8/OLiooGBgbwBVwhnZ2dXC7X0dERLTrvEolk9b95FTpCZgUEBAwODkql0oiIiJMnT+KOg8fQ0BB9Y8zW1nZoaAhvnpVkYmLi7Ozc39+fn5/v4+PT2dmJOxGzjh07lpycbGNjg/77vFtbW3M4nDt37mBNx6zMzMzAwEDqVihBEEFBQV1dXeXl5b6+vj/88APudEzZt2+fi4uLSCT6+uuvF593W1tbkiSHh4exZnw4mCzDLHr94SNHjgiFwgMHDjzxxBN4I608LpdLL76h0WgMDFj0qUtKSkpKSqK2Dxw4cOLECd05FOvMO++809PTQ3/mdc87tbGOT31ubm5paWlDQwM1EvLy8qqurqYOnTt37ujRowkJCVgDMuXjjz9WKBSVlZUpKSktLS2Ojo56/9/RWjjvMCJcIVu2bLGwsOjv78cdBAMHBwd6KHDnzh07Ozu8eXCJiIjo6enBnYIpp06dunr1alVVlbm5OVVib2+ve94RQroTideT8+fPnz59uqam5r5fc8PDwwcGBtbrolR2dnbe3t5Hjx718fGh5kPpnXeCIFb/TGnoCBmk+9GXSqVTU1Oenp4Y8+AiFovp9UPKysri4+Px5llJup+ByspKHx8fjGGYk52dffny5erq6o0bN9KFYrG4vLycWpGxrKwsMjKSvp22nhQVFWVmZlZVVbm6utKFuue9qqrKzc1tra8csBg1Q4ranpmZ6e/vd3BwQAiJxeIrV65QY8GysrKYmBj6FvKqBS/dZlB5eXlGRkZgYOD8/PxPP/307rvvvv3227hDMWv//v0DAwP19fX+/v4WFhZFRUXU18OQkJBt27YhhJqbm5uamtbloDAjI0MqlV6/ft3Z2dnW1vbMmTNPPfUUNWXUwcHhjz/+GBkZqampoR8xXDdu3LgRGBjo7+//+OOPUyXZ2dn+/v5qtToyMpIkyU2bNpWVlV25ciUsLAxv1GU3MjLi4ODg6elJjwXfeuutXbt2HT9+XCKReHp63r59u6mp6fLlyzExMXijLrvGxsZ9+/Zt27aNy+XW1tYGBgaWlpYSBKFUKsPDww0NDT09Pb/77ruKiorg4GDcYR8COkIGqVQqqVTa19dnZGQUFBTk5uaGOxHjGhsbdR+VCw0NpQYBU1NTlZWVCKHY2Fj60tk609raOjExQe8KhUKBQDA8PCyVSkdHRx0dHbdv305PKVxPqLco6JYEBgZaWloihNRqdVVV1cTERFRU1Lq8Oz4/Py+RSHRLnnzySXt7e4VC0dTUNDg4uHHjRpFI9NBlgNYikiQ7Ojra29tJkvT19Q0ICKAPqVSqyspKuVy+c+dOe3t7jCEfEXSEAAAAWA3uEQIAAGA16AgBAACwGnSEAAAAWA06QgAAAKwGHSEAAABWg44QAAAAq0FHCAC7XLhw4YsvvsCdAoBVBJ4jBIBd4uPjp6amfvvtN9xBAFgtYEQIAACA1Vb76hgArHsDAwPd3d2mpqZCoVD31cwymczY2NjIyKi9vX1sbMzPz49a703XyMjIX3/9xefzhULh4ldaz87Otra2ajQaJyenxW/4Gx4evnnzppOTk7u7O7V4EAAsxczC9wCAhxsbG9u9eze6t2CbnZ1dTU0NfZTH4x07dkwkEhEEQRAEj8c7ffo0fVStVqempnK5XIIgEEJmZmaFhYX0Ua1Wm5WVRXWN1Lv/9+zZQx0Si8UikejUqVPUX0QIRUdHUysJAMBOcGkUADxIkkxISOjo6Kirq5ubmxsZGQkJCXnuued0l3H//PPPg4OD5XK5TCZLSUlJS0urqKigDmVlZeXl5X3yyScKhWJ0dDQ6Onr//v319fXU0ezs7BMnThw6dGh0dFSpVPb09Dz//PP0j21pabl27VpXV5dSqczJyfn555+Li4tXsu0ArC64e2IAWIpawby8vJwukcvlxsbGn376KbXL4/G8vb0XFhaoXZVK5eTkJBaLSZLUarWWlpbUNmV6elogECQmJlI1LS0td+3add/fKxaLTUxMxsfH6RJvb+/k5OTlbh8AawbcIwQAD2reZl9f37lz5+hCCwuLzs5OejcqKorLvXvZhsfjRUREUH9reHhYJpPpLnFnamoqEomkUilC6O+//5bJZImJiUv9ai8vLysrK3rXxcVFdxgKANtARwgAHnK5nMvl/vjjj7qFvr6+uuu3Uav60aysrEZHRxFCY2NjCCG9Ve4EAsHMzAxCaHp6GiGku1i8HlNTU91dAwODubm5/3NDAFjroCMEAA8bGxutVltcXGxnZ7dUndu3b+vuDg4OOjk5IYSoPxcftba2RgjZ2toihAYGBpiIDcD6A5NlAMCDmi+al5f3gDrl5eWzs7PUtkwmq6ys3Lp1K0LIwsLCw8Pj0qVLWq2WOjowMFBfXx8ZGYkQcnd39/b2LigoUKvVzLYBgHUBOkIA8AgICEhNTf3www8PHjxYUVHR0NDw5ZdfJiQkfP/993QdQ0PD2NjYioqKq1evxsbGajSa9PR06tD777/f3t6+d+/eqqqqkpKS6OhoExOTtLQ06uhnn33W29u7ffv2kpISiURSWFh45MgRDI0EYC2AS6MAYJOTk+Pn55ebm1tQUMDlcu3t7aOiojZv3kxXePXVV1Uq1SuvvDI5Oenv719ZWblp0ybq0EsvvUQQRFZWVmxsLI/H27FjR2lpqaurK3U0Jibml19+yczMTE5O1mq1jo6OKSkp1CEPDw/qViLNw8ODHncCwELwrlEA8KPmcNMTRCl8Pj8zMzMzMxMhtLCwQD//rkej0VDP4y/loRUAYDn47wEAfhwO58EvOVuqF0T33krzANALAvBgcI8QAAAAq8FXRQBWqaampgc8WQEAWC5wjxAAAACrwaVRAAAArPYfjOXSV2JD4EQAAAAASUVORK5CYII=", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iterated_clf.controls[2] = Patience(4)\n", + "fit!(mach, rows=train)\n", + "\n", + "plot(\n", + " epochs,\n", + " losses,\n", + " xlab = \"epoch\",\n", + " ylab = \"cross entropy\",\n", + " label=\"out-of-sample\",\n", + ")\n", + "plot!(epochs, training_losses, label=\"training\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia 1.10.3", + "language": "julia", + "name": "julia-1.10" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/src/extended_examples/MNIST/notebook.jl b/docs/src/extended_examples/MNIST/notebook.jl new file mode 100644 index 00000000..6ef43d7b --- /dev/null +++ b/docs/src/extended_examples/MNIST/notebook.jl @@ -0,0 +1,290 @@ +# # Using MLJ to classifiy the MNIST image dataset + +using Pkg #!md +const DIR = @__DIR__ #!md +Pkg.activate(DIR) #!md +Pkg.instantiate() #!md + +# **Julia version** is assumed to be ^1.10 + +using MLJ +using Flux +import MLJFlux +import MLUtils +import MLJIteration # for `skip` + +# If running on a GPU, you will also need to `import CUDA` and `import cuDNN`. + +using Plots +gr(size=(600, 300*(sqrt(5)-1))); + +# ## Basic training + +# Downloading the MNIST image dataset: + +import MLDatasets: MNIST + +ENV["DATADEPS_ALWAYS_ACCEPT"] = true +images, labels = MNIST(split=:train)[:]; + +# In MLJ, integers cannot be used for encoding categorical data, so we +# must force the labels to have the `Multiclass` [scientific +# type](https://juliaai.github.io/ScientificTypes.jl/dev/). For +# more on this, see [Working with Categorical +# Data](https://alan-turing-institute.github.io/MLJ.jl/dev/working_with_categorical_data/). + +labels = coerce(labels, Multiclass); +images = coerce(images, GrayImage); + +# Checking scientific types: + +@assert scitype(images) <: AbstractVector{<:Image} +@assert scitype(labels) <: AbstractVector{<:Finite} + +# Looks good. + +# For general instructions on coercing image data, see [Type coercion +# for image +# data](https://juliaai.github.io/ScientificTypes.jl/dev/#Type-coercion-for-image-data) + +images[1] + +# We start by defining a suitable `Builder` object. This is a recipe +# for building the neural network. Our builder will work for images of +# any (constant) size, whether they be color or black and white (ie, +# single or multi-channel). The architecture always consists of six +# alternating convolution and max-pool layers, and a final dense +# layer; the filter size and the number of channels after each +# convolution layer is customisable. + +import MLJFlux +struct MyConvBuilder + filter_size::Int + channels1::Int + channels2::Int + channels3::Int +end + +function MLJFlux.build(b::MyConvBuilder, rng, n_in, n_out, n_channels) + k, c1, c2, c3 = b.filter_size, b.channels1, b.channels2, b.channels3 + mod(k, 2) == 1 || error("`filter_size` must be odd. ") + p = div(k - 1, 2) # padding to preserve image size + init = Flux.glorot_uniform(rng) + front = Chain( + Conv((k, k), n_channels => c1, pad=(p, p), relu, init=init), + MaxPool((2, 2)), + Conv((k, k), c1 => c2, pad=(p, p), relu, init=init), + MaxPool((2, 2)), + Conv((k, k), c2 => c3, pad=(p, p), relu, init=init), + MaxPool((2 ,2)), + MLUtils.flatten) + d = Flux.outputsize(front, (n_in..., n_channels, 1)) |> first + return Chain(front, Dense(d, n_out, init=init)) +end + +# **Notes.** + +# - There is no final `softmax` here, as this is applied by default in all MLJFLux +# classifiers. Customisation of this behaviour is controlled using using the `finaliser` +# hyperparameter of the classifier. +# +# - Instead of calculating the padding `p`, Flux can infer the required padding in each +# dimension, which you enable by replacing `pad = (p, p)` with `pad = SamePad()`. + +# We now define the MLJ model. + +ImageClassifier = @load ImageClassifier +clf = ImageClassifier( + builder=MyConvBuilder(3, 16, 32, 32), + batch_size=50, + epochs=10, + rng=123, +) + +# You can add Flux options `optimiser=...` and `loss=...` in the above constructor +# call. At present, `loss` must be a Flux-compatible loss, not an MLJ measure. To run on a +# GPU, add to the constructor `acceleration=CUDALib()` and omit `rng`. + +# For illustration purposes, we won't use all the data here: + +train = 1:500 +test = 501:1000 + + +# Binding the model with data in an MLJ machine: +mach = machine(clf, images, labels); + +# Training for 10 epochs on the first 500 images: + +fit!(mach, rows=train, verbosity=2); + +# Inspecting: + +report(mach) + +#- + +chain = fitted_params(mach) + +#- + +Flux.params(chain)[2] + +#- + +# Adding 20 more epochs: + +clf.epochs = clf.epochs + 20 +fit!(mach, rows=train); + +# Computing an out-of-sample estimate of the loss: + +predicted_labels = predict(mach, rows=test); +cross_entropy(predicted_labels, labels[test]) + +# Or to fit and predict, in one line: + +evaluate!(mach, + resampling=Holdout(fraction_train=0.5), + measure=cross_entropy, + rows=1:1000, + verbosity=0) + + +# ## Wrapping the MLJFlux model with iteration controls + +# Any iterative MLJFlux model can be wrapped in *iteration controls*, +# as we demonstrate next. For more on MLJ's `IteratedModel` wrapper, +# see the [MLJ +# documentation](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/). + +# The "self-iterating" classifier, called `iterated_clf` below, is for +# iterating the image classifier defined above until one of the +# following stopping criterion apply: + +# - `Patience(3)`: 3 consecutive increases in the loss +# - `InvalidValue()`: an out-of-sample loss, or a training loss, is `NaN`, `Inf`, or `-Inf` +# - `TimeLimit(t=5/60)`: training time has exceeded 5 minutes +# +# These checks (and other controls) will be applied every two epochs +# (because of the `Step(2)` control). Additionally, training a +# machine bound to `iterated_clf` will: +# +# - save a snapshot of the machine every three control cycles (every six epochs) +# - record traces of the out-of-sample loss and training losses for plotting +# - record mean value traces of each Flux parameter for plotting + +# For a complete list of controls, see [this +# table](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/#Controls-provided). + +# ### Wrapping the classifier + +# Some helpers + +# To extract Flux params from an MLJFlux machine + +parameters(mach) = vec.(Flux.params(fitted_params(mach))); + +# To store the traces: + +losses = [] +training_losses = [] +parameter_means = Float32[]; +epochs = [] + +# To update the traces: + +update_loss(loss) = push!(losses, loss) +update_training_loss(losses) = push!(training_losses, losses[end]) +update_means(mach) = append!(parameter_means, mean.(parameters(mach))); +update_epochs(epoch) = push!(epochs, epoch) + +# The controls to apply: + +save_control = + MLJIteration.skip(Save(joinpath(DIR, "mnist.jls")), predicate=3) + +controls=[ + Step(2), + Patience(3), + InvalidValue(), + TimeLimit(5/60), + save_control, + WithLossDo(), + WithLossDo(update_loss), + WithTrainingLossesDo(update_training_loss), + Callback(update_means), + WithIterationsDo(update_epochs), +]; + +# The "self-iterating" classifier: + +iterated_clf = IteratedModel( + clf, + controls=controls, + resampling=Holdout(fraction_train=0.7), + measure=log_loss, +) + +# ### Binding the wrapped model to data: + +mach = machine(iterated_clf, images, labels); + + +# ### Training + +fit!(mach, rows=train); + +# ### Comparison of the training and out-of-sample losses: + +plot( + epochs, + losses, + xlab = "epoch", + ylab = "cross entropy", + label="out-of-sample", +) +plot!(epochs, training_losses, label="training") + +savefig(joinpath(DIR, "loss.png")) + +# ### Evolution of weights + +n_epochs = length(losses) +n_parameters = div(length(parameter_means), n_epochs) +parameter_means2 = reshape(copy(parameter_means), n_parameters, n_epochs)' +plot( + epochs, + parameter_means2, + title="Flux parameter mean weights", + xlab = "epoch", +) + +# **Note.** The higher the number in the plot legend, the deeper the layer we are +# **weight-averaging. + +savefig(joinpath(DIR, "weights.png")) + + +# ### Retrieving a snapshot for a prediction: + +mach2 = machine(joinpath(DIR, "mnist3.jls")) +predict_mode(mach2, images[501:503]) + + +# ### Restarting training + +# Mutating `iterated_clf.controls` or `clf.epochs` (which is otherwise +# ignored) will allow you to restart training from where it left off. + +iterated_clf.controls[2] = Patience(4) +fit!(mach, rows=train) + +plot( + epochs, + losses, + xlab = "epoch", + ylab = "cross entropy", + label="out-of-sample", +) +plot!(epochs, training_losses, label="training") diff --git a/docs/src/extended_examples/MNIST/notebook.md b/docs/src/extended_examples/MNIST/notebook.md new file mode 100644 index 00000000..b07ccdd4 --- /dev/null +++ b/docs/src/extended_examples/MNIST/notebook.md @@ -0,0 +1,352 @@ +```@meta +EditURL = "notebook.jl" +``` + +# Using MLJ to classifiy the MNIST image dataset + +**Julia version** is assumed to be ^1.10 + +````@julia +using MLJ +using Flux +import MLJFlux +import MLUtils +import MLJIteration # for `skip` +```` + +If running on a GPU, you will also need to `import CUDA` and `import cuDNN`. + +````@julia +using Plots +gr(size=(600, 300*(sqrt(5)-1))); +nothing #hide +```` + +## Basic training + +Downloading the MNIST image dataset: + +````@julia +import MLDatasets: MNIST + +ENV["DATADEPS_ALWAYS_ACCEPT"] = true +images, labels = MNIST(split=:train)[:]; +nothing #hide +```` + +In MLJ, integers cannot be used for encoding categorical data, so we +must force the labels to have the `Multiclass` [scientific +type](https://juliaai.github.io/ScientificTypes.jl/dev/). For +more on this, see [Working with Categorical +Data](https://alan-turing-institute.github.io/MLJ.jl/dev/working_with_categorical_data/). + +````@julia +labels = coerce(labels, Multiclass); +images = coerce(images, GrayImage); +nothing #hide +```` + +Checking scientific types: + +````@julia +@assert scitype(images) <: AbstractVector{<:Image} +@assert scitype(labels) <: AbstractVector{<:Finite} +```` + +Looks good. + +For general instructions on coercing image data, see [Type coercion +for image +data](https://juliaai.github.io/ScientificTypes.jl/dev/#Type-coercion-for-image-data) + +````@julia +images[1] +```` + +We start by defining a suitable `Builder` object. This is a recipe +for building the neural network. Our builder will work for images of +any (constant) size, whether they be color or black and white (ie, +single or multi-channel). The architecture always consists of six +alternating convolution and max-pool layers, and a final dense +layer; the filter size and the number of channels after each +convolution layer is customisable. + +````@julia +import MLJFlux +struct MyConvBuilder + filter_size::Int + channels1::Int + channels2::Int + channels3::Int +end + +function MLJFlux.build(b::MyConvBuilder, rng, n_in, n_out, n_channels) + k, c1, c2, c3 = b.filter_size, b.channels1, b.channels2, b.channels3 + mod(k, 2) == 1 || error("`filter_size` must be odd. ") + p = div(k - 1, 2) # padding to preserve image size + init = Flux.glorot_uniform(rng) + front = Chain( + Conv((k, k), n_channels => c1, pad=(p, p), relu, init=init), + MaxPool((2, 2)), + Conv((k, k), c1 => c2, pad=(p, p), relu, init=init), + MaxPool((2, 2)), + Conv((k, k), c2 => c3, pad=(p, p), relu, init=init), + MaxPool((2 ,2)), + MLUtils.flatten) + d = Flux.outputsize(front, (n_in..., n_channels, 1)) |> first + return Chain(front, Dense(d, n_out, init=init)) +end +```` + +**Notes.** + +- There is no final `softmax` here, as this is applied by default in all MLJFLux + classifiers. Customisation of this behaviour is controlled using using the `finaliser` + hyperparameter of the classifier. + +- Instead of calculating the padding `p`, Flux can infer the required padding in each + dimension, which you enable by replacing `pad = (p, p)` with `pad = SamePad()`. + +We now define the MLJ model. + +````@julia +ImageClassifier = @load ImageClassifier +clf = ImageClassifier( + builder=MyConvBuilder(3, 16, 32, 32), + batch_size=50, + epochs=10, + rng=123, +) +```` + +You can add Flux options `optimiser=...` and `loss=...` in the above constructor +call. At present, `loss` must be a Flux-compatible loss, not an MLJ measure. To run on a +GPU, add to the constructor `acceleration=CUDALib()` and omit `rng`. + +For illustration purposes, we won't use all the data here: + +````@julia +train = 1:500 +test = 501:1000 +```` + +Binding the model with data in an MLJ machine: + +````@julia +mach = machine(clf, images, labels); +nothing #hide +```` + +Training for 10 epochs on the first 500 images: + +````@julia +fit!(mach, rows=train, verbosity=2); +nothing #hide +```` + +Inspecting: + +````@julia +report(mach) +```` + +````@julia +chain = fitted_params(mach) +```` + +````@julia +Flux.params(chain)[2] +```` + +Adding 20 more epochs: + +````@julia +clf.epochs = clf.epochs + 20 +fit!(mach, rows=train); +nothing #hide +```` + +Computing an out-of-sample estimate of the loss: + +````@julia +predicted_labels = predict(mach, rows=test); +cross_entropy(predicted_labels, labels[test]) +```` + +Or to fit and predict, in one line: + +````@julia +evaluate!(mach, + resampling=Holdout(fraction_train=0.5), + measure=cross_entropy, + rows=1:1000, + verbosity=0) +```` + +## Wrapping the MLJFlux model with iteration controls + +Any iterative MLJFlux model can be wrapped in *iteration controls*, +as we demonstrate next. For more on MLJ's `IteratedModel` wrapper, +see the [MLJ +documentation](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/). + +The "self-iterating" classifier, called `iterated_clf` below, is for +iterating the image classifier defined above until one of the +following stopping criterion apply: + +- `Patience(3)`: 3 consecutive increases in the loss +- `InvalidValue()`: an out-of-sample loss, or a training loss, is `NaN`, `Inf`, or `-Inf` +- `TimeLimit(t=5/60)`: training time has exceeded 5 minutes + +These checks (and other controls) will be applied every two epochs +(because of the `Step(2)` control). Additionally, training a +machine bound to `iterated_clf` will: + +- save a snapshot of the machine every three control cycles (every six epochs) +- record traces of the out-of-sample loss and training losses for plotting +- record mean value traces of each Flux parameter for plotting + +For a complete list of controls, see [this +table](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/#Controls-provided). + +### Wrapping the classifier + +Some helpers + +To extract Flux params from an MLJFlux machine + +````@julia +parameters(mach) = vec.(Flux.params(fitted_params(mach))); +nothing #hide +```` + +To store the traces: + +````@julia +losses = [] +training_losses = [] +parameter_means = Float32[]; +epochs = [] +```` + +To update the traces: + +````@julia +update_loss(loss) = push!(losses, loss) +update_training_loss(losses) = push!(training_losses, losses[end]) +update_means(mach) = append!(parameter_means, mean.(parameters(mach))); +update_epochs(epoch) = push!(epochs, epoch) +```` + +The controls to apply: + +````@julia +save_control = + MLJIteration.skip(Save(joinpath(DIR, "mnist.jls")), predicate=3) + +controls=[ + Step(2), + Patience(3), + InvalidValue(), + TimeLimit(5/60), + save_control, + WithLossDo(), + WithLossDo(update_loss), + WithTrainingLossesDo(update_training_loss), + Callback(update_means), + WithIterationsDo(update_epochs), +]; +nothing #hide +```` + +The "self-iterating" classifier: + +````@julia +iterated_clf = IteratedModel( + clf, + controls=controls, + resampling=Holdout(fraction_train=0.7), + measure=log_loss, +) +```` + +### Binding the wrapped model to data: + +````@julia +mach = machine(iterated_clf, images, labels); +nothing #hide +```` + +### Training + +````@julia +fit!(mach, rows=train); +nothing #hide +```` + +### Comparison of the training and out-of-sample losses: + +````@julia +plot( + epochs, + losses, + xlab = "epoch", + ylab = "cross entropy", + label="out-of-sample", +) +plot!(epochs, training_losses, label="training") + +savefig(joinpath(DIR, "loss.png")) +```` + +### Evolution of weights + +````@julia +n_epochs = length(losses) +n_parameters = div(length(parameter_means), n_epochs) +parameter_means2 = reshape(copy(parameter_means), n_parameters, n_epochs)' +plot( + epochs, + parameter_means2, + title="Flux parameter mean weights", + xlab = "epoch", +) +```` + +**Note.** The higher the number in the plot legend, the deeper the layer we are +**weight-averaging. + +````@julia +savefig(joinpath(DIR, "weights.png")) +```` + +### Retrieving a snapshot for a prediction: + +````@julia +mach2 = machine(joinpath(DIR, "mnist3.jls")) +predict_mode(mach2, images[501:503]) +```` + +### Restarting training + +Mutating `iterated_clf.controls` or `clf.epochs` (which is otherwise +ignored) will allow you to restart training from where it left off. + +````@julia +iterated_clf.controls[2] = Patience(4) +fit!(mach, rows=train) + +plot( + epochs, + losses, + xlab = "epoch", + ylab = "cross entropy", + label="out-of-sample", +) +plot!(epochs, training_losses, label="training") +```` + +--- + +*This page was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).* + diff --git a/docs/src/extended_examples/MNIST/notebook.unexecuted.ipynb b/docs/src/extended_examples/MNIST/notebook.unexecuted.ipynb new file mode 100644 index 00000000..b19ab019 --- /dev/null +++ b/docs/src/extended_examples/MNIST/notebook.unexecuted.ipynb @@ -0,0 +1,724 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Using MLJ to classifiy the MNIST image dataset" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using Pkg\n", + "const DIR = @__DIR__\n", + "Pkg.activate(DIR)\n", + "Pkg.instantiate()" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "**Julia version** is assumed to be ^1.10" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using MLJ\n", + "using Flux\n", + "import MLJFlux\n", + "import MLUtils\n", + "import MLJIteration # for `skip`" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "If running on a GPU, you will also need to `import CUDA` and `import cuDNN`." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using Plots\n", + "gr(size=(600, 300*(sqrt(5)-1)));" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "## Basic training" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Downloading the MNIST image dataset:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "import MLDatasets: MNIST\n", + "\n", + "ENV[\"DATADEPS_ALWAYS_ACCEPT\"] = true\n", + "images, labels = MNIST(split=:train)[:];" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "In MLJ, integers cannot be used for encoding categorical data, so we\n", + "must force the labels to have the `Multiclass` [scientific\n", + "type](https://juliaai.github.io/ScientificTypes.jl/dev/). For\n", + "more on this, see [Working with Categorical\n", + "Data](https://alan-turing-institute.github.io/MLJ.jl/dev/working_with_categorical_data/)." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "labels = coerce(labels, Multiclass);\n", + "images = coerce(images, GrayImage);" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Checking scientific types:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "@assert scitype(images) <: AbstractVector{<:Image}\n", + "@assert scitype(labels) <: AbstractVector{<:Finite}" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Looks good." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "For general instructions on coercing image data, see [Type coercion\n", + "for image\n", + "data](https://juliaai.github.io/ScientificTypes.jl/dev/#Type-coercion-for-image-data)" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "images[1]" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "We start by defining a suitable `Builder` object. This is a recipe\n", + "for building the neural network. Our builder will work for images of\n", + "any (constant) size, whether they be color or black and white (ie,\n", + "single or multi-channel). The architecture always consists of six\n", + "alternating convolution and max-pool layers, and a final dense\n", + "layer; the filter size and the number of channels after each\n", + "convolution layer is customisable." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "import MLJFlux\n", + "struct MyConvBuilder\n", + " filter_size::Int\n", + " channels1::Int\n", + " channels2::Int\n", + " channels3::Int\n", + "end\n", + "\n", + "function MLJFlux.build(b::MyConvBuilder, rng, n_in, n_out, n_channels)\n", + " k, c1, c2, c3 = b.filter_size, b.channels1, b.channels2, b.channels3\n", + " mod(k, 2) == 1 || error(\"`filter_size` must be odd. \")\n", + " p = div(k - 1, 2) # padding to preserve image size\n", + " init = Flux.glorot_uniform(rng)\n", + " front = Chain(\n", + " Conv((k, k), n_channels => c1, pad=(p, p), relu, init=init),\n", + " MaxPool((2, 2)),\n", + " Conv((k, k), c1 => c2, pad=(p, p), relu, init=init),\n", + " MaxPool((2, 2)),\n", + " Conv((k, k), c2 => c3, pad=(p, p), relu, init=init),\n", + " MaxPool((2 ,2)),\n", + " MLUtils.flatten)\n", + " d = Flux.outputsize(front, (n_in..., n_channels, 1)) |> first\n", + " return Chain(front, Dense(d, n_out, init=init))\n", + "end" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "**Notes.**" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "- There is no final `softmax` here, as this is applied by default in all MLJFLux\n", + " classifiers. Customisation of this behaviour is controlled using using the `finaliser`\n", + " hyperparameter of the classifier.\n", + "\n", + "- Instead of calculating the padding `p`, Flux can infer the required padding in each\n", + " dimension, which you enable by replacing `pad = (p, p)` with `pad = SamePad()`." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We now define the MLJ model." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "ImageClassifier = @load ImageClassifier\n", + "clf = ImageClassifier(\n", + " builder=MyConvBuilder(3, 16, 32, 32),\n", + " batch_size=50,\n", + " epochs=10,\n", + " rng=123,\n", + ")" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "You can add Flux options `optimiser=...` and `loss=...` in the above constructor\n", + "call. At present, `loss` must be a Flux-compatible loss, not an MLJ measure. To run on a\n", + "GPU, add to the constructor `acceleration=CUDALib()` and omit `rng`." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "For illustration purposes, we won't use all the data here:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "train = 1:500\n", + "test = 501:1000" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Binding the model with data in an MLJ machine:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "mach = machine(clf, images, labels);" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Training for 10 epochs on the first 500 images:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "fit!(mach, rows=train, verbosity=2);" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Inspecting:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "report(mach)" + ], + "metadata": {}, + "execution_count": null + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "chain = fitted_params(mach)" + ], + "metadata": {}, + "execution_count": null + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "Flux.params(chain)[2]" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Adding 20 more epochs:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "clf.epochs = clf.epochs + 20\n", + "fit!(mach, rows=train);" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Computing an out-of-sample estimate of the loss:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "predicted_labels = predict(mach, rows=test);\n", + "cross_entropy(predicted_labels, labels[test])" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "Or to fit and predict, in one line:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "evaluate!(mach,\n", + " resampling=Holdout(fraction_train=0.5),\n", + " measure=cross_entropy,\n", + " rows=1:1000,\n", + " verbosity=0)" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "## Wrapping the MLJFlux model with iteration controls" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Any iterative MLJFlux model can be wrapped in *iteration controls*,\n", + "as we demonstrate next. For more on MLJ's `IteratedModel` wrapper,\n", + "see the [MLJ\n", + "documentation](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/)." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The \"self-iterating\" classifier, called `iterated_clf` below, is for\n", + "iterating the image classifier defined above until one of the\n", + "following stopping criterion apply:" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "- `Patience(3)`: 3 consecutive increases in the loss\n", + "- `InvalidValue()`: an out-of-sample loss, or a training loss, is `NaN`, `Inf`, or `-Inf`\n", + "- `TimeLimit(t=5/60)`: training time has exceeded 5 minutes\n", + "\n", + "These checks (and other controls) will be applied every two epochs\n", + "(because of the `Step(2)` control). Additionally, training a\n", + "machine bound to `iterated_clf` will:\n", + "\n", + "- save a snapshot of the machine every three control cycles (every six epochs)\n", + "- record traces of the out-of-sample loss and training losses for plotting\n", + "- record mean value traces of each Flux parameter for plotting" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "For a complete list of controls, see [this\n", + "table](https://alan-turing-institute.github.io/MLJ.jl/dev/controlling_iterative_models/#Controls-provided)." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "### Wrapping the classifier" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Some helpers" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "To extract Flux params from an MLJFlux machine" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "parameters(mach) = vec.(Flux.params(fitted_params(mach)));" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "To store the traces:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "losses = []\n", + "training_losses = []\n", + "parameter_means = Float32[];\n", + "epochs = []" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "To update the traces:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "update_loss(loss) = push!(losses, loss)\n", + "update_training_loss(losses) = push!(training_losses, losses[end])\n", + "update_means(mach) = append!(parameter_means, mean.(parameters(mach)));\n", + "update_epochs(epoch) = push!(epochs, epoch)" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "The controls to apply:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "save_control =\n", + " MLJIteration.skip(Save(joinpath(DIR, \"mnist.jls\")), predicate=3)\n", + "\n", + "controls=[\n", + " Step(2),\n", + " Patience(3),\n", + " InvalidValue(),\n", + " TimeLimit(5/60),\n", + " save_control,\n", + " WithLossDo(),\n", + " WithLossDo(update_loss),\n", + " WithTrainingLossesDo(update_training_loss),\n", + " Callback(update_means),\n", + " WithIterationsDo(update_epochs),\n", + "];" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "The \"self-iterating\" classifier:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "iterated_clf = IteratedModel(\n", + " clf,\n", + " controls=controls,\n", + " resampling=Holdout(fraction_train=0.7),\n", + " measure=log_loss,\n", + ")" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### Binding the wrapped model to data:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "mach = machine(iterated_clf, images, labels);" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### Training" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "fit!(mach, rows=train);" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### Comparison of the training and out-of-sample losses:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "plot(\n", + " epochs,\n", + " losses,\n", + " xlab = \"epoch\",\n", + " ylab = \"cross entropy\",\n", + " label=\"out-of-sample\",\n", + ")\n", + "plot!(epochs, training_losses, label=\"training\")\n", + "\n", + "savefig(joinpath(DIR, \"loss.png\"))" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### Evolution of weights" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "n_epochs = length(losses)\n", + "n_parameters = div(length(parameter_means), n_epochs)\n", + "parameter_means2 = reshape(copy(parameter_means), n_parameters, n_epochs)'\n", + "plot(\n", + " epochs,\n", + " parameter_means2,\n", + " title=\"Flux parameter mean weights\",\n", + " xlab = \"epoch\",\n", + ")" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "**Note.** The higher the number in the plot legend, the deeper the layer we are\n", + "**weight-averaging." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "savefig(joinpath(DIR, \"weights.png\"))" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### Retrieving a snapshot for a prediction:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "mach2 = machine(joinpath(DIR, \"mnist3.jls\"))\n", + "predict_mode(mach2, images[501:503])" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### Restarting training" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Mutating `iterated_clf.controls` or `clf.epochs` (which is otherwise\n", + "ignored) will allow you to restart training from where it left off." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "iterated_clf.controls[2] = Patience(4)\n", + "fit!(mach, rows=train)\n", + "\n", + "plot(\n", + " epochs,\n", + " losses,\n", + " xlab = \"epoch\",\n", + " ylab = \"cross entropy\",\n", + " label=\"out-of-sample\",\n", + ")\n", + "plot!(epochs, training_losses, label=\"training\")" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/docs/src/extended_examples/MNIST/weights.png b/docs/src/extended_examples/MNIST/weights.png new file mode 100644 index 0000000000000000000000000000000000000000..df1fb43d8e1579391f86cf5347eb05b68d2697a5 GIT binary patch literal 35741 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

Mh=1rLYuxi&YxOe#Sr78u-mo2smw`*~5wQ=>oMB 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

k);Xw70X%n!N=+kB^hCyn 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