refractoring

This commit is contained in:
2023-05-10 20:38:23 +07:00
commit 7c4a0dfa6f
15 changed files with 3195 additions and 0 deletions

1
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1 @@
{}

913
Manifest.toml Normal file
View File

@@ -0,0 +1,913 @@
# This file is machine-generated - editing it directly is not advised
julia_version = "1.9.0"
manifest_format = "2.0"
project_hash = "6da2bd801ebd94457c5a5cb36ae71250437066e8"
[[deps.AbstractFFTs]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "16b6dbc4cf7caee4e1e75c49485ec67b667098a0"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.3.1"
weakdeps = ["ChainRulesCore"]
[deps.AbstractFFTs.extensions]
AbstractFFTsChainRulesCoreExt = "ChainRulesCore"
[[deps.Accessors]]
deps = ["Compat", "CompositionsBase", "ConstructionBase", "Dates", "InverseFunctions", "LinearAlgebra", "MacroTools", "Requires", "Test"]
git-tree-sha1 = "a4f8669e46c8cdf68661fe6bb0f7b89f51dd23cf"
uuid = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
version = "0.1.30"
[deps.Accessors.extensions]
AccessorsAxisKeysExt = "AxisKeys"
AccessorsIntervalSetsExt = "IntervalSets"
AccessorsStaticArraysExt = "StaticArrays"
AccessorsStructArraysExt = "StructArrays"
[deps.Accessors.weakdeps]
AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5"
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
[[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "cc37d689f599e8df4f464b2fa3870ff7db7492ef"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.6.1"
weakdeps = ["StaticArrays"]
[deps.Adapt.extensions]
AdaptStaticArraysExt = "StaticArrays"
[[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.BFloat16s]]
deps = ["LinearAlgebra", "Printf", "Random", "Test"]
git-tree-sha1 = "dbf84058d0a8cbbadee18d25cf606934b22d7c66"
uuid = "ab4f0b2a-ad5b-11e8-123f-65d77653426b"
version = "0.4.2"
[[deps.BangBang]]
deps = ["Compat", "ConstructionBase", "Future", "InitialValues", "LinearAlgebra", "Requires", "Setfield", "Tables", "ZygoteRules"]
git-tree-sha1 = "7fe6d92c4f281cf4ca6f2fba0ce7b299742da7ca"
uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
version = "0.3.37"
[[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.CEnum]]
git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.2"
[[deps.CUDA]]
deps = ["AbstractFFTs", "Adapt", "BFloat16s", "CEnum", "CUDA_Driver_jll", "CUDA_Runtime_Discovery", "CUDA_Runtime_jll", "CompilerSupportLibraries_jll", "ExprTools", "GPUArrays", "GPUCompiler", "KernelAbstractions", "LLVM", "LazyArtifacts", "Libdl", "LinearAlgebra", "Logging", "Preferences", "Printf", "Random", "Random123", "RandomNumbers", "Reexport", "Requires", "SparseArrays", "SpecialFunctions", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "280893f920654ebfaaaa1999fbd975689051f890"
uuid = "052768ef-5323-5732-b1bb-66c8b64840ba"
version = "4.2.0"
[[deps.CUDA_Driver_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "498f45593f6ddc0adff64a9310bb6710e851781b"
uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc"
version = "0.5.0+1"
[[deps.CUDA_Runtime_Discovery]]
deps = ["Libdl"]
git-tree-sha1 = "bcc4a23cbbd99c8535a5318455dcf0f2546ec536"
uuid = "1af6417a-86b4-443c-805f-a4643ffb695f"
version = "0.2.2"
[[deps.CUDA_Runtime_jll]]
deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "5248d9c45712e51e27ba9b30eebec65658c6ce29"
uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2"
version = "0.6.0+0"
[[deps.CUDNN_jll]]
deps = ["Artifacts", "CUDA_Runtime_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "2918fbffb50e3b7a0b9127617587afa76d4276e8"
uuid = "62b44479-cb7b-5706-934f-f13b2eb2e645"
version = "8.8.1+0"
[[deps.Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"
[[deps.ChainRules]]
deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "Statistics", "StructArrays"]
git-tree-sha1 = "8bae903893aeeb429cf732cf1888490b93ecf265"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "1.49.0"
[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "e30f2f4e20f7f186dc36529910beaedc60cfa644"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.16.0"
[[deps.CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"
[[deps.Compat]]
deps = ["UUIDs"]
git-tree-sha1 = "7a60c856b9fa189eb34f5f8a6f6b5529b7942957"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.6.1"
weakdeps = ["Dates", "LinearAlgebra"]
[deps.Compat.extensions]
CompatLinearAlgebraExt = "LinearAlgebra"
[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.0.2+0"
[[deps.CompositionsBase]]
git-tree-sha1 = "455419f7e328a1a2493cabc6428d79e951349769"
uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b"
version = "0.1.1"
[[deps.ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "738fec4d684a9a6ee9598a8bfee305b26831f28c"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.5.2"
[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.DataAPI]]
git-tree-sha1 = "e8119c1a33d267e16108be441a287a6981ba1630"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.14.0"
[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.13"
[[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 = "a4ad7ef19d2cdc2eff57abbbe68032b1cd0bd8f8"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.13.0"
[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
[[deps.Distributions]]
deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "Test"]
git-tree-sha1 = "eead66061583b6807652281c0fbf291d7a9dc497"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.90"
[deps.Distributions.extensions]
DistributionsChainRulesCoreExt = "ChainRulesCore"
DistributionsDensityInterfaceExt = "DensityInterface"
[deps.Distributions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
[[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.ExprTools]]
git-tree-sha1 = "c1d06d129da9f55715c6c212866f5b1bddc5fa00"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.9"
[[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.FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
[[deps.FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "fc86b4fd3eff76c3ce4f5e96e2fdfa6282722885"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "1.0.0"
[[deps.Flux]]
deps = ["Adapt", "CUDA", "ChainRulesCore", "Functors", "LinearAlgebra", "MLUtils", "MacroTools", "NNlib", "NNlibCUDA", "OneHotArrays", "Optimisers", "Preferences", "ProgressLogging", "Random", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "Zygote", "cuDNN"]
git-tree-sha1 = "64005071944bae14fc145661f617eb68b339189c"
uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c"
version = "0.13.16"
[deps.Flux.extensions]
AMDGPUExt = "AMDGPU"
[deps.Flux.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
[[deps.FoldsThreads]]
deps = ["Accessors", "FunctionWrappers", "InitialValues", "SplittablesBase", "Transducers"]
git-tree-sha1 = "eb8e1989b9028f7e0985b4268dabe94682249025"
uuid = "9c68100b-dfe1-47cf-94c8-95104e173443"
version = "0.1.1"
[[deps.ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"]
git-tree-sha1 = "00e252f4d706b3d55a8863432e742bf5717b498d"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.35"
weakdeps = ["StaticArrays"]
[deps.ForwardDiff.extensions]
ForwardDiffStaticArraysExt = "StaticArrays"
[[deps.FunctionWrappers]]
git-tree-sha1 = "d62485945ce5ae9c0c48f124a84998d755bae00e"
uuid = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e"
version = "1.1.3"
[[deps.Functors]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "478f8c3145bb91d82c2cf20433e8c1b30df454cc"
uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
version = "0.4.4"
[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
[[deps.GPUArrays]]
deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"]
git-tree-sha1 = "9ade6983c3dbbd492cf5729f865fe030d1541463"
uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
version = "8.6.6"
[[deps.GPUArraysCore]]
deps = ["Adapt"]
git-tree-sha1 = "1cd7f0af1aa58abc02ea1d872953a97359cb87fa"
uuid = "46192b85-c4d5-4398-a991-12ede77f4527"
version = "0.1.4"
[[deps.GPUCompiler]]
deps = ["ExprTools", "InteractiveUtils", "LLVM", "Libdl", "Logging", "Scratch", "TimerOutputs", "UUIDs"]
git-tree-sha1 = "e9a9173cd77e16509cdf9c1663fda19b22a518b7"
uuid = "61eb1bfa-7361-4325-ad38-22787b887f55"
version = "0.19.3"
[[deps.GeneralUtils]]
deps = ["DataStructures", "Distributions", "JSON3"]
path = "C:\\Users\\naraw\\.julia\\dev\\GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
version = "0.1.0"
[[deps.HypergeometricFunctions]]
deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
git-tree-sha1 = "84204eae2dd237500835990bcade263e27674a93"
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
version = "0.3.16"
[[deps.IRTools]]
deps = ["InteractiveUtils", "MacroTools", "Test"]
git-tree-sha1 = "eac00994ce3229a464c2847e956d77a2c64ad3a5"
uuid = "7869d1d1-7146-5819-86e3-90919afe41df"
version = "0.4.10"
[[deps.InitialValues]]
git-tree-sha1 = "4da0f88e9a39111c2fa3add390ab15f3a44f3ca3"
uuid = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
version = "0.3.1"
[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
[[deps.InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "6667aadd1cdee2c6cd068128b3d226ebc4fb0c67"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.9"
[[deps.IrrationalConstants]]
git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.2.2"
[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"
[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.1"
[[deps.JSON3]]
deps = ["Dates", "Mmap", "Parsers", "SnoopPrecompile", "StructTypes", "UUIDs"]
git-tree-sha1 = "84b10656a41ef564c39d2d477d7236966d2b5683"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.12.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", "SparseArrays", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "47be64f040a7ece575c2b5f53ca6da7b548d69f4"
uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
version = "0.9.4"
[[deps.LLVM]]
deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Printf", "Unicode"]
git-tree-sha1 = "a8960cae30b42b66dd41808beb76490519f6f9e2"
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
version = "5.0.0"
[[deps.LLVMExtra_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "09b7505cc0b1cee87e5d4a26eea61d2e1b0dcd35"
uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab"
version = "0.0.21+0"
[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
version = "0.6.3"
[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
version = "7.84.0+0"
[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
version = "1.10.2+0"
[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
[[deps.LinearAlgebra]]
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
[[deps.LogExpFunctions]]
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "0a1b7c2863e44523180fdb3146534e265a91870b"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.23"
[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.MLStyle]]
git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8"
uuid = "d8e11817-5142-5d16-987a-aa16d5891078"
version = "0.4.17"
[[deps.MLUtils]]
deps = ["ChainRulesCore", "Compat", "DataAPI", "DelimitedFiles", "FLoops", "FoldsThreads", "NNlib", "Random", "ShowCases", "SimpleTraits", "Statistics", "StatsBase", "Tables", "Transducers"]
git-tree-sha1 = "ca31739905ddb08c59758726e22b9e25d0d1521b"
uuid = "f1d291b0-491e-4a28-83b9-f70985020b54"
version = "0.4.2"
[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "42324d08725e200c23d4dfb549e0d5d89dede2d2"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.10"
[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
version = "2.28.2+0"
[[deps.MicroCollections]]
deps = ["BangBang", "InitialValues", "Setfield"]
git-tree-sha1 = "629afd7d10dbc6935ec59b32daeb33bc4460a42e"
uuid = "128add7d-3638-4c79-886c-908ea0c25c34"
version = "0.1.4"
[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.1.0"
[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2022.10.11"
[[deps.NNlib]]
deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Pkg", "Random", "Requires", "Statistics"]
git-tree-sha1 = "99e6dbb50d8a96702dc60954569e9fe7291cc55d"
uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
version = "0.8.20"
[deps.NNlib.extensions]
NNlibAMDGPUExt = "AMDGPU"
[deps.NNlib.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
[[deps.NNlibCUDA]]
deps = ["Adapt", "CUDA", "LinearAlgebra", "NNlib", "Random", "Statistics", "cuDNN"]
git-tree-sha1 = "f94a9684394ff0d325cc12b06da7032d8be01aaf"
uuid = "a00861dc-f156-4864-bf3c-e6376f28a68d"
version = "0.2.7"
[[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.OneHotArrays]]
deps = ["Adapt", "ChainRulesCore", "Compat", "GPUArraysCore", "LinearAlgebra", "NNlib"]
git-tree-sha1 = "f511fca956ed9e70b80cd3417bb8c2dde4b68644"
uuid = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f"
version = "0.2.3"
[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
version = "0.3.21+4"
[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
version = "0.8.1+0"
[[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 = "6a01f65dd8583dee82eecc2a19b0ff21521aa749"
uuid = "3bd65402-5787-11e9-1adc-39752487f4e2"
version = "0.2.18"
[[deps.OrderedCollections]]
git-tree-sha1 = "d321bf2de576bf25ec4d3e4360faca399afca282"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.0"
[[deps.PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "67eae2738d63117a196f497d7db789821bce61d1"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.17"
[[deps.Parsers]]
deps = ["Dates", "SnoopPrecompile"]
git-tree-sha1 = "478ac6c952fddd4399e71d4779797c538d0ff2bf"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.5.8"
[[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.9.0"
[[deps.PrecompileTools]]
deps = ["Preferences"]
git-tree-sha1 = "259e206946c293698122f63e2b513a7c99a244e8"
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
version = "1.1.1"
[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.4.0"
[[deps.PrettyPrint]]
git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4"
uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98"
version = "0.2.0"
[[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.QuadGK]]
deps = ["DataStructures", "LinearAlgebra"]
git-tree-sha1 = "6ec7ac8412e83d57e313393220879ede1740f9ee"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.8.2"
[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
[[deps.Random123]]
deps = ["Random", "RandomNumbers"]
git-tree-sha1 = "552f30e847641591ba3f39fd1bed559b9deb0ef3"
uuid = "74087812-796a-5b5d-8853-05524746bad3"
version = "1.6.1"
[[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.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"
[[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", "Pkg"]
git-tree-sha1 = "6ed52fdd3382cf21947b15e8870ac0ddbff736da"
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
version = "0.4.0+0"
[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"
[[deps.Scratch]]
deps = ["Dates"]
git-tree-sha1 = "30449ee12237627992a99d5e30ae63e4d78cd24a"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.2.0"
[[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.SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"
[[deps.SnoopPrecompile]]
deps = ["Preferences"]
git-tree-sha1 = "e760a70afdcd461cf01a575947738d359234665c"
uuid = "66db9d55-30c0-4569-8b51-7e840670fc0c"
version = "1.0.3"
[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "a4ada03f999bd01b3a25dcaa30b2d929fe537e00"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.1.0"
[[deps.SparseArrays]]
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
[[deps.SpecialFunctions]]
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "ef28127915f4229c971eb43f3fc075dd3fe91880"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.2.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.StaticArrays]]
deps = ["LinearAlgebra", "Random", "StaticArraysCore", "Statistics"]
git-tree-sha1 = "c262c8e978048c2b095be1672c9bee55b4619521"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.5.24"
[[deps.StaticArraysCore]]
git-tree-sha1 = "6b7ba252635a5eff6a0b0664a41ee140a1c9e72a"
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
version = "1.4.0"
[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
version = "1.9.0"
[[deps.StatsAPI]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "45a7769a04a3cf80da1c1c7c60caf932e6f4c9f7"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.6.0"
[[deps.StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "75ebe04c5bed70b91614d684259b661c9e6274a4"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.34.0"
[[deps.StatsFuns]]
deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "f625d686d5a88bcd2b15cd81f18f98186fdc0c9a"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "1.3.0"
weakdeps = ["ChainRulesCore", "InverseFunctions"]
[deps.StatsFuns.extensions]
StatsFunsChainRulesCoreExt = "ChainRulesCore"
StatsFunsInverseFunctionsExt = "InverseFunctions"
[[deps.StructArrays]]
deps = ["Adapt", "DataAPI", "GPUArraysCore", "StaticArraysCore", "Tables"]
git-tree-sha1 = "521a0e828e98bb69042fec1809c1b5a680eb7389"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.15"
[[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", "Pkg", "libblastrampoline_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
version = "5.10.1+6"
[[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", "Test"]
git-tree-sha1 = "1544b926975372da01227b382066ab70e574a3ec"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.10.1"
[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
version = "1.10.0"
[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[[deps.TimerOutputs]]
deps = ["ExprTools", "Printf"]
git-tree-sha1 = "f548a9e9c490030e545f72074a41edfd0e5bcdd7"
uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
version = "0.5.23"
[[deps.Transducers]]
deps = ["Adapt", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "Setfield", "SplittablesBase", "Tables"]
git-tree-sha1 = "25358a5f2384c490e98abd565ed321ffae2cbb37"
uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999"
version = "0.4.76"
[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
[[deps.UnsafeAtomics]]
git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278"
uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f"
version = "0.2.1"
[[deps.UnsafeAtomicsLLVM]]
deps = ["LLVM", "UnsafeAtomics"]
git-tree-sha1 = "ea37e6066bf194ab78f4e747f5245261f17a7175"
uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
version = "0.1.2"
[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
version = "1.2.13+0"
[[deps.Zygote]]
deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "Random", "Requires", "SnoopPrecompile", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"]
git-tree-sha1 = "987ae5554ca90e837594a0f30325eeb5e7303d1e"
uuid = "e88e6eb3-aa80-5325-afca-941959d7151f"
version = "0.6.60"
[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 = "977aed5d006b840e2e40c0b48984f7463109046d"
uuid = "700de1a5-db45-46bc-99cf-38207098b444"
version = "0.2.3"
[[deps.cuDNN]]
deps = ["CEnum", "CUDA", "CUDNN_jll"]
git-tree-sha1 = "ec954b59f6b0324543f2e3ed8118309ac60cb75b"
uuid = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
version = "1.0.3"
[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
version = "5.7.0+0"
[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
version = "1.48.0+0"
[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
version = "17.4.0+0"

13
Project.toml Normal file
View File

@@ -0,0 +1,13 @@
name = "Ironpen"
uuid = "29a645ab-0d6f-4ef8-acfd-1b192480382c"
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"]
version = "0.1.0"
[deps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
GeneralUtils = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"

153
src/DB_services.jl Normal file
View File

@@ -0,0 +1,153 @@
module DB_services
""" version 0.2
"""
using DataStructures: count
export send_to_DB, data_prep_for_DB
using DataStructures
using JSON3
using Redis
using Random
using UUIDs
include("Utils.jl")
using .Utils
"""
Dummy iron_pen_ai for raw_data_db_service testing
"""
#------------------------------------------------------------------------------------------------100
""" Prepare model data for sending to raw_data_db_service by flattening all hierarchy
data structure inside model_data into 1-dept JSON3.
This function output is flattened JSON3 data
*** all parameter name that is going to Cassandra must not contain a capital letter ***
"""
function data_prep_for_DB(model_name::String, experiment_number::Int, episode_number::Int,
time_stamp::Int, model_data::OrderedDict)::Array{OrderedDict, 1}
payload_template = OrderedDict{Any, Any}(
:model_name => model_name,
:knowledgeFn_name => "none",
:experiment_number => experiment_number,
:episode_number => episode_number,
)
payloads = []
for (k, v) in model_data[:m][:knowledgeFn] # loop over each knowledgeFn
payload = deepcopy(payload_template)
payload[:knowledgeFn_name] = v[:knowledgefn_name]
payload[:neurons_list] = []
for (k1, v1) in v
if k1 == :neurons_array || k1 == :output_neurons_array
for (k2, v2) in v1 # loop over each neuron
if k2 != :type # add the following additonal data into neuron's ODict data (already have its parameters in there)
neuron = OrderedDict(v2) # v2 is still in JSON3 format but
# to be able to add new value to
# it, it needs to be in
# OrderedDict format
# # add corresponding knowledgeFn to neuron OrderedDict
# neuron[:knowledgefn_name] = v[:knowledgefn_name]
# add corresponding experiment_number to neuron OrderedDict
neuron[:experiment_number] = experiment_number
# add corresponding episode_number to neuron OrderedDict
neuron[:episode_number] = episode_number
# # add corresponding tick_number to neuron OrderedDict
# neuron[:tick_number] = tick_number
""" add neuron name of itself to neuron OrderedDict
since neurons in neurons_array and output_neurons_array has the
same name (because its name derived from its position in the
array it lives in). In order to store them in the same
OrderedDict, I need to change their name so I prefix their name
with their array name
"""
neuron[:neuron_name] = Symbol(string(k1) * "_" * string(k2))
neuron[:model_error] = model_data[:m][:model_error]
neuron[:knowledgefn_error] = model_data[:m][:knowledgeFn][k][:knowledgeFn_error]
neuron[:model_name] = model_name
# use as identifier durin debug
# neuron[:random] = Random.rand(1:100)
push!(payload[:neurons_list], neuron)
end
end
end
end
push!(payloads, payload)
end
return payloads
end
function send_to_DB(model_name::String, experiment_number::Int, episode_number::Int,
tick_number::Int, model_json_string::String, redis_server_ip::String,
pub_channel::String, sub_channel::String)
model_ordereddict = OrderedDict(JSON3.read(model_json_string))
payloads = data_prep_for_DB(model_name, experiment_number, episode_number, tick_number,
model_ordereddict)
for payload in payloads
# ask raw data service whether it is ready
# println("checking raw_data_db_service")
ask = Dict(:sender => "ironpen_ai",
:topic => "whois", # [uuid1(), "whois"] to get name of the receiver
:topic_id => uuid1(),
:responding_to => nothing, # receiver fills in the message uuid it is responding to
:communication_channel => sub_channel, # a channel that sender wants receiver to send message to or "none" to get message at receiver's default respond channel
:instruction => nothing,
:payload => nothing,
:isreturn => true)
incoming_message = Utils.service_query(redis_server_ip, pub_channel, sub_channel, ask)
# println("raw_data_db_service ok")
if UUID(incoming_message[:responding_to]) == ask[:topic_id]
message = Dict(:sender => "ironpen_ai",
:topic => "process", # [uuid1(), "whois"] to get name of the receiver
:topic_id => uuid1(),
:responding_to => nothing, # receiver fills in the message uuid it is responding to
:communication_channel => sub_channel, # a channel that sender wants receiver to send message to or "none" to get message at receiver's default respond channel
:instruction => "insert",
:payload => payload,
:isreturn => false)
result = Utils.service_query(redis_server_ip, pub_channel, sub_channel, message)
# println("published")
else
error("raw_data_db_service not respond")
end
end
end
end # module end

89
src/Ironpen.jl Normal file
View File

@@ -0,0 +1,89 @@
module Ironpen
export kfn_1
""" Order by dependencies of each file. The 1st included file must not depend on any other
files and each file can only depend on the file included before it.
"""
include("types.jl")
using .types # bring model into this module namespace (this module is a parent module)
include("snn_utils.jl")
using .snn_utils
# include("Save_and_load.jl")
# using .Save_and_load
# include("DB_services.jl")
# using .DB_services
include("forward.jl")
using .forward
include("learn.jl")
using .learn
include("readout.jl")
using .readout
include("interface.jl")
using .interface
#------------------------------------------------------------------------------------------------100
"""
Todo:
[*3] no "start learning" use reset learning and "inference", "learning" mode instead
[4] add time-based learning method. Also implement "thinking period"
[5] verify that model can complete learning cycle with no error
[6] neuroplasticity() with synaptic connection strength concept
[] using RL to control learning signal
[] consider using Dates.now() instead of timestamp because time_stamp may overflow
[] training should include adjusting α, neuron membrane potential decay factor
which defined by neuron.tau_m formular in type.jl
[DONE] each knowledgeFn should have its own noise generater
[DONE] where to put pseudo derivative (n.phi)
[DONE] add excitatory, inhabitory to neuron
Change from version: v06_36a
-
All features
- multidispatch + for loop as main compute method
- hard connection constrain yes
- normalize output yes
- allow -w_rec yes
- voltage drop when neuron fires voltage drop equals to vth
- v_t decay during refractory
duration exponantial decay
- input data population encoding, each pixel data =>
population encoding, ralative between pixel data
- compute neuron weight init rand()
- output neuron weight init randn()
"""
end # module end

200
src/WPembeddings.jl Normal file
View File

@@ -0,0 +1,200 @@
"
version 0.4
Word and Positional embedding module
"
module WPembeddings
using Embeddings
using JSON3
using Redis
include("Utils.jl")
export get_word_embedding, get_positional_embedding, wp_embedding
#----------------------------------------------------------------------------------------------
# user setting for word embedding
GloVe_embedding_filepath = "C:\\myWork\\my_projects\\AI\\NLP\\my_NLP\\glove.840B.300d.txt"
max_GloVe_vocab_size = 0 # size 10000+ or "all"
#----------------------------------------------------------------------------------------------
# load GloVe word embedding. URL of the embedding file: https://nlp.stanford.edu/projects/glove/
if max_GloVe_vocab_size == 0
# don't load vocab
elseif max_GloVe_vocab_size != "all"
@time const embtable = Embeddings.load_embeddings(GloVe{:en}, GloVe_embedding_filepath,
max_vocab_size=max_GloVe_vocab_size) # size 10000 or something
const get_word_index = Dict(word=>ii for (ii,word) in enumerate(embtable.vocab))
else
@time const embtable = Embeddings.load_embeddings(GloVe{:en}, GloVe_embedding_filepath)
const get_word_index = Dict(word=>ii for (ii,word) in enumerate(embtable.vocab))
end
# if max_GloVe_vocab_size != "all"
# @time const embtable = Embeddings.load_embeddings(GloVe{:en}, GloVe_embedding_filepath,
# max_vocab_size=max_GloVe_vocab_size) # size 10000 or something
# const get_word_index = Dict(word=>ii for (ii,word) in enumerate(embtable.vocab))
# elseif max_GloVe_vocab_size == 0
# else
# @time const embtable = Embeddings.load_embeddings(GloVe{:en}, GloVe_embedding_filepath)
# const get_word_index = Dict(word=>ii for (ii,word) in enumerate(embtable.vocab))
# end
"""
get_word_embedding(word::String)
Get embedding vector of a word. Its dimention is depend on GloVe file used
# Example
we_matrix = get_word_embedding("blue")
"""
function get_word_embedding(word::String)
index = get_word_index[word]
embedding = embtable.embeddings[:,index]
return embedding
end
"""
get_positional_embedding(total_word_position::Integer, word_embedding_dimension::Integer=300)
return positional embedding matrix of size [word_embedding_dimension * total_word_position]
# Example
pe_matrix = get_positional_embedding(length(content), 300)
"""
function get_positional_embedding(total_word_position::Integer, word_embedding_dimension::Integer=300)
d = word_embedding_dimension
p = total_word_position
pe = [x = i%2 == 0 ? cos(j/(10^(2i/d))) : sin(j/(10^(2i/d))) for i = 1:d, j = 1:p]
return pe
end
"""
wp_embedding(tokenized_word::Array{String}, positional_embedding::Bool=false)
Word embedding with positional embedding.
tokenized_word = sentense's tokenized word (not sentense in English definition but BERT definition.
1-BERT sentense can be 20+ English's sentense)
# Example
"""
function wp_embedding(tokenized_word::Array{String}, positional_embedding::Bool=false)
we_matrix = 0
for (i, v) in enumerate(tokenized_word)
if i == 1
we_matrix = get_word_embedding(v)
else
we_matrix = hcat(we_matrix, get_word_embedding(v))
end
end
if positional_embedding
pe_matrix = get_positional_embedding(length(tokenized_word), 300) # positional embedding
wp_matrix = we_matrix + pe_matrix
return wp_matrix
else
return we_matrix
end
end
"""
wp_query(tokenized_word::Array{String}, positional_embedding::Bool=false)
convert tokenized_word into JSON3 String to be sent to GloVe docker server
"""
function wp_query_send(tokenized_word::Array{String}, positional_embedding::Bool=false)
d = Dict("tokenized_word"=> tokenized_word, "positional_embedding"=>positional_embedding)
json3_str = JSON3.write(d)
return json3_str
end
"""
wp_query(tokenized_word::Array{String}, positional_embedding::Bool=false)
Using inside word_embedding_server to receive word embedding job
convert JSON3 String into tokenized_word and positional_embedding
"""
function wp_query_receive(json3_str::String)
d = JSON3.read(json3_str)
tokenized_word = Array(d.tokenized_word)
positional_embedding = d.positional_embedding
return tokenized_word, positional_embedding
end
"""
Send tokenized_word to word_embedding_server and return word embedding
# Example
WPembeddings.query_wp_server(tokenized_word)
"""
function query_wp_server(query;
host="0.0.0.0",
port=6379,
publish_channel="word_embedding_server/input",
positional_encoding=true)
# channel used to receive JSON String from word_embedding_server
wp_channel = Channel(10)
function wp_receive(x)
array = Utils.JSON3_str_to_Array(x)
put!(wp_channel, array)
end
# establish connection to word_embedding_server using default port
conn = Redis.RedisConnection(host=host, port=port)
sub = Redis.open_subscription(conn)
Redis.subscribe(sub, "word_embedding_server/output", wp_receive)
# Redis.subscribe(sub, "word_embedding_server/output", WPembeddings.wp_receive)
# set positional_encoding = true to enable positional encoding
query = WPembeddings.wp_query_send(query, positional_encoding)
# Ask word_embedding_server for word embedding
Redis.publish(conn, publish_channel, query);
wait(wp_channel) # wait for word_embedding_server to response
embedded_word = take!(wp_channel)
disconnect(conn)
return embedded_word
end
end

236
src/forward.jl Normal file
View File

@@ -0,0 +1,236 @@
module forward
using Flux.Optimise: apply!
using Statistics, Flux, Random, LinearAlgebra
using GeneralUtils
using ..types, ..snn_utils
#------------------------------------------------------------------------------------------------100
""" Model forward()
"""
function (m::model)(input_data::AbstractVector)
# m.global_tick += 1
m.time_stamp += 1
# process all corresponding KFN
raw_model_respond = m.knowledgeFn[:I](m, input_data)
# the 2nd return (KFN error) should not be used as model error but I use it because there is
# only one KFN in a model right now
return raw_model_respond
end
#------------------------------------------------------------------------------------------------100
""" knowledgeFn forward()
"""
function (kfn::kfn_1)(m::model, input_data::AbstractVector)
kfn.time_stamp = m.time_stamp
kfn.softreset = m.softreset
kfn.learning_stage = m.learning_stage
kfn.error = m.error
# generate noise
noise = [GeneralUtils.randomChoiceWithProb([true, false],[0.5,0.5])
for i in 1:length(input_data)]
# noise = [rand(rng, Distributions.Binomial(1, 0.5)) for i in 1:10] # another option
input_data = [noise; input_data] # noise start from neuron id 1
for n in kfn.neurons_array
timestep_forward!(n)
end
for n in kfn.output_neurons_array
timestep_forward!(n)
end
kfn.learning_stage = m.learning_stage
if kfn.learning_stage == "start_learning"
# reset params here instead of at the end_learning so that neuron's parameter data
# don't gets wiped and can be logged for visualization later
for n in kfn.neurons_array
# epsilon_rec need to be reset because it counting how many each synaptic fires and
# use this info to calculate how much synaptic weight should be adjust
reset_learning_params!(n)
end
# clear variables
kfn.firing_neurons_list = Vector{Int64}()
kfn.outputs = nothing
end
# pass input_data into input neuron.
# number of data point equals to number of input neuron starting from id 1
for (i, data) in enumerate(input_data)
kfn.neurons_array[i].z_t1 = data
end
kfn.snn_firing_state_t0 = [n.z_t for n in kfn.neurons_array] #TODO check if it is used?
#CHANGE Threads.@threads for n in kfn.neurons_array
for n in kfn.neurons_array
n(kfn)
end
kfn.snn_firing_state_t1 = [n.z_t1 for n in kfn.neurons_array]
append!(kfn.firing_neurons_list, findall(kfn.snn_firing_state_t1)) # store id of neuron that fires
if kfn.learning_stage == "end_learning" # use for random new neuron connection
kfn.firing_neurons_list |> unique!
end
# Threads.@threads for n in kfn.output_neurons_array
for n in kfn.output_neurons_array
n(kfn)
end
out = [n.out_t1 for n in kfn.output_neurons_array]
return out
end
#------------------------------------------------------------------------------------------------100
""" passthrough_neuron forward()
"""
function (n::passthrough_neuron)(kfn::knowledgeFn)
n.time_stamp = kfn.time_stamp
# n.global_tick = kfn.global_tick
end
#------------------------------------------------------------------------------------------------100
""" lif_neuron forward()
"""
function (n::lif_neuron)(kfn::knowledgeFn)
n.time_stamp = kfn.time_stamp
# pulling other neuron's firing status at time t
n.z_i_t = getindex(kfn.snn_firing_state_t0, n.subscription_list)
n.z_i_t .*= n.sub_ExIn_type
if n.refractory_counter != 0
n.refractory_counter -= 1
# neuron is in refractory state, skip all calculation
n.z_t1 = false # used by timestep_forward() in kfn. Set to zero because neuron spike
# last only 1 timestep follow by a period of refractory.
n.recurrent_signal = n.recurrent_signal * 0.0
# Exponantial decay of v_t1
n.v_t1 = n.v_t * n.alpha^(n.time_stamp - n.last_firing_time) # or n.v_t1 = n.alpha * n.v_t
else
n.recurrent_signal = sum(n.w_rec .* n.z_i_t) # signal from other neuron that this neuron subscribed
n.alpha_v_t = n.alpha * n.v_t
n.v_t1 = n.alpha_v_t + n.recurrent_signal
if n.v_t1 > n.v_th
n.z_t1 = true
n.refractory_counter = n.refractory_duration
n.firing_counter += 1
n.v_t1 = n.v_t1 - n.v_th
else
n.z_t1 = false
end
# there is a difference from alif formula
n.phi = (n.gamma_pd / n.v_th) * max(0, 1 - (n.v_t1 - n.v_th) / n.v_th)
end
end
#------------------------------------------------------------------------------------------------100
""" alif_neuron forward()
"""
function (n::alif_neuron)(kfn::knowledgeFn)
n.time_stamp = kfn.time_stamp
n.z_i_t = getindex(kfn.snn_firing_state_t0, n.subscription_list)
n.z_i_t .*= n.sub_ExIn_type
if n.refractory_counter != 0
n.refractory_counter -= 1
# neuron is in refractory state, skip all calculation
n.z_t1 = false # used by timestep_forward() in kfn. Set to zero because neuron spike last only 1 timestep follow by a period of refractory.
n.a = (n.rho * n.a) + ((1 - n.rho) * n.z_t)
n.recurrent_signal = n.recurrent_signal * 0.0
# Exponantial decay of v_t1
n.v_t1 = n.v_t * n.alpha^(n.time_stamp - n.last_firing_time) # or n.v_t1 = n.alpha * n.v_t
n.phi = 0
else
n.z_t = isnothing(n.z_t) ? false : n.z_t
n.a = (n.rho * n.a) + ((1 - n.rho) * n.z_t)
n.av_th = n.v_th + (n.beta * n.a)
n.recurrent_signal = sum(n.w_rec .* n.z_i_t) # signal from other neuron that this neuron subscribed
n.alpha_v_t = n.alpha * n.v_t
n.v_t1 = n.alpha_v_t + n.recurrent_signal
if n.v_t1 > n.av_th
n.z_t1 = true
n.refractory_counter = n.refractory_duration
n.firing_counter += 1
n.v_t1 = n.v_t1 - n.v_th
else
n.z_t1 = false
end
# there is a difference from lif formula
n.phi = (n.gamma_pd / n.v_th) * max(0, 1 - (n.v_t1 - n.av_th) / n.v_th)
end
end
#------------------------------------------------------------------------------------------------100
""" linear_neuron forward()
In this implementation, each output neuron is fully connected to every lif and alif neuron.
"""
function (n::linear_neuron)(kfn::T) where T<:knowledgeFn
n.time_stamp = kfn.time_stamp
n.out_t1 = getindex(kfn.snn_firing_state_t1, n.subscription_list)[1]
end
end # end module

79
src/interface.jl Normal file
View File

@@ -0,0 +1,79 @@
module interface
# export
# using
#------------------------------------------------------------------------------------------------100
end

304
src/learn.jl Normal file
View File

@@ -0,0 +1,304 @@
module learn
using Flux.Optimise: apply!
using Statistics, Flux, Random, LinearAlgebra
using GeneralUtils
using ..types
export learn!
#------------------------------------------------------------------------------------------------100
function learn!(m::model, model_respond, correct_answer)
if m.learning_stage == "learning"
model_error = Flux.logitcrossentropy(model_respond, correct_answer)
output_elements_error = model_respond - correct_answer
learn!(m.knowledgeFn[:I], model_error, output_elements_error)
#WORKING compute error
# if m.time_stamp < m.m
model_error = model_respond .- correct_answer
else
model_error = nothing
end
return model_error
end
function learn!(m::model, raw_model_respond, correct_answer=nothing)
if m.learning_stage != "doing_inference"
model_error = Flux.logitcrossentropy(raw_model_respond, correct_answer)
output_elements_error = raw_model_respond - correct_answer
learn!(m.knowledgeFn[:I], model_error, output_elements_error)
else
model_error = nothing
end
return model_error
end
""" knowledgeFn learn()
"""
function learn!(kfn::knowledgeFn, error::Union{Float64,Nothing}=nothing,
output_error::Union{Vector,Nothing}=nothing)
kfn.error = error
kfn.output_error = output_error
# Threads.@threads for n in kfn.neurons_array
for n in kfn.neurons_array
learn!(n, kfn) # Neurons are always learning, besides error from model output
end
if kfn.output_error !== nothing
# Threads.@threads for n in kfn.output_neurons_array
for n in kfn.output_neurons_array # not use multithreading because 1st output neuron
# will set learning rate that will be used by
# other output neurons
learn!(n, kfn)
end
#TODO: put other KFN to learn here
# for main loop user's display and training's exit condition
avg_neurons_firing_rate = 0.0
for n in kfn.neurons_array
if typeof(n) <: compute_neuron
avg_neurons_firing_rate += n.firing_rate
end
end
kfn.avg_neurons_firing_rate = avg_neurons_firing_rate /
kfn.kfn_params[:compute_neuron_number]
avg_neurons_v_t1 = 0.0
for n in kfn.neurons_array
if typeof(n) <: compute_neuron
avg_neurons_v_t1 += n.v_t1
end
end
kfn.avg_neurons_v_t1 = avg_neurons_v_t1 / kfn.kfn_params[:compute_neuron_number]
end
end
""" passthrough_neuron learn()
"""
function learn!(n::passthrough_neuron, kfn::knowledgeFn)
# skip
end
""" lif learn()
"""
function learn!(n::lif_neuron, kfn::knowledgeFn)
if n.learnable_flag == true
n.decayed_epsilon_rec = n.alpha * n.epsilon_rec
n.epsilon_rec = n.decayed_epsilon_rec + n.z_i_t
n.e_rec = n.phi * n.epsilon_rec
end
# a piece of knowledgeFn error that belongs to this neuron
n.error = isnothing(kfn.error) ? nothing : kfn.error * n.Bn
n.learning_stage = kfn.learning_stage
# accumulate voltage regularization terms
Snn_utils.cal_v_reg!(n)
if n.learning_stage == "doing_inference"
# no learning
elseif n.learning_stage == "start_learning" ||
n.learning_stage == "start_learning_no_wchange_reset"
# if error signal available then accumulates Δw
if n.error !== nothing
Snn_utils.firing_rate!(n)
Snn_utils.firing_diff!(n)
n.w_rec_change = n.w_rec_change +
-apply!(n.optimiser, n.w_rec,
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
-Snn_utils.firing_rate_regulator!(n) +
-Snn_utils.voltage_regulator!(n)
end
elseif n.learning_stage == "during_learning"
# if error signal available then accumulates Δw
if n.error !== nothing
Snn_utils.firing_rate!(n)
Snn_utils.firing_diff!(n)
n.w_rec_change = n.w_rec_change +
-apply!(n.optimiser, n.w_rec,
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
-Snn_utils.firing_rate_regulator!(n) +
-Snn_utils.voltage_regulator!(n)
end
elseif n.learning_stage == "end_learning"
# if error signal available then accumulates Δw
if n.error !== nothing
Snn_utils.firing_rate!(n)
Snn_utils.firing_diff!(n)
n.w_rec_change = n.w_rec_change +
-apply!(n.optimiser, n.w_rec,
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
-Snn_utils.firing_rate_regulator!(n) +
-Snn_utils.voltage_regulator!(n)
end
not_zero = (!iszero).(n.w_rec)
# set 0 in w_rec_change update according to 0 in w_rec for hard constrain connection
n.w_rec = n.w_rec + (not_zero .* n.w_rec_change)
replace!(x -> x < 0 ? 0 : x, n.w_rec) # no negative weight
Snn_utils.neuroplasticity!(n, kfn.firing_neurons_list)
end
end
""" alif_neuron learn()
"""
function learn!(n::alif_neuron, kfn::knowledgeFn)
n.decayed_epsilon_rec = n.alpha * n.epsilon_rec
n.epsilon_rec = n.decayed_epsilon_rec + n.z_i_t
n.epsilon_rec_a = (n.phi * n.epsilon_rec) +
((n.rho - (n.phi * n.beta)) * n.epsilon_rec_a)
n.e_rec_v = n.phi * n.epsilon_rec
n.e_rec_a = -n.phi * n.beta * n.epsilon_rec_a
n.e_rec = n.e_rec_v + n.e_rec_a
# a piece of knowledgeFn error that belongs to this neuron
n.error = isnothing(kfn.error) ? nothing : kfn.error * n.Bn
n.learning_stage = kfn.learning_stage
if n.learning_stage == "doing_inference"
# no learning
elseif n.learning_stage == "start_learning" ||
n.learning_stage == "start_learning_no_wchange_reset"
# if error signal available then accumulates Δw
if n.error !== nothing
Snn_utils.firing_rate!(n)
Snn_utils.firing_diff!(n)
n.w_rec_change = n.w_rec_change +
-apply!(n.optimiser, n.w_rec,
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
-Snn_utils.firing_rate_regulator!(n) +
-Snn_utils.voltage_regulator!(n)
end
elseif n.learning_stage == "during_learning"
# if error signal available then accumulates Δw
if n.error !== nothing
Snn_utils.firing_rate!(n)
Snn_utils.firing_diff!(n)
n.w_rec_change = n.w_rec_change +
-apply!(n.optimiser, n.w_rec,
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
-Snn_utils.firing_rate_regulator!(n) +
-Snn_utils.voltage_regulator!(n)
end
elseif n.learning_stage == "end_learning"
# if error signal available then accumulates Δw
if n.error !== nothing
Snn_utils.firing_rate!(n)
Snn_utils.firing_diff!(n)
n.w_rec_change = n.w_rec_change +
-apply!(n.optimiser, n.w_rec,
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
-Snn_utils.firing_rate_regulator!(n) +
-Snn_utils.voltage_regulator!(n)
end
not_zero = (!iszero).(n.w_rec)
# set 0 in w_rec_change update according to 0 in w_rec for hard constrain connection
n.w_rec = n.w_rec + (not_zero .* n.w_rec_change)
replace!(x -> x < 0 ? 0 : x, n.w_rec) # no negative weight
Snn_utils.neuroplasticity!(n, kfn.firing_neurons_list)
end
end
""" linear_neuron learn()
"""
function learn!(n::linear_neuron, kfn::knowledgeFn)
n.error = kfn.output_error[n.id]
n.learning_stage = kfn.learning_stage
if n.learning_stage == "doing_inference"
# no learning
elseif n.learning_stage == "start_learning"
# if error signal available then accumulates Δw
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
n.w_out_change = n.w_out_change + Δw
n.eta = n.optimiser.eta
Δb = -n.eta * n.error
n.b_change = n.b_change + Δb
elseif n.error !== nothing && n.id !== 1
n.eta = kfn.output_neurons_array[1].eta
Δw = -n.eta * n.error * n.epsilon_j
n.w_out_change = n.w_out_change + Δw
Δb = -n.eta * n.error
n.b_change = n.b_change + Δb
end
elseif n.learning_stage == "during_learning"
# if error signal available then accumulates Δw
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
n.w_out_change = n.w_out_change + Δw
n.eta = n.optimiser.eta
Δb = -n.eta * n.error
n.b_change = n.b_change + Δb
elseif n.error !== nothing && n.id !== 1
n.eta = kfn.output_neurons_array[1].eta
Δw = -n.eta * n.error * n.epsilon_j
n.w_out_change = n.w_out_change + Δw
Δb = -n.eta * n.error
n.b_change = n.b_change + Δb
end
elseif n.learning_stage == "end_learning"
# if error signal available then accumulates Δw
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
n.w_out_change = n.w_out_change + Δw
n.eta = n.optimiser.eta
Δb = -n.eta * n.error
n.b_change = n.b_change + Δb
elseif n.error !== nothing && n.id !== 1
n.eta = kfn.output_neurons_array[1].eta
Δw = -n.eta * n.error * n.epsilon_j
n.w_out_change = n.w_out_change + Δw
Δb = -n.eta * n.error
n.b_change = n.b_change + Δb
end
n.w_out = n.w_out + n.w_out_change
n.b = n.b + n.b_change
end
end
end # module end

83
src/readout.jl Normal file
View File

@@ -0,0 +1,83 @@
module readout
using Flux.Optimise: apply!
using Statistics, Flux, Random, LinearAlgebra
using GeneralUtils
using ..types, ..readout, ..learn, ..forward
export readout!
#------------------------------------------------------------------------------------------------100
function readout!(kfn::knowledgeFn; correctAnswer=nothing) # correctAnswer=nothing use for inference
# clear output to start reading
# kfn.on_out_t0 *= 0.0 #FIXME should I clear it before RSNN readout?
respondCount = zeros(length(kfn.on_out_t0))
# prepare signal used to read RSNN
readoutSignal = zeros(length(kfn.passthrough_zt0))
readoutSignal[1] = 1
readoutSignal[end] = 1
lastKfnTimeStamp = kfn.timeStamp[1]
for t in 1:kfn.on_tauOut[1]
# println("t $t")
tick = lastKfnTimeStamp + t
if t == kfn.on_tauOut[1]
println("")
end
if kfn.learningStage[1] == 0 # RSNN is in inference mode, do not change marker
# skip
else # RSNN is in learning mode, assign marker for commiting wChange at the end of readout window.
marker = t == kfn.on_tauOut[1] ? 4 : kfn.learningStage[1]
end
# RSNN forward ----------
singleTimeReadout, on_out_t0, softmaxRespond = kfn(readoutSignal, tick, marker,
correctAnswer=correctAnswer)
_, _, respondPosition = Utils.findMax(softmaxRespond)
respondCount += respondPosition
if correctAnswer !== nothing
kfn.kfnError = [Flux.logitcrossentropy(on_out_t0, correctAnswer)]
learn!(kfn)
end
end
_, readout, _ = Utils.findMax(respondCount/kfn.on_tauOut[1])
return readout, kfn.on_out_t0
end
end # module

319
src/snn_utils.jl Normal file
View File

@@ -0,0 +1,319 @@
module snn_utils
using Flux.Optimise: apply!
export calculate_α, calculate_ρ, calculate_k, timestep_forward!, init_neuron, no_negative,
precision, calculate_w_change!, store_knowledgefn_error!, interneurons_adjustment!,
reset_z_t!, reset_learning_params!, reset_learning_history_params!,
cal_v_reg!, calculate_w_change_end!,
firing_rate_error!, firing_rate_regulator!, update_Bn!, cal_firing_reg!,
neuroplasticity!, shakeup!, reset_learning_no_wchange!, adjust_internal_learning_rate!,
gradient_withloss
using Statistics, Random, LinearAlgebra, Distributions, Zygote
using ..types
#------------------------------------------------------------------------------------------------100
function timestep_forward!(x::passthrough_neuron)
x.z_t = x.z_t1
end
function timestep_forward!(x::compute_neuron)
x.z_t = x.z_t1
x.v_t = x.v_t1
end
function timestep_forward!(x::linear_neuron)
x.out_t = x.out_t1
end
no_negative(n) = n < 0.0 ? 0.0 : x
precision(x::Array{<:Array}) = ( std(mean.(x)) / mean(mean.(x)) ) * 100
# reset functions for LIF/ALIF neuron
reset_last_firing_time!(n::compute_neuron) = n.last_firing_time = 0.0
reset_refractory_state_active!(n::compute_neuron) = n.refractory_state_active = false
reset_v_t!(n::compute_neuron) = n.v_t = n.v_t_default
reset_z_t!(n::compute_neuron) = n.z_t = false
reset_epsilon_rec!(n::compute_neuron) = n.epsilon_rec = n.epsilon_rec * 0.0
reset_epsilon_rec_a!(n::alif_neuron) = n.epsilon_rec_a = n.epsilon_rec_a * 0.0
reset_epsilon_in!(n::compute_neuron) = n.epsilon_in = isnothing(n.epsilon_in) ? nothing : n.epsilon_in * 0.0
reset_error!(n::Union{compute_neuron, linear_neuron}) = n.error = nothing
reset_w_in_change!(n::compute_neuron) = n.w_in_change = isnothing(n.w_in_change) ? nothing : n.w_in_change * 0.0
reset_w_rec_change!(n::compute_neuron) = n.w_rec_change = n.w_rec_change * 0.0
reset_a!(n::alif_neuron) = n.a = n.a * 0.0
reset_reg_voltage_a!(n::compute_neuron) = n.reg_voltage_a = n.reg_voltage_a * 0.0
reset_reg_voltage_b!(n::compute_neuron) = n.reg_voltage_b = n.reg_voltage_b * 0.0
reset_reg_voltage_error!(n::compute_neuron) = n.reg_voltage_error = n.reg_voltage_error * 0.0
reset_firing_counter!(n::compute_neuron) = n.firing_counter = n.firing_counter * 0.0
reset_firing_diff!(n::Union{compute_neuron, linear_neuron}) = n.firing_diff = n.firing_diff * 0.0
reset_previous_error!(n::Union{compute_neuron}) =
n.previous_error = n.previous_error * 0.0
# reset function for output neuron
reset_epsilon_j!(n::linear_neuron) = n.epsilon_j = n.epsilon_j * 0.0
reset_out_t!(n::linear_neuron) = n.out_t = n.out_t * 0.0
reset_w_out_change!(n::linear_neuron) = n.w_out_change = n.w_out_change * 0.0
reset_b_change!(n::linear_neuron) = n.b_change = n.b_change * 0.0
""" Reset a part of learning-related params that used to collect learning history during learning
session
"""
# function reset_learning_no_wchange!(n::lif_neuron)
# reset_epsilon_rec!(n)
# # reset_v_t!(n)
# # reset_z_t!(n)
# # reset_reg_voltage_a!(n)
# # reset_reg_voltage_b!(n)
# # reset_reg_voltage_error!(n)
# reset_firing_counter!(n)
# reset_firing_diff!(n)
# reset_previous_error!(n)
# reset_error!(n)
# # # reset refractory state at the end of episode. Otherwise once neuron goes into refractory state,
# # # it will stay in refractory state forever
# # reset_refractory_state_active!(n)
# end
# function reset_learning_no_wchange!(n::Union{alif_neuron, elif_neuron})
# reset_epsilon_rec!(n)
# reset_epsilon_rec_a!(n)
# reset_v_t!(n)
# reset_z_t!(n)
# # reset_a!(n)
# reset_reg_voltage_a!(n)
# reset_reg_voltage_b!(n)
# reset_reg_voltage_error!(n)
# reset_firing_counter!(n)
# reset_firing_diff!(n)
# reset_previous_error!(n)
# reset_error!(n)
# # reset refractory state at the end of episode. Otherwise once neuron goes into refractory state,
# # it will stay in refractory state forever
# reset_refractory_state_active!(n)
# end
# function reset_learning_no_wchange!(n::linear_neuron)
# reset_epsilon_j!(n)
# reset_out_t!(n)
# reset_error!(n)
# end
""" Reset all learning-related params at the END of learning session
"""
function reset_learning_params!(n::lif_neuron)
reset_epsilon_rec!(n)
reset_w_rec_change!(n)
# reset_v_t!(n)
# reset_z_t!(n)
# reset_reg_voltage_a!(n)
# reset_reg_voltage_b!(n)
# reset_reg_voltage_error!(n)
reset_firing_counter!(n)
reset_firing_diff!(n)
reset_previous_error!(n)
reset_error!(n)
# # reset refractory state at the end of episode. Otherwise once neuron goes into refractory state,
# # it will stay in refractory state forever
# reset_refractory_state_active!(n)
end
function reset_learning_params!(n::alif_neuron)
reset_epsilon_rec!(n)
reset_epsilon_rec_a!(n)
reset_w_rec_change!(n)
# reset_v_t!(n)
# reset_z_t!(n)
# reset_a!(n)
# reset_reg_voltage_a!(n)
# reset_reg_voltage_b!(n)
# reset_reg_voltage_error!(n)
reset_firing_counter!(n)
reset_firing_diff!(n)
reset_previous_error!(n)
reset_error!(n)
# # reset refractory state at the end of episode. Otherwise once neuron goes into refractory state,
# # it will stay in refractory state forever
# reset_refractory_state_active!(n)
end
# function reset_learning_no_wchange!(n::passthrough_neuron)
# end
function reset_learning_params!(n::passthrough_neuron)
# skip
end
#------------------------------------------------------------------------------------------------100
function store_knowledgefn_error!(kfn::knowledgeFn)
# condition to adjust nueron in KFN plane in addition to weight adjustment inside each neuron
if kfn.learning_stage == "start_learning"
if kfn.recent_knowledgeFn_error === nothing && kfn.knowledgeFn_error === nothing
kfn.recent_knowledgeFn_error = [[]]
elseif kfn.recent_knowledgeFn_error === nothing
kfn.recent_knowledgeFn_error = [[kfn.knowledgeFn_error]]
elseif kfn.recent_knowledgeFn_error !== nothing && kfn.knowledgeFn_error === nothing
push!(kfn.recent_knowledgeFn_error, [])
else
push!(kfn.recent_knowledgeFn_error, [kfn.knowledgeFn_error])
end
elseif kfn.learning_stage == "during_learning"
if kfn.knowledgeFn_error === nothing
#skip
else
push!(kfn.recent_knowledgeFn_error[end], kfn.knowledgeFn_error)
end
elseif kfn.learning_stage == "end_learning"
if kfn.recent_knowledgeFn_error === nothing
#skip
else
push!(kfn.recent_knowledgeFn_error[end], kfn.knowledgeFn_error)
end
else
error("case does not defined yet")
end
if length(kfn.recent_knowledgeFn_error) > 3
deleteat!(kfn.recent_knowledgeFn_error, 1)
end
end
function update_Bn!(kfn::knowledgeFn)
Δw = nothing
for n in kfn.output_neurons_array
Δw = Δw === nothing ? n.w_out_change : Δw + n.w_out_change
n.w_out = n.w_out - (n.Bn_wout_decay * n.w_out) # w_out decay
end
# Δw = Δw / kfn.kfn_params[:linear_neuron_number] # average
input_neuron_number = kfn.kfn_params[:input_neuron_number] # skip input neuron
for i = 1:kfn.kfn_params[:compute_neuron_number]
n = kfn.neurons_array[input_neuron_number+i]
n.Bn = n.Bn + Δw[i]
n.Bn = n.Bn - (n.Bn_wout_decay * n.Bn) # w_out decay
end
end
""" Regulates membrane potential to stay under v_th, output is weight change
"""
function cal_v_reg!(n::lif_neuron)
# retified linear function
component_a1 = n.v_t1 - n.v_th < 0 ? 0 : (n.v_t1 - n.v_th)^2
component_a2 = -n.v_t1 - n.v_th < 0 ? 0 : (-n.v_t1 - n.v_th)^2
n.reg_voltage_a = n.reg_voltage_a + component_a1 + component_a2
component_b = n.v_t1 - n.v_th < 0 ? 0 : n.v_t1 - n.v_th
#FIXME: not sure the following line is correct
n.reg_voltage_b = n.reg_voltage_b + (component_b * n.epsilon_rec)
end
function cal_v_reg!(n::alif_neuron)
# retified linear function
component_a1 = n.v_t1 - n.av_th < 0 ? 0 : (n.v_t1 - n.av_th)^2
component_a2 = -n.v_t1 - n.av_th < 0 ? 0 : (-n.v_t1 - n.av_th)^2
n.reg_voltage_a = n.reg_voltage_a + component_a1 + component_a2
component_b = n.v_t1 - n.av_th < 0 ? 0 : n.v_t1 - n.av_th
#FIXME: not sure the following line is correct
n.reg_voltage_b = n.reg_voltage_b + (component_b * (n.epsilon_rec - n.epsilon_rec_a))
end
function voltage_error!(n::compute_neuron)
n.reg_voltage_error = 0.5 * n.reg_voltage_a
return n.reg_voltage_error
end
function voltage_regulator!(n::compute_neuron) # running average
Δw = n.optimiser.eta * n.c_reg_v * n.reg_voltage_b
return Δw
end
function firing_rate_error(kfn::knowledgeFn)
start_id = kfn.kfn_params[:input_neuron_number] + 1
return 0.5 * sum([(n.firing_diff)^2 for n in kfn.neurons_array[start_id:end]])
end
function firing_rate_regulator!(n::compute_neuron)
# n.firing_rate NOT running average (average over learning batch)
Δw = n.optimiser.eta * n.c_reg *
(n.firing_rate - n.firing_rate_target) * n.e_rec
Δw = n.firing_rate > n.firing_rate_target ? Δw : Δw * 0.0
return Δw
end
firing_rate!(n::compute_neuron) = n.firing_rate = (n.firing_counter / n.time_stamp) * 1000
firing_diff!(n::compute_neuron) = n.firing_diff = n.firing_rate - n.firing_rate_target
function neuroplasticity!(n::compute_neuron, firing_neurons_list::Vector)
# if there is 0-weight then replace it with new connection
zero_weight_index = findall(iszero.(n.w_rec))
if length(zero_weight_index) != 0
""" sampling new connection from list of neurons that fires instead of ramdom choose from
all compute neuron because there is no point to connect to neuron that not fires i.e.
not fire = no information
"""
subscribe_options = filter(x -> x [n.id], firing_neurons_list) # exclude this neuron id from the list
filter!(x -> x n.subscription_list, subscribe_options) # exclude this neuron's subscription_list from the list
shuffle!(subscribe_options)
end
new_connection_percent = 10 - ((n.optimiser.eta / 0.0001) / 10) # percent is in range 0.1 to 10
percentage = [new_connection_percent, 100.0 - new_connection_percent] / 100.0
for i in zero_weight_index
if Utils.random_choices([true, false], percentage)
n.subscription_list[i] = pop!(subscribe_options)
n.w_rec[i] = 0.01 # new connection should not send large signal otherwise it would throw
# RSNN off path. Let weight grow by an optimiser
end
end
end
function adjust_internal_learning_rate!(n::compute_neuron)
n.internal_learning_rate = n.error_diff[end] < 0.0 ? n.internal_learning_rate * 0.99 :
n.internal_learning_rate * 1.005
end
function push_epsilon_rec_a!(n::lif_neuron)
# skip
end
function push_epsilon_rec_a!(n::alif_neuron)
push!(n.epsilon_rec_a, 0)
end
end # end module

763
src/types.jl Normal file
View File

@@ -0,0 +1,763 @@
module types
export
# struct
IronpenStruct, model, knowledgeFn, lif_neuron, alif_neuron, linear_neuron,
kfn_1, compute_neuron, neuron, output_neuron, passthrough_neuron,
# function
instantiate_custom_types, init_neuron, populate_neuron,
add_neuron!
using Random, Flux, LinearAlgebra
#------------------------------------------------------------------------------------------------100
abstract type Ironpen end
abstract type knowledgeFn <: Ironpen end
abstract type neuron <: Ironpen end
abstract type input_neuron <: neuron end
abstract type output_neuron <: neuron end
abstract type compute_neuron <: neuron end
#------------------------------------------------------------------------------------------------100
""" Model struct
"""
Base.@kwdef mutable struct model <: Ironpen
knowledgeFn::Union{Dict,Nothing} = nothing
model_params::Union{Dict,Nothing} = nothing
error::Union{Float64,Nothing} = 0.0
output_error::Union{Array,Nothing} = Vector{AbstractFloat}()
""" "inference" = no learning params will be collected.
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
correct answer is available then merge Δw_rec_change into w_rec_change then
reset epsilon_j.
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
learning_stage::String = "inference"
softreset::Bool = false
time_stamp::Number = 0.0
end
""" Model outer constructor
# Example
I_kfnparams = Dict(
:type => "lif_neuron",
:v_t1 => 0.0, # neuron membrane potential at time = t+1
:v_th => 2.0, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
:z_t => false, # neuron firing status at time = t
:z_t1 => false, # neuron firing status at time = t+1
:gamma_pd => 0.3, # discount factor. The value is from the paper
:phi => 0.0, # psuedo derivative
:refractory_duration => 2.0, # neuron refractory period in tick
:delta => 1.0,
:tau_m => 20.0, # membrane time constant in millisecond. The value is from the paper
:eta => 0.01, # learning rate
I_kfn = Ironpen_ai_gpu.knowledgeFn(I_kfnparams, lif_neuron_params, alif_neuron_params,
linear_neuron_params)
model_params_1 = Dict(:knowledgeFn => Dict(:I => I_kfn,
:run => run_kfn),
:learning_stage => "doing_inference",)
model_1 = Ironpen_ai_gpu.model(model_params_1)
"""
function model(params::Dict)
m = model()
m.model_params = params
fields = fieldnames(typeof(m))
for i in fields
if i in keys(params)
m.:($i) = params[i] # assign params to n struct fields
end
end
return m
end
#------------------------------------------------------------------------------------------------100
""" knowledgeFn struct
"""
Base.@kwdef mutable struct kfn_1 <: knowledgeFn
knowledgefn_name::Union{String,Nothing} = nothing
kfn_params::Union{Dict,Nothing} = nothing # store params of knowledgeFn itself for later use
time_stamp::Number = 0.0
# Bn contain error coefficient for both neurons and output neurons in one place
Bn::Vector{Float64} = Vector{Float64}() # error projection coefficient from kfn output's error to each neurons's error
neurons_array::Union{Array,Nothing} = [] # put neurons here
""" put output neuron here. I seperate output neuron because
1. its calculation is difference than other neuron types
2. other neuron type will not induced to connnect to output neuron
3. output neuron does not induced to connect to its own type """
output_neurons_array::Union{Array,Nothing} = []
""" "inference" = no learning params will be collected.
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
correct answer is available then merge Δw_rec_change into w_rec_change then
reset epsilon_j.
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
learning_stage::String = "inference"
error::Union{Float64,Nothing} = nothing
output_error::Union{Array,Nothing} = Vector{AbstractFloat}()
recent_knowledgeFn_error::Union{Any,Nothing} = nothing
softreset::Bool = false
meta_params::Union{Dict{Any,Any},Nothing} = Dict()
firing_neurons_list::Array{Int64} = Vector{Int64}() # store id of firing neurons
snn_firing_state_t0::Union{Vector{Bool},Nothing} = nothing # store firing state of all neurons at t0
snn_firing_state_t1::Union{Vector{Bool},Nothing} = nothing # store firing state of all neurons at t1
avg_neurons_firing_rate::Union{Float64,Nothing} = 0.0 # for displaying average firing rate over all neurons
avg_neurons_v_t1::Union{Float64,Nothing} = 0.0 # for displaying average v_t1 over all neurons
end
#------------------------------------------------------------------------------------------------100
""" Knowledge function outer constructor >>> auto generate <<<
# Example
lif_neuron_params = Dict(
:type => "lif_neuron",
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
:z_t => false, # neuron firing status at time = t
:gamma_pd => 0.3, # discount factor. The value is from the paper
:refractory_duration => 2.0, # neuron refractory period in tick
:delta => 1.0,
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
)
alif_neuron_params = Dict(
:type => "alif_neuron",
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
:z_t => false, # neuron firing status at time = t
:gamma_pd => 0.3, # discount factor. The value is from the paper
:refractory_duration => 2.0, # neuron refractory period in millisecond
:delta => 1.0,
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
# adaptation time constant in millisecond. It should equals to total time SNN takes to
# perform a task i.e. equals to episode length
:tau_a => 10.0,
:beta => 0.15, # constant.
:a => 0.0,
)
linear_neuron_params = Dict(
:type => "linear_neuron",
:k => 0.9, # output leakink coefficient
:tau_out => 5.0, # output time constant in millisecond. It should equals to time use for 1 sequence
:out => 0.0, # neuron's output value store here
)
I_kfnparams = Dict(
:knowledgefn_name => "I",
:lif_neuron_number => 200,
:alif_neuron_number => 100, # from Allen Institute, ALIF is 40% of LIF
:linear_neuron_number => 5, # output neuron, this is also the output length
:Bn => "random", # error projection coefficient from kfn output's error to each neurons's error
:learning_rate => 0.01,
:neuron_connection_pattern => "100%", # number of each neuron subscribe to other neuron in knowledgeFn.neurons_array
:output_neuron_connection_pattern => "100%", # "60%" of kfn.neurons_array or number
:maximum_input_data_length => 5, # in case of GloVe word encoding, it is 300
:neuron_w_in_generation_pattern => "random", # number or "random"
:neuron_w_rec_generation_pattern => "random",
:neuron_v_t_default => 0.5,
:neuron_voltage_drop_percentage => "100%",
:neuron_firing_rate_target => 50.0,
:neuron_learning_rate => 0.01,
:neuron_c_reg => 0.0001,
:neuron_c_reg_v => 0.0001,
:neuron_optimiser => "ADAM",
:meta_params => Dict(:is_first_cycle => true,
:launch_time => 0.0,))
kfn1 = knowledgeFn(kfn_params, lif_neuron_params, alif_neuron_params, linear_neuron_params)
"""
function kfn_1(kfn_params::Dict)
kfn = kfn_1()
kfn.kfn_params = kfn_params
kfn.knowledgefn_name = kfn.kfn_params[:knowledgefn_name]
if kfn.kfn_params[:compute_neuron_number] < kfn.kfn_params[:total_input_port]
throw(error("number of compute neuron must be greater than input neuron"))
end
# Bn
if kfn.kfn_params[:Bn] == "random"
kfn.Bn = [Random.rand(0:0.001:1) for i in 1:kfn.kfn_params[:compute_neuron_number]]
else # in case I want to specify manually
kfn.Bn = [kfn.kfn_params[:Bn] for i in 1:kfn.kfn_params[:compute_neuron_number]]
end
# assign neurons ID by their position in kfn.neurons array because I think it is
# straight forward way
# add input port
for (k, v) in kfn.kfn_params[:input_port]
current_type = kfn.kfn_params[:input_port][k]
for i = 1:current_type[:numbers]
n_id = length(kfn.neurons_array) + 1
neuron = init_neuron(n_id, current_type[:params], kfn.kfn_params)
push!(kfn.neurons_array, neuron)
end
end
# add compute neurons
for (k, v) in kfn.kfn_params[:compute_neuron]
current_type = kfn.kfn_params[:compute_neuron][k]
for i = 1:current_type[:numbers]
n_id = length(kfn.neurons_array) + 1
neuron = init_neuron(n_id, current_type[:params], kfn.kfn_params)
push!(kfn.neurons_array, neuron)
end
end
for i = 1:kfn.kfn_params[:output_port][:numbers]
neuron = init_neuron(i, kfn.kfn_params[:output_port][:params],
kfn.kfn_params)
push!(kfn.output_neurons_array, neuron)
end
# random which neuron output port subscribed to, 1-compute_neuron for each output port
sub_list = shuffle!([kfn.kfn_params[:total_input_port]+1:length(kfn.neurons_array)...])
sub_output_neuron = [pop!(sub_list) for i in 1:kfn.kfn_params[:output_port][:numbers]]
for i in kfn.output_neurons_array
i.subscription_list = [pop!(sub_output_neuron)]
end
for n in kfn.neurons_array
if typeof(n) <: compute_neuron
n.firing_rate_target = kfn.kfn_params[:neuron_firing_rate_target]
end
end
# excitatory neuron to inhabitory neuron = 60:40 % of compute_neuron
ex_number = Int(floor(0.6 * kfn.kfn_params[:compute_neuron_number]))
ex_n = [1 for i in 1:ex_number]
in_number = kfn.kfn_params[:compute_neuron_number] - ex_number
in_n = [-1 for i in 1:in_number]
ex_in = shuffle!([ex_n; in_n])
# input neurons are always excitatory, compute_neurons are random between excitatory
# and inhabitory
for n in reverse(kfn.neurons_array)
try n.ExIn_type = pop!(ex_in) catch end
end
# add ExIn_type into each compute_neuron sub_ExIn_type
for n in reverse(kfn.neurons_array)
try # input neuron doest have n.subscription_list
for sub_id in n.subscription_list
n_ExIn_type = kfn.neurons_array[sub_id].ExIn_type
push!(n.sub_ExIn_type, n_ExIn_type)
end
catch
end
end
return kfn
end
#------------------------------------------------------------------------------------------------100
""" passthrough_neuron struct
"""
Base.@kwdef mutable struct passthrough_neuron <: input_neuron
id::Union{Int64,Nothing} = nothing # ID of this neuron which is it position in knowledgeFn array
type::String = "passthrough_neuron"
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
z_t::Bool = false
z_t1::Bool = false
time_stamp::Number = 0.0 # current time
ExIn_type::Integer = 1 # 1 excitatory, -1 inhabitory. input neuron is always excitatory
end
function passthrough_neuron(params::Dict)
n = passthrough_neuron()
field_names = fieldnames(typeof(n))
for i in field_names
if i in keys(params)
if i == :optimiser
opt_type = string(split(params[i], ".")[end])
n.:($i) = load_optimiser(opt_type)
else
n.:($i) = params[i] # assign params to n struct fields
end
end
end
return n
end
#------------------------------------------------------------------------------------------------100
""" lif_neuron struct
"""
Base.@kwdef mutable struct lif_neuron <: compute_neuron
id::Union{Int64,Nothing} = nothing # this neuron ID i.e. position of this neuron in knowledgeFn
type::String = "lif_neuron"
ExIn_type::Integer = 1 # 1 excitatory, -1 inhabitory
# Bn::Union{Float64,Nothing} = Random.rand() # Bias for neuron error
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
subscription_list::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
sub_ExIn_type::Array{Int64} = Vector{Int64}() # store ExIn type of subscribed neurons
time_stamp::Number = 0.0 # current time
w_rec::Union{Array{Float64},Nothing} = nothing # synaptic weight (for receiving signal from other neuron)
v_t::Float64 = 0.0 # vᵗ, postsynaptic neuron membrane potential of previous timestep
v_t1::Float64 = 0.0 # vᵗ⁺¹, postsynaptic neuron membrane potential at current timestep
v_t_default::Union{Float64,Nothing} = 0.0 # default membrane potential voltage
v_th::Float64 = 1.0 # vᵗʰ, neuron firing threshold
z_t::Bool = false # zᵗ, neuron postsynaptic firing of previous timestep
# zᵗ⁺¹, neuron firing status at time = t+1. I need this because the way I calculate all
# neurons forward function at each timestep-by-timestep is to do every neuron
# forward calculation. Each neuron requires access to other neuron's firing status
# during v_t1 calculation hence I need a variable to hold z_t1 so that I'm not replacing z_t
z_t1::Bool = false # neuron postsynaptic firing at current timestep (after neuron's calculation)
z_i_t::Union{Array{Bool},Nothing} = nothing # neuron presynaptic firing at current timestep (which is other neuron postsynaptic firing of previous timestep)
# Bn_wout_decay::Union{Float64,Nothing} = 0.01 # use to balance Bn and w_out
gamma_pd::Union{Float64,Nothing} = 0.3 # γ_pd, discount factor, value from paper
alpha::Union{Float64,Nothing} = nothing # α, neuron membrane potential decay factor
phi::Union{Float64,Nothing} = nothing # ϕ, psuedo derivative
epsilon_rec::Union{Array{Float64},Nothing} = nothing # ϵ_rec, eligibility vector for neuron spike
decayed_epsilon_rec::Union{Array{Float64},Nothing} = nothing # α * epsilon_rec
e_rec::Union{Array{Float64},Nothing} = nothing # eligibility trace for neuron spike
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
last_firing_time::Union{Float64,Nothing} = 0.0 # the last time neuron fires
refractory_duration::Union{Float64,Nothing} = 3 # neuron's refratory period in millisecond
# refractory_state_active::Union{Bool,Nothing} = false # if true, neuron is in refractory state and cannot process new information
refractory_counter::Integer = 0
tau_m::Union{Float64,Nothing} = nothing # τ_m, membrane time constant in millisecond
eta::Union{Float64,Nothing} = 0.01 # η, learning rate
w_rec_change::Union{Array{Float64},Nothing} = nothing # Δw_rec, cumulated w_rec change
recurrent_signal::Union{Float64,Nothing} = nothing # incoming recurrent signal
alpha_v_t::Union{Float64,Nothing} = nothing # alpha * v_t
voltage_drop_percentage::Union{Float64,Nothing} = 1.0 # voltage drop as a percentage of v_th
error::Union{Float64,Nothing} = nothing # local neuron error
optimiser::Union{Any,Nothing} = load_optimiser("AdaBelief") # Flux optimizer
firing_counter::Float64 = 0.0 # store how many times neuron fires
firing_rate_target::Float64 = 20.0 # neuron's target firing rate in Hz
firing_diff::Float64 = 0.0 # e-prop supplement paper equation 5
firing_rate_error::Float64 = 0.0 # local neuron error w.r.t. firing regularization
firing_rate::Float64 = 0.0 # running average of firing rate in Hz
current_error::Union{Float64,Nothing} = 0.0
previous_error::Union{Float64,Nothing} = 0.0
error_diff::Union{Array{Float64},Nothing} = Vector{Float64}()
""" "inference" = no learning params will be collected.
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
correct answer is available then merge Δw_rec_change into w_rec_change then
reset epsilon_j.
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
learning_stage::String = "inference"
end
""" lif neuron outer constructor
# Example
lif_neuron_params = Dict(
:type => "lif_neuron",
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
:z_t => false, # neuron firing status at time = t
:gamma_pd => 0.3, # discount factor. The value is from the paper
:refractory_duration => 2.0, # neuron refractory period in tick
:delta => 1.0,
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
)
neuron1 = lif_neuron(lif_neuron_params)
"""
function lif_neuron(params::Dict)
n = lif_neuron()
field_names = fieldnames(typeof(n))
for i in field_names
if i in keys(params)
if i == :optimiser
opt_type = string(split(params[i], ".")[end])
n.:($i) = load_optimiser(opt_type)
else
n.:($i) = params[i] # assign params to n struct fields
end
end
end
return n
end
#------------------------------------------------------------------------------------------------100
""" alif_neuron struct
"""
Base.@kwdef mutable struct alif_neuron <: compute_neuron
id::Union{Int64,Nothing} = nothing # this neuron ID i.e. position of this neuron in knowledgeFn
type::String = "alif_neuron"
ExIn_type::Integer = -1 # 1 excitatory, -1 inhabitory
# Bn::Union{Float64,Nothing} = Random.rand() # Bias for neuron error
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
subscription_list::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
sub_ExIn_type::Array{Int64} = Vector{Int64}() # store ExIn type of subscribed neurons
time_stamp::Union{Number,Nothing} = nothing # current time
w_rec::Union{Array{Float64},Nothing} = nothing # synaptic weight (for receiving signal from other neuron)
v_t::Float64 = 0.0 # vᵗ, postsynaptic neuron membrane potential of previous timestep
v_t1::Float64 = 0.0 # vᵗ⁺¹, postsynaptic neuron membrane potential at current timestep
v_t_default::Union{Float64,Nothing} = 0.0
v_th::Float64 = 1.0 # vᵗʰ, neuron firing threshold
z_t::Bool = false # zᵗ, neuron postsynaptic firing of previous timestep
# zᵗ⁺¹, neuron firing status at time = t+1. I need this because the way I calculate all
# neurons forward function at each timestep-by-timestep is to do every neuron
# forward calculation. Each neuron requires access to other neuron's firing status
# during v_t1 calculation hence I need a variable to hold z_t1 so that I'm not replacing z_t
z_t1::Bool = false # neuron postsynaptic firing at current timestep (after neuron's calculation)
z_i_t::Union{Array{Bool},Nothing} = nothing # neuron presynaptic firing at current timestep (which is other neuron postsynaptic firing of previous timestep)
# Bn_wout_decay::Union{Float64,Nothing} = 0.01 # use to balance Bn and w_out
alpha::Union{Float64,Nothing} = nothing # α, neuron membrane potential decay factor
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
epsilon_rec::Union{Array{Float64},Nothing} = nothing # ϵ_rec(v), eligibility vector for neuron i spike
epsilon_rec_a::Union{Array{Float64},Nothing} = nothing # ϵ_rec(a)
decayed_epsilon_rec::Union{Array{Float64},Nothing} = nothing # α * epsilon_rec
e_rec_v::Union{Array{Float64},Nothing} = nothing # a component of neuron's eligibility trace resulted from v_t
e_rec_a::Union{Array{Float64},Nothing} = nothing # a component of neuron's eligibility trace resulted from av_th
e_rec::Union{Array{Float64},Nothing} = nothing # neuron's eligibility trace
eta::Union{Float64,Nothing} = 0.01 # eta, learning rate
gamma_pd::Union{Float64,Nothing} = 0.3 # γ_pd, discount factor, value from paper
last_firing_time::Union{Float64,Nothing} = 0.0 # the last time neuron fires
phi::Union{Float64,Nothing} = nothing # ϕ, psuedo derivative
refractory_duration::Union{Float64,Nothing} = 3 # neuron's refractory period in millisecond
# refractory_state_active::Union{Bool,Nothing} = false # if true, neuron is in refractory state and cannot process new information
refractory_counter::Integer = 0
tau_m::Union{Float64,Nothing} = nothing # τ_m, membrane time constant in millisecond
w_rec_change::Union{Array{Float64},Nothing} = nothing # Δw_rec, cumulated w_rec change
recurrent_signal::Union{Float64,Nothing} = nothing # incoming recurrent signal
alpha_v_t::Union{Float64,Nothing} = nothing # alpha * v_t
voltage_drop_percentage::Union{Float64,Nothing} = 1.0 # voltage drop as a percentage of v_th
error::Union{Float64,Nothing} = nothing # local neuron error
optimiser::Union{Any,Nothing} = load_optimiser("AdaBelief") # Flux optimizer
firing_counter::Float64 = 0.0 # store how many times neuron fires
firing_rate_target::Float64 = 20.0 # neuron's target firing rate in Hz
firing_diff::Float64 = 0.0 # e-prop supplement paper equation 5
firing_rate_error::Float64 = 0.0 # local neuron error w.r.t. firing regularization
firing_rate::Float64 = 0.0 # running average of firing rate, Hz
current_error::Union{Float64,Nothing} = 0.0
previous_error::Union{Float64,Nothing} = 0.0
error_diff::Union{Array{Float64},Nothing} = Vector{Float64}()
tau_a::Union{Float64,Nothing} = nothing # τ_a, adaption time constant in millisecond
beta::Union{Float64,Nothing} = 0.15 # β, constant, value from paper
rho::Union{Float64,Nothing} = nothing # ρ, threshold adaptation decay factor
a::Union{Float64,Nothing} = 0.0 # threshold adaptation
av_th::Union{Float64,Nothing} = nothing # adjusted neuron firing threshold
""" "inference" = no learning params will be collected.
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
correct answer is available then merge Δw_rec_change into w_rec_change then
reset epsilon_j.
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
learning_stage::String = "inference"
end
""" alif neuron outer constructor
# Example
alif_neuron_params = Dict(
:type => "alif_neuron",
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I
use auto generate)
:z_t => false, # neuron firing status at time = t
:gamma_pd => 0.3, # discount factor. The value is from the paper
:refractory_duration => 2.0, # neuron refractory period in millisecond
:delta => 1.0,
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use
for 1 sequence
# adaptation time constant in millisecond. It should equals to total time SNN takes to
# perform a task i.e. equals to episode length
:tau_a => 10.0,
:beta => 0.15, # constant.
:a => 0.0,
)
neuron1 = alif_neuron(alif_neuron_params)
"""
function alif_neuron(params::Dict)
n = alif_neuron()
field_names = fieldnames(typeof(n))
for i in field_names
if i in keys(params)
if i == :optimiser
opt_type = string(split(params[i], ".")[end])
n.:($i) = load_optimiser(opt_type)
else
n.:($i) = params[i] # assign params to n struct fields
end
end
end
return n
end
#------------------------------------------------------------------------------------------------100
""" linear_neuron struct
"""
Base.@kwdef mutable struct linear_neuron <: output_neuron
id::Union{Int64,Nothing} = nothing # ID of this neuron which is it position in knowledgeFn array
type::String = "linear_neuron"
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
subscription_list::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
time_stamp::Union{Number,Nothing} = nothing # current time
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
out_t::Bool = false # output of linear neuron BEFORE forward()
out_t1::Bool = false # output of linear neuron AFTER forward()
end
""" linear neuron outer constructor
# Example
linear_neuron_params = Dict(
:type => "linear_neuron",
:k => 0.9, # output leakink coefficient
:tau_out => 5.0, # output time constant in millisecond. It should equals to time use for 1 sequence
:out => 0.0, # neuron's output value store here
)
neuron1 = linear_neuron(linear_neuron_params)
"""
function linear_neuron(params::Dict)
n = linear_neuron()
field_names = fieldnames(typeof(n))
for i in field_names
if i in keys(params)
if i == :optimiser
opt_type = string(split(params[i], ".")[end])
n.:($i) = load_optimiser(opt_type)
else
n.:($i) = params[i] # assign params to n struct fields
end
end
end
return n
end
#------------------------------------------------------------------------------------------------100
function load_optimiser(optimiser_name::String; params::Union{Dict,Nothing} = nothing)
if optimiser_name == "AdaBelief"
params = (0.01, (0.9, 0.8))
return Flux.Optimise.AdaBelief(params...)
elseif optimiser_name == "AdaBelief2"
# output neuron requires slower change pace so η is lower than compute neuron at 0.007
# because if w_out change too fast, compute neuron will not able to
# grapse output neuron moving direction i.e. both compute neuron's direction and
# output neuron direction are out of sync.
params = (0.007, (0.9, 0.8))
return Flux.Optimise.AdaBelief(params...)
else
error("optimiser is not defined yet in load_optimiser()")
end
end
function init_neuron!(id::Int64, n::passthrough_neuron, n_params::Dict, kfn_params::Dict)
n.id = id
n.knowledgefn_name = kfn_params[:knowledgefn_name]
end
# function init_neuron!(id::Int64, n::lif_neuron, kfn_params::Dict)
# n.id = id
# n.knowledgefn_name = kfn_params[:knowledgefn_name]
# subscription_options = shuffle!([1:(kfn_params[:input_neuron_number]+kfn_params[:compute_neuron_number])...])
# if typeof(kfn_params[:synaptic_connection_number]) == String
# percent = parse(Int, kfn_params[:synaptic_connection_number][1:end-1]) / 100
# synaptic_connection_number = floor(length(subscription_options) * percent)
# n.subscription_list = [pop!(subscription_options) for i = 1:synaptic_connection_number]
# end
# filter!(x -> x != n.id, n.subscription_list)
# n.epsilon_rec = zeros(length(n.subscription_list))
# n.w_rec = Random.rand(length(n.subscription_list))
# n.w_rec_change = zeros(length(n.subscription_list))
# n.reg_voltage_b = zeros(length(n.subscription_list))
# n.alpha = calculate_α(n)
# end
function init_neuron!(id::Int64, n::lif_neuron, n_params::Dict, kfn_params::Dict)
n.id = id
n.knowledgefn_name = kfn_params[:knowledgefn_name]
subscription_options = shuffle!([1:kfn_params[:total_neurons]...])
subscription_numbers = Int(floor(n_params[:synaptic_connection_number] *
kfn_params[:total_neurons] / 100.0))
n.subscription_list = [pop!(subscription_options) for i = 1:subscription_numbers]
# prevent subscription to itself by removing this neuron id
filter!(x -> x != n.id, n.subscription_list)
n.epsilon_rec = zeros(length(n.subscription_list))
n.w_rec = Random.rand(length(n.subscription_list))
n.w_rec_change = zeros(length(n.subscription_list))
# n.reg_voltage_b = zeros(length(n.subscription_list))
n.alpha = calculate_α(n)
end
function init_neuron!(id::Int64, n::alif_neuron, n_params::Dict,
kfn_params::Dict)
n.id = id
n.knowledgefn_name = kfn_params[:knowledgefn_name]
subscription_options = shuffle!([1:kfn_params[:total_neurons]...])
subscription_numbers = Int(floor(n_params[:synaptic_connection_number] *
kfn_params[:total_neurons] / 100.0))
n.subscription_list = [pop!(subscription_options) for i = 1:subscription_numbers]
# prevent subscription to itself by removing this neuron id
filter!(x -> x != n.id, n.subscription_list)
n.epsilon_rec = zeros(length(n.subscription_list))
n.w_rec = Random.rand(length(n.subscription_list))
n.w_rec_change = zeros(length(n.subscription_list))
# n.reg_voltage_b = zeros(length(n.subscription_list))
n.alpha = calculate_α(n) # the more time has passed from the last time neuron was
# activated, the more neuron membrane potential is reduced
n.rho = calculate_ρ(n)
n.epsilon_rec_a = zeros(length(n.subscription_list))
end
# function init_neuron!(id::Int64, n::linear_neuron, kfn_params::Dict)
# n.id = id
# n.knowledgefn_name = kfn_params[:knowledgefn_name]
# start_id = kfn_params[:input_neuron_number] + 1 # don't readout from input neurons
# n.subscription_list = [start_id:(start_id+kfn_params[:compute_neuron_number]-1)...]
# n.epsilon_j = zeros(length(n.subscription_list))
# n.w_out = Random.randn(length(n.subscription_list))
# n.w_out_change = zeros(length(n.subscription_list))
# n.b = Random.randn()
# n.b_change = 0.0
# n.k = calculate_k(n)
# end
#WORKING
function init_neuron!(id::Int64, n::linear_neuron, n_params::Dict, kfn_params::Dict)
n.id = id
n.knowledgefn_name = kfn_params[:knowledgefn_name]
# start_id = kfn_params[:total_input_port] + 1 # don't readout from input neurons
# subscription_options = [start_id:(start_id+kfn_params[:total_compute_neuron]-1)...]
# n.subscription_list = [rand(subscription_options)]
# n.epsilon_j = zeros(length(n.subscription_list))
# n.w_out = Random.randn(length(n.subscription_list))
# n.w_out_change = zeros(length(n.subscription_list))
# n.b = Random.randn()
# n.b_change = 0.0
# n.k = calculate_k(n)
end
""" Make a neuron intended for use with knowledgeFn
"""
function init_neuron(id::Int64, n_params::Dict, kfn_params::Dict)
n = instantiate_custom_types(n_params)
init_neuron!(id, n, n_params, kfn_params)
return n
end
""" This function instantiate Ironpen type.
# Example
new_model = instantiate_custom_types("model")
"""
function instantiate_custom_types(params::Union{Dict,Nothing} = nothing)
type = string(split(params[:type], ".")[end])
if type == "model"
return model()
elseif type == "knowledgeFn"
return knowledgeFn()
elseif type == "passthrough_neuron"
return passthrough_neuron(params)
elseif type == "lif_neuron"
return lif_neuron(params)
elseif type == "alif_neuron"
return alif_neuron(params)
elseif type == "linear_neuron"
return linear_neuron(params)
else
return nothing
end
end
""" Add a new neuron into a knowledgeFn
# Example
add_neuron!(kfn.kfn_params[:lif_neuron_params], kfn)
"""
# function add_neuron!(neuron_Dict::Dict, kfn::knowledgeFn)
# id = length(kfn.neurons_array) + 1
# neuron = init_neuron(id, neuron_Dict, kfn.kfn_params,
# total_neurons = (length(kfn.neurons_array) + 1))
# push!(kfn.neurons_array, neuron)
# # Randomly select an output neuron to add a new neuron to
# add_n_output_n!(Random.rand(kfn.output_neurons_array), id)
# end
""" Add a new neuron to output neuron's subscription_list
"""
function add_n_output_n!(o_n::linear_neuron, id::Int64)
push!(o_n.subscription_list, id)
push!(o_n.epsilon_j, 0.0)
push!(o_n.w_out, Random.randn(1)[1])
push!(o_n.w_out_change, 0.0)
end
calculate_α(neuron::lif_neuron) = exp(-neuron.delta / neuron.tau_m)
calculate_α(neuron::alif_neuron) = exp(-neuron.delta / neuron.tau_m)
calculate_ρ(neuron::alif_neuron) = exp(-neuron.delta / neuron.tau_a)
calculate_k(neuron::linear_neuron) = exp(-neuron.delta / neuron.tau_out)
#------------------------------------------------------------------------------------------------100
end # module end

0
test/etc2.jl Normal file
View File

15
test/etc3.jl Normal file
View File

@@ -0,0 +1,15 @@
src_folder = "C:\\myWork\\my_projects\\AI\\NLP\\my_NLP\\Ironpen_ai\\src"
include("$src_folder/Utils.jl")
using .Utils
pub = "ch1"
sub = "ch2"
function p(x)
println("function called")
return x + 1
end
service_server("192.168.0.10", pub, sub, "testserver", p)

View File

@@ -0,0 +1,27 @@
using Revise
using Ironpen_ai
using DataStructures
using JSON3
using Redis
# file_location = "C:\\myWork\\my_projects\\AI\\NLP\\my_NLP\\Ironpen_ai\\"
# filename = "tonModel_2.json"
# jsonString = read(file_location * filename, String)
# jsonObject = JSON3.read(jsonString)
# model_data = OrderedDict(jsonObject)
# Ironpen_ai.data_prep_for_db(1, 1, 1, model_data)