neuralplex 0.0.1__tar.gz → 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -158,3 +158,5 @@ cython_debug/
158
158
  # and can be added to the global gitignore or merged into this file. For a more nuclear
159
159
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
160
  #.idea/
161
+
162
+ *.ipynb
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: neuralplex
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: A Neuralplex.
5
5
  Project-URL: Homepage, https://github.com/faranalytics/neuralplex
6
6
  Project-URL: Issues, https://github.com/faranalytics/neuralplex/issues
@@ -9,7 +9,9 @@ License-File: LICENSE
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python :: 3
12
- Requires-Python: >=3.8
12
+ Requires-Python: >=3.11
13
13
  Description-Content-Type: text/markdown
14
14
 
15
- # neuralplex
15
+ # Neural-pleX
16
+
17
+ An object oriented neural network implementation.
@@ -0,0 +1,3 @@
1
+ # Neural-pleX
2
+
3
+ An object oriented neural network implementation.
@@ -4,13 +4,13 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "neuralplex"
7
- version = "0.0.1"
7
+ version = "0.0.2"
8
8
  authors = [
9
9
  { name="FAR Analytics & Research", email="adam@farar.net" },
10
10
  ]
11
11
  description = "A Neuralplex."
12
12
  readme = "README.md"
13
- requires-python = ">=3.8"
13
+ requires-python = ">=3.11"
14
14
  classifiers = [
15
15
  "Programming Language :: Python :: 3",
16
16
  "License :: OSI Approved :: MIT License",
@@ -0,0 +1,20 @@
1
+ from typing import List, Self
2
+
3
+ from neuralplex.perceptron import Perceptron
4
+
5
+
6
+ class Layer:
7
+
8
+ def __init__(self, perceptrons: List[Perceptron], deg: float = None):
9
+ self.perceptrons = perceptrons
10
+ self.deg = deg
11
+
12
+ if not self.deg is None:
13
+ for perceptron in self.perceptrons:
14
+ if perceptron.deg is None:
15
+ perceptron.deg = self.deg
16
+
17
+ def connect(self, layer: Self):
18
+ for p1 in self.perceptrons:
19
+ for p2 in layer.perceptrons:
20
+ p1.connectRHS(p2)
@@ -0,0 +1,43 @@
1
+ from typing import List
2
+ from neuralplex import Layer
3
+
4
+
5
+ class Network:
6
+
7
+ def __init__(self, layers: List[Layer]):
8
+ self.layers = layers
9
+ self.input = layers[0]
10
+ self.output = layers[len(layers) - 1]
11
+
12
+ for i in range(0, len(layers) - 1):
13
+ l1 = layers[i]
14
+ l2 = layers[i + 1]
15
+ l1.connect(l2)
16
+
17
+ def train(self, inputs: List[float], outputs: List[float]):
18
+ if len(self.input.perceptrons) != len(inputs):
19
+ raise Exception(
20
+ f'The length of the training values, {len(inputs)}, is not equal to the length of input perceptrons: {len(self.input.perceptrons)}')
21
+
22
+ if len(self.output.perceptrons) != len(outputs):
23
+ raise Exception(
24
+ f'The length of the training values, {len(outputs)}, is not equal to the length of output perceptrons: {len(self.output.perceptrons)}')
25
+
26
+ for i in range(0, len(inputs)):
27
+ self.input.perceptrons[i].activate(inputs[i])
28
+
29
+ for i in range(0, len(outputs)):
30
+ o = outputs[i]
31
+ p = self.output.perceptrons[i]
32
+ p.propagate(p.q-o)
33
+
34
+ def predict(self, inputs: List[float]):
35
+
36
+ if len(self.input.perceptrons) != len(inputs):
37
+ raise Exception(
38
+ f'The length of the training values, {len(inputs)}, is not equal to the length of input perceptrons: {len(self.input.perceptrons)}')
39
+
40
+ for i in range(0, len(inputs)):
41
+ self.input.perceptrons[i].activate(inputs[i])
42
+
43
+ return [perceptron.q for perceptron in self.output.perceptrons]
@@ -0,0 +1,77 @@
1
+ from typing import Dict, List, Self
2
+
3
+
4
+ class Perceptron:
5
+
6
+ def __init__(self, coef: float, deg: float = None, name=None):
7
+ self.coef = coef
8
+ self.deg = deg
9
+ self.name = name
10
+ self.perceptronsRHS: List[Self] = []
11
+ self.perceptronsLHS: List[Self] = []
12
+ self.activations: List[float] = []
13
+ self.propagation: Dict[float] = {}
14
+ self.q = 0
15
+
16
+ def connectRHS(self, perceptronRHS: Self):
17
+ if perceptronRHS not in self.perceptronsRHS:
18
+ self.perceptronsRHS.append(perceptronRHS)
19
+
20
+ if self not in perceptronRHS.perceptronsLHS:
21
+ perceptronRHS.connectLHS(self)
22
+
23
+ def connectLHS(self, perceptronLHS: Self):
24
+ if perceptronLHS not in self.perceptronsLHS:
25
+ self.perceptronsLHS.append(perceptronLHS)
26
+
27
+ if self not in perceptronLHS.perceptronsRHS:
28
+ perceptronLHS.connectRHS(self)
29
+
30
+ def disconnectRHS(self, perceptronRHS: Self):
31
+ if perceptronRHS in self.perceptronsRHS:
32
+ self.perceptronsRHS.remove(perceptronRHS)
33
+
34
+ if self in perceptronRHS.perceptronsLHS:
35
+ perceptronRHS.disconnectLHS(self)
36
+
37
+ if len(self.perceptronsRHS) == 0:
38
+ for perceptron in self.perceptronsLHS:
39
+ perceptron.disconnectRHS(self)
40
+
41
+ def disconnectLHS(self, perceptronLHS: Self):
42
+ if perceptronLHS in self.perceptronsLHS:
43
+ self.perceptronsLHS.remove(perceptronLHS)
44
+
45
+ if self in perceptronLHS.perceptronsRHS:
46
+ perceptronLHS.disconnectRHS(self)
47
+
48
+ if len(self.perceptronsLHS) == 0:
49
+ for perceptron in self.perceptronsRHS:
50
+ perceptron.disconnectLHS(self)
51
+
52
+ def activate(self, t: float):
53
+ self.activations.append(self.coef * t**self.deg)
54
+ # print(self.name, len(self.activations))
55
+ if len(self.perceptronsLHS) == 0 or len(self.activations) == len(self.perceptronsLHS):
56
+ self.q = sum(self.activations)
57
+ for perceptron in self.perceptronsRHS:
58
+ perceptron.activate(self.q)
59
+ self.activations = []
60
+
61
+ def propagate(self, t: float, p: Self = None):
62
+ self.propagation.update({p: t})
63
+ if len(self.perceptronsRHS) == 0 or len(self.propagation) == len(self.perceptronsRHS):
64
+ if len(self.perceptronsRHS) > 5:
65
+ perceptronRHS_max: Perceptron = max(
66
+ self.propagation, key=lambda x: abs(self.propagation.get(x)))
67
+ self.disconnectRHS(perceptronRHS_max)
68
+ print(self.name, self.propagation[perceptronRHS_max], len(
69
+ self.perceptronsRHS))
70
+ d = sum(self.propagation.values())
71
+ if d > 0:
72
+ self.coef = self.coef - 1e-4
73
+ else:
74
+ self.coef = self.coef + 1e-4
75
+ for perceptron in self.perceptronsLHS:
76
+ perceptron.propagate(d, self)
77
+ self.propagation = {}
@@ -0,0 +1,73 @@
1
+ import time
2
+ from random import random, randint
3
+ import json
4
+ import pickle
5
+ import numbers
6
+ import math
7
+ from sklearn.metrics import r2_score
8
+ from neuralplex import Network, Layer, Perceptron
9
+
10
+ EPOCHS = int(1e6)
11
+
12
+ l1 = Layer(
13
+ perceptrons=[
14
+ Perceptron(coef=random(), name='in-a'),
15
+ Perceptron(coef=random(), name='in-b'),
16
+ Perceptron(coef=random(), name='in-c'),
17
+ Perceptron(coef=random(), name='in-d'),
18
+ ],
19
+ deg=1,
20
+ )
21
+
22
+ # l2a = Layer(
23
+ # perceptrons=[Perceptron(coef=random()*1e2) for i in range(0, 10)], deg=2
24
+ # )
25
+
26
+ l2b = Layer(
27
+ perceptrons=[Perceptron(coef=random()*1e2) for i in range(0, 10)], deg=2
28
+ )
29
+
30
+ l3 = Layer(perceptrons=[Perceptron(coef=random(), name='out')], deg=1)
31
+
32
+ n1 = Network([l1, l2b, l3])
33
+
34
+ for i in range(0, EPOCHS):
35
+
36
+ rn = randint(1, 15)
37
+
38
+ b = [int(n) for n in bin(rn)[2:]]
39
+
40
+ while len(b) < 4:
41
+ b = [0] + b
42
+
43
+ n1.train(b, [rn])
44
+
45
+ pn = n1.predict(b)
46
+
47
+ print(f"{i} input: {json.dumps(b)}, truth: {rn} prediction: {json.dumps(pn)}")
48
+
49
+ # time.sleep(1)
50
+
51
+ y_true = []
52
+ y_pred = []
53
+ for i in range(1, 16):
54
+
55
+ b = [int(n) for n in bin(i)[2:]]
56
+
57
+ while len(b) < 4:
58
+ b = [0] + b
59
+
60
+ pn = n1.predict(b)
61
+
62
+ y_true.append(i)
63
+ y_pred.append(pn[0])
64
+
65
+ print(f"{i} input: {json.dumps(b)}, truth: {i} prediction: {json.dumps(pn)}")
66
+
67
+ R2 = r2_score(y_true, y_pred)
68
+
69
+ print(R2)
70
+
71
+ if R2 >= .7:
72
+ with open("model.pkl", "wb") as f:
73
+ pickle.dump(n1, f)
Binary file
@@ -1 +0,0 @@
1
- # neuralplex
@@ -1,14 +0,0 @@
1
- class Layer:
2
-
3
- def __init__(self, perceptrons, deg):
4
- self.perceptrons = perceptrons
5
- self.deg = deg
6
-
7
- if self.deg:
8
- for perceptron in self.perceptrons:
9
- perceptron.deg = self.deg
10
-
11
- def connect(self, layer):
12
- for p1 in self.perceptrons:
13
- for p2 in layer.perceptrons:
14
- p1.connect(p2)
@@ -1,36 +0,0 @@
1
- class Network:
2
-
3
- def __init__(self, layers):
4
- self.layers = layers;
5
- self.input = layers[0];
6
- self.output = layers[len(layers) - 1];
7
-
8
- for i in range(0, len(layers) - 1):
9
- l1 = layers[i]
10
- l2 = layers[i + 1]
11
- l1.connect(l2)
12
-
13
- def epoch(self, inputs, outputs):
14
- if len(self.input.perceptrons) != len(inputs):
15
- raise Exception(f'The length of the training values, {len(inputs)}, is not equal to the number of input perceptrons: {len(self.input.perceptrons)}')
16
-
17
- if len(self.output.perceptrons) != len(outputs):
18
- raise Exception(f'The length of the training values, {len(outputs)}, is not equal to the number of output perceptrons: {len(self.output.perceptrons)}')
19
-
20
- for i in range(0, len(inputs)):
21
- self.input.perceptrons[i].activate(inputs[i])
22
-
23
- for i in range(0, len(outputs)):
24
- o = outputs[i]
25
- p = self.output.perceptrons[i]
26
- p.propagate(p.q-o)
27
-
28
- def predict(self, inputs):
29
-
30
- if len(self.input.perceptrons) != len(inputs):
31
- raise Exception(f'The length of the training values, ${len(inputs)}, is not equal to the number of input perceptrons: {len(self.input.perceptrons)}')
32
-
33
- for i in range(0, len(inputs)):
34
- self.input.perceptrons[i].activate(inputs[i]);
35
-
36
- return [perceptron.q for perceptron in self.output.perceptrons]
@@ -1,35 +0,0 @@
1
- class Perceptron:
2
-
3
- def __init__(self, coef, deg=1):
4
- self.coef = coef
5
- self.deg = deg
6
- self.perceptronsRHS = []
7
- self.perceptronsLHS = []
8
- self.activations = []
9
- self.propagations = []
10
- self.q = 0
11
-
12
- def connect(self, perceptron):
13
- self.perceptronsRHS.append(perceptron);
14
- perceptron.perceptronsLHS.append(self);
15
-
16
- def activate(self, t):
17
- self.activations.append(self.coef * t**self.deg)
18
- if len(self.perceptronsLHS) == 0 or len(self.activations) == len(self.perceptronsLHS):
19
- self.q = sum(self.activations)
20
- for perceptron in self.perceptronsRHS:
21
- perceptron.activate(self.q)
22
- self.activations = []
23
-
24
- def propagate(self, t):
25
- self.propagations.append(t)
26
- if len(self.perceptronsRHS) == 0 or len(self.propagations) == len(self.perceptronsRHS):
27
- d = sum(self.propagations)
28
- if d > 0:
29
- self.coef = self.coef - 1e-5
30
- else:
31
- self.coef = self.coef + 1e-5
32
-
33
- for perceptron in self.perceptronsLHS:
34
- perceptron.propagate(d)
35
- self.propagations = []
@@ -1,83 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": null,
6
- "metadata": {},
7
- "outputs": [],
8
- "source": [
9
- "import random\n",
10
- "import json\n",
11
- "from neuralplex import Network, Layer, Perceptron"
12
- ]
13
- },
14
- {
15
- "cell_type": "code",
16
- "execution_count": null,
17
- "metadata": {},
18
- "outputs": [],
19
- "source": [
20
- "l1 = Layer(perceptrons=[\n",
21
- " Perceptron(coef=random.randint(0,1)),\n",
22
- " Perceptron(coef=random.randint(0,1)),\n",
23
- " Perceptron(coef=random.randint(0,1)),\n",
24
- " Perceptron(coef=random.randint(0,1))\n",
25
- "], deg=1)\n",
26
- "\n",
27
- "l2 = Layer(perceptrons=[Perceptron(coef=random.randint(0,1)) for i in range(0, 1000)], deg=2)\n",
28
- "\n",
29
- "l3 = Layer(perceptrons=[\n",
30
- " Perceptron(coef=random.randint(0,1))\n",
31
- "], deg=1)\n",
32
- "\n",
33
- "n1 = Network([l1, l2, l3])\n",
34
- "\n",
35
- "for i in range(0, int(1e5*3)):\n",
36
- "\n",
37
- " n = random.randint(1,15)\n",
38
- " \n",
39
- " binary = [int(i) for i in list('{0:0b}'.format(n))]\n",
40
- " \n",
41
- " while len(binary) < 4:\n",
42
- " binary = [0] + binary\n",
43
- "\n",
44
- " print(binary, n)\n",
45
- "\n",
46
- " n1.epoch(binary, [n])\n",
47
- "\n",
48
- " prediction = n1.predict(binary)\n",
49
- "\n",
50
- " if \n",
51
- " print(f'{i} input: {json.dumps(binary)}, truth: {n} prediction: {json.dumps(prediction)}')"
52
- ]
53
- },
54
- {
55
- "cell_type": "code",
56
- "execution_count": null,
57
- "metadata": {},
58
- "outputs": [],
59
- "source": []
60
- }
61
- ],
62
- "metadata": {
63
- "kernelspec": {
64
- "display_name": "py39",
65
- "language": "python",
66
- "name": "python3"
67
- },
68
- "language_info": {
69
- "codemirror_mode": {
70
- "name": "ipython",
71
- "version": 3
72
- },
73
- "file_extension": ".py",
74
- "mimetype": "text/x-python",
75
- "name": "python",
76
- "nbconvert_exporter": "python",
77
- "pygments_lexer": "ipython3",
78
- "version": "3.9.16"
79
- }
80
- },
81
- "nbformat": 4,
82
- "nbformat_minor": 2
83
- }
@@ -1,40 +0,0 @@
1
- import random
2
- import json
3
- from neuralplex import Network, Layer, Perceptron
4
-
5
- l1 = Layer(
6
- perceptrons=[
7
- Perceptron(coef=random.randint(0, 10)),
8
- Perceptron(coef=random.randint(0, 10)),
9
- Perceptron(coef=random.randint(0, 10)),
10
- Perceptron(coef=random.randint(0, 10)),
11
- ],
12
- deg=1,
13
- )
14
-
15
- l2 = Layer(
16
- perceptrons=[Perceptron(coef=random.randint(0, 1)) for i in range(0, 1000)], deg=2
17
- )
18
-
19
- l3 = Layer(perceptrons=[Perceptron(coef=random.randint(0, 1))], deg=1)
20
-
21
- n1 = Network([l1, l2, l3])
22
-
23
- for i in range(0, int(1e5 * 3)):
24
-
25
- n = random.randint(1, 15)
26
-
27
- binary = [int(i) for i in list("{0:0b}".format(n))]
28
-
29
- while len(binary) < 4:
30
- binary = [0] + binary
31
-
32
- print(binary, n)
33
-
34
- n1.epoch(binary, [n])
35
-
36
- prediction = n1.predict(binary)
37
-
38
- print(
39
- f"{i} input: {json.dumps(binary)}, truth: {n} prediction: {json.dumps(prediction)}"
40
- )
File without changes