{"id":16701773,"url":"https://github.com/mrdimosthenis/clj-synapses","last_synced_at":"2025-03-14T06:41:52.278Z","repository":{"id":57721669,"uuid":"395815068","full_name":"mrdimosthenis/clj-synapses","owner":"mrdimosthenis","description":"A neural networks library for Clojure","archived":false,"fork":false,"pushed_at":"2021-08-15T08:14:40.000Z","size":170,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-21T01:26:39.129Z","etag":null,"topics":["clojure","deep-learning","functional-programming","machine-learning","neural-network"],"latest_commit_sha":null,"homepage":"https://cljdoc.org/d/org.clojars.mrdimosthenis/clj-synapses/1.0.3/doc/readme","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mrdimosthenis.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-13T22:28:51.000Z","updated_at":"2025-01-12T17:49:07.000Z","dependencies_parsed_at":"2022-09-26T21:51:33.672Z","dependency_job_id":null,"html_url":"https://github.com/mrdimosthenis/clj-synapses","commit_stats":null,"previous_names":["mrdimosthenis/synapses-clj"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrdimosthenis%2Fclj-synapses","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrdimosthenis%2Fclj-synapses/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrdimosthenis%2Fclj-synapses/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrdimosthenis%2Fclj-synapses/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrdimosthenis","download_url":"https://codeload.github.com/mrdimosthenis/clj-synapses/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243538121,"owners_count":20307101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","deep-learning","functional-programming","machine-learning","neural-network"],"created_at":"2024-10-12T18:45:33.722Z","updated_at":"2025-03-14T06:41:52.258Z","avatar_url":"https://github.com/mrdimosthenis.png","language":"Clojure","funding_links":[],"categories":["Machine Learning"],"sub_categories":[],"readme":"# clj-synapses\n\nA **neural networks** library for **Clojure**!\n\n## Basic usage\n\n### Install synapses\n\n```clojure\n[org.clojars.mrdimosthenis/clj-synapses \"1.0.3\"]\n```\n\n### Load the `net` namespace\n\n```clojure\n(require '[clj-synapses.net :as net])\n```\n\n### Create a random neural network by providing its layer sizes\n\n```clojure\n(def rand-network\n  (net/-\u003enet\n    [2 3 1]))\n```\n\n* Input layer: the first layer of the network has 2 nodes.\n* Hidden layer: the second layer has 3 neurons.\n* Output layer: the third layer has 1 neuron.\n\n### Get the json of the random neural network\n\n```clojure\n(net/-\u003ejson\n  rand-network)\n;;=\u003e \"[[{\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [-0.5,0.1,0.8]},\n;;      {\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [0.7,0.6,-0.1]},\n;;      {\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [-0.8,-0.1,-0.7]}],\n;;     [{\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [0.5,-0.3,-0.4,-0.5]}]]\"\n```\n\n### Create a neural network by providing its json\n\n```clojure\n(def network\n  (net/json-\u003e\n    \"[[{\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [-0.5,0.1,0.8]},\n       {\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [0.7,0.6,-0.1]},\n       {\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [-0.8,-0.1,-0.7]}],\n      [{\\\"activationF\\\" : \\\"sigmoid\\\", \\\"weights\\\" : [0.5,-0.3,-0.4,-0.5]}]]\"))\n```\n\n### Make a prediction\n\n```clojure\n(net/predict\n  network\n  [0.2 0.6])\n;;=\u003e [0.49131100324012494]\n```\n\n### Train a neural network\n\n```clojure\n(net/fit\n  network\n  0.1\n  [0.2 0.6]\n  [0.9])\n```\n\nThe `fit` function returns a new neural network with the weights adjusted to a single observation.\n\n## Advanced usage\n\n### Fully train a neural network\n\nIn practice, for a neural network to be fully trained, it should be fitted with multiple observations, usually by\nreducing over a collection.\n\n```clojure\n(reduce\n  (fn [acc [xs ys]]\n    (net/fit acc 0.1 xs ys))\n  network\n  [[[0.2 0.6] [0.9]]\n   [[0.1 0.8] [0.2]]\n   [[0.5 0.4] [0.6]]])\n```\n\n### Boost the performance\n\nEvery function is efficient because its implementation is based on lazy list and all information is obtained at a single\npass.\n\nFor a neural network that has huge layers, the performance can be further improved by using the parallel counterparts\nof `net/predict` and `net/fit` (`net/par-predict` and `net/par-fit`).\n\n### Create a neural network for testing\n\n```clojure\n(net/-\u003enet\n  [2 3 1]\n  1000)\n```\n\nWe can provide a `seed` to create a non-random neural network. This way, we can use it for testing.\n\n### Define the activation functions and the weights\n\n```clojure\n(require '[clj-synapses.fun :as fun])\n\n(defn activation-f\n  [layer-index]\n  (condp = layer-index\n    0 fun/sigmoid\n    1 fun/identity\n    2 fun/leaky-re-lu\n    3 fun/tanh))\n\n(defn weight-init-f\n  [layer-index]\n  (* (inc layer-index)\n     (- 1 (* 2.0 (rand)))))\n\n(def custom-network\n  (net/-\u003enet\n    [4 6 8 5 3]\n    activation-f\n    weight-init-f))\n```\n\n* The `activation-f` function accepts the index of a layer and returns an activation function for its neurons.\n* The `weight-initf` function accepts the index of a layer and returns a weight for the synapses of its neurons.\n\nIf we don't provide these functions, the activation function of all neurons is sigmoid, and the weight distribution of\nthe synapses is normal between -1.0 and 1.0.\n\n### Draw a neural network\n\n```clojure\n(net/-\u003esvg\n  custom-network)\n```\n\n![Network Drawing](https://github.com/mrdimosthenis/scala-synapses/blob/master/neural_network.png?raw=true)\n\nWith its svg drawing, we can see what a neural network looks like. The color of each neuron depends on its activation\nfunction while the transparency of the synapses depends on their weight.\n\n### Measure the difference between the expected and predicted values\n\n```clojure\n(require '[clj-synapses.stats :as stats])\n\n(def exp-and-pred-vals\n  [[[0.0 0.0 1.0] [0.0 0.1 0.9]]\n   [[0.0 1.0 0.0] [0.8 0.2 0.0]]\n   [[1.0 0.0 0.0] [0.7 0.1 0.2]]\n   [[1.0 0.0 0.0] [0.3 0.3 0.4]]\n   [[0.0 0.0 1.0] [0.2 0.2 0.6]]])\n```\n\n* Root-mean-square error\n\n```clojure\n(stats/rmse\n  exp-and-pred-vals)\n;;=\u003e 0.6957010852370435\n```\n\n* Classification accuracy score\n\n```clojure\n(stats/score\n  exp-and-pred-vals)\n;;=\u003e 0.6\n```\n\n### Load the `codec` namespace\n\n```clojure\n(require '[clj-synapses.codec :as codec])\n```\n\n* One hot encoding is a process that turns discrete attributes into a list of 0.0 and 1.0.\n* Minmax normalization scales continuous attributes into values between 0.0 and 1.0.\n\n```clojure\n(def setosa\n  {\"petal_length\" \"1.5\"\n   \"petal_width\"  \"0.1\"\n   \"sepal_length\" \"4.9\"\n   \"sepal_width\"  \"3.1\"\n   \"species\"      \"setosa\"})\n\n(def versicolor\n  {\"petal_length\" \"3.8\"\n   \"petal_width\"  \"1.1\"\n   \"sepal_length\" \"5.5\"\n   \"sepal_width\"  \"2.4\"\n   \"species\"      \"versicolor\"})\n\n(def virginica\n  {\"petal_length\" \"6.0\"\n   \"petal_width\"  \"2.2\"\n   \"sepal_length\" \"5.0\"\n   \"sepal_width\"  \"1.5\"\n   \"species\"      \"virginica\"})\n\n(def dataset\n  [setosa\n   versicolor\n   virginica])\n```\n\nYou can use a `codec` to encode and decode a data point.\n\n### Create a `codec` by providing the attributes and the data points\n\n```clojure\n(def preprocessor\n  (codec/-\u003ecodec\n    [[\"petal_length\" false]\n     [\"petal_width\" false]\n     [\"sepal_length\" false]\n     [\"sepal_width\" false]\n     [\"species\" true]]\n    dataset))\n)\n```\n\n* The first parameter is a vector of pairs that define the name and the type (discrete or not) of each attribute.\n* The second parameter is a collection that contains the data points.\n\n### Get the json of the codec\n\n```clojure\n(codec/-\u003ejson\n  preprocessor)\n;;=\u003e \"[{\\\"Case\\\" : \\\"SerializableContinuous\\\",\n;;      \\\"Fields\\\" : [{\\\"key\\\" : \\\"petal_length\\\",\\\"min\\\" : 1.5,\\\"max\\\" : 6.0}]},\n;;     {\\\"Case\\\" : \\\"SerializableContinuous\\\",\n;;      \\\"Fields\\\" : [{\\\"key\\\" : \\\"petal_width\\\",\\\"min\\\" : 0.1,\\\"max\\\" : 2.2}]},\n;;     {\\\"Case\\\" : \\\"SerializableContinuous\\\",\n;;      \\\"Fields\\\" : [{\\\"key\\\" : \\\"sepal_length\\\",\\\"min\\\" : 4.9,\\\"max\\\" : 5.5}]},\n;;     {\\\"Case\\\" : \\\"SerializableContinuous\\\",\n;;      \\\"Fields\\\" : [{\\\"key\\\" : \\\"sepal_width\\\",\\\"min\\\" : 1.5,\\\"max\\\" : 3.1}]},\n;;     {\\\"Case\\\" : \\\"SerializableDiscrete\\\",\n;;      \\\"Fields\\\" : [{\\\"key\\\" : \\\"species\\\",\\\"values\\\" : [\\\"virginica\\\",\\\"versicolor\\\",\\\"setosa\\\"]}]}]\"\n```\n\n### Create a codec by providing its json\n\n```clojure\n(codec/json-\u003e\n  \"[{\\\"Case\\\" : \\\"SerializableContinuous\\\",\n     \\\"Fields\\\" : [{\\\"key\\\" : \\\"petal_length\\\",\\\"min\\\" : 1.5,\\\"max\\\" : 6.0}]},\n    {\\\"Case\\\" : \\\"SerializableContinuous\\\",\n     \\\"Fields\\\" : [{\\\"key\\\" : \\\"petal_width\\\",\\\"min\\\" : 0.1,\\\"max\\\" : 2.2}]},\n    {\\\"Case\\\" : \\\"SerializableContinuous\\\",\n     \\\"Fields\\\" : [{\\\"key\\\" : \\\"sepal_length\\\",\\\"min\\\" : 4.9,\\\"max\\\" : 5.5}]},\n    {\\\"Case\\\" : \\\"SerializableContinuous\\\",\n     \\\"Fields\\\" : [{\\\"key\\\" : \\\"sepal_width\\\",\\\"min\\\" : 1.5,\\\"max\\\" : 3.1}]},\n    {\\\"Case\\\" : \\\"SerializableDiscrete\\\",\n     \\\"Fields\\\" : [{\\\"key\\\" : \\\"species\\\",\\\"values\\\" : [\\\"virginica\\\",\\\"versicolor\\\",\\\"setosa\\\"]}]}]\")\n```\n\n### Encode a data point\n\n```clojure\n(def encoded-setosa\n  (codec/encode\n    preprocessor\n    setosa))\n;; [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0]\n```\n\n### Decode a data point\n\n```clojure\n(codec/decode\n  preprocessor\n  encoded-setosa)\n;;=\u003e {\"species\"      \"setosa\"\n;;    \"sepal_width\"  \"3.1\"\n;;    \"petal_width\"  \"0.1\",\n;;    \"petal_length\" \"1.5\"\n;;    \"sepal_length\" \"4.9\"}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrdimosthenis%2Fclj-synapses","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrdimosthenis%2Fclj-synapses","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrdimosthenis%2Fclj-synapses/lists"}