neuralplex 0.0.2__tar.gz → 0.0.4__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.
@@ -159,4 +159,5 @@ cython_debug/
159
159
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
160
  #.idea/
161
161
 
162
- *.ipynb
162
+ *.ipynb
163
+ *.pkl
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: neuralplex
3
- Version: 0.0.2
3
+ Version: 0.0.4
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
@@ -14,4 +14,25 @@ Description-Content-Type: text/markdown
14
14
 
15
15
  # Neural-pleX
16
16
 
17
- An object oriented neural network implementation.
17
+ An object oriented neural network implementation.
18
+
19
+ ## Installation
20
+ ```bash
21
+ pip install neuralplex
22
+ ```
23
+ ## Run the Test
24
+
25
+ Install the package using the [Installation](#installation) instructions.
26
+
27
+ ### Clone the repository.
28
+ ```bash
29
+ git clone https://github.com/faranalytics/neuralplex.git
30
+ ```
31
+ ### Change directory into the repository.
32
+ ```bash
33
+ cd neuralplex
34
+ ```
35
+ ### Run the tests.
36
+ ```bash
37
+ python -m unittest -v
38
+ ```
@@ -0,0 +1,24 @@
1
+ # Neural-pleX
2
+
3
+ An object oriented neural network implementation.
4
+
5
+ ## Installation
6
+ ```bash
7
+ pip install neuralplex
8
+ ```
9
+ ## Run the Test
10
+
11
+ Install the package using the [Installation](#installation) instructions.
12
+
13
+ ### Clone the repository.
14
+ ```bash
15
+ git clone https://github.com/faranalytics/neuralplex.git
16
+ ```
17
+ ### Change directory into the repository.
18
+ ```bash
19
+ cd neuralplex
20
+ ```
21
+ ### Run the tests.
22
+ ```bash
23
+ python -m unittest -v
24
+ ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "neuralplex"
7
- version = "0.0.2"
7
+ version = "0.0.4"
8
8
  authors = [
9
9
  { name="FAR Analytics & Research", email="adam@farar.net" },
10
10
  ]
@@ -5,16 +5,16 @@ from neuralplex.perceptron import Perceptron
5
5
 
6
6
  class Layer:
7
7
 
8
- def __init__(self, perceptrons: List[Perceptron], deg: float = None):
8
+ def __init__(self, perceptrons: List[Perceptron], step: float = None):
9
9
  self.perceptrons = perceptrons
10
- self.deg = deg
10
+ self.step = step
11
11
 
12
- if not self.deg is None:
12
+ if not self.step is None:
13
13
  for perceptron in self.perceptrons:
14
- if perceptron.deg is None:
15
- perceptron.deg = self.deg
14
+ if perceptron.step is None:
15
+ perceptron.step = self.step
16
16
 
17
- def connect(self, layer: Self):
17
+ def connect(self, layer: Self) -> None:
18
18
  for p1 in self.perceptrons:
19
19
  for p2 in layer.perceptrons:
20
20
  p1.connectRHS(p2)
@@ -0,0 +1,46 @@
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_layer = layers[0]
10
+ self.output_layer = 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, X_train: List[float], y_train: List[float]) -> None:
18
+ if len(self.input_layer.perceptrons) != len(X_train):
19
+ raise Exception(
20
+ f"The length of the training values, {len(X_train)}, is not equal to the length of input perceptrons: {len(self.input_layer.perceptrons)}"
21
+ )
22
+
23
+ if len(self.output_layer.perceptrons) != len(y_train):
24
+ raise Exception(
25
+ f"The length of the training values, {len(y_train)}, is not equal to the length of output perceptrons: {len(self.output_layer.perceptrons)}"
26
+ )
27
+
28
+ for i in range(0, len(X_train)):
29
+ self.input_layer.perceptrons[i].activate(X_train[i])
30
+
31
+ for i in range(0, len(y_train)):
32
+ y_train = y_train[i]
33
+ perceptron = self.output_layer.perceptrons[i]
34
+ perceptron.propagate(perceptron.value - y_train, None)
35
+
36
+ def predict(self, inputs: List[float]) -> List[float]:
37
+
38
+ if len(self.input_layer.perceptrons) != len(inputs):
39
+ raise Exception(
40
+ f"The length of the training values, {len(inputs)}, is not equal to the length of input perceptrons: {len(self.input.perceptrons)}"
41
+ )
42
+
43
+ for i in range(0, len(inputs)):
44
+ self.input_layer.perceptrons[i].activate(inputs[i])
45
+
46
+ return [perceptron.value for perceptron in self.output_layer.perceptrons]
@@ -0,0 +1,93 @@
1
+ import math
2
+ import statistics
3
+ from typing import Dict, List, Self
4
+ from scipy.stats import linregress
5
+
6
+
7
+ class Perceptron:
8
+
9
+ def __init__(self, m: float, b: float = 0, step: float = None, name=None):
10
+
11
+ self.m = m
12
+ self.b = b
13
+ self.name = name
14
+ self.step = step
15
+
16
+ self.value = 0
17
+ self.activation_count = 0
18
+
19
+ self.perceptronsRHS: List[Self] = []
20
+ self.perceptronsLHS: List[Self] = []
21
+
22
+ self.activation: Dict[Self, float] = {}
23
+ self.propagation: Dict[Self, float] = {}
24
+
25
+ def connectRHS(self, perceptronRHS: Self) -> None:
26
+ if perceptronRHS not in self.perceptronsRHS:
27
+ self.perceptronsRHS.append(perceptronRHS)
28
+
29
+ if self not in perceptronRHS.perceptronsLHS:
30
+ perceptronRHS.connectLHS(self)
31
+
32
+ def connectLHS(self, perceptronLHS: Self) -> None:
33
+ if perceptronLHS not in self.perceptronsLHS:
34
+ self.perceptronsLHS.append(perceptronLHS)
35
+
36
+ if self not in perceptronLHS.perceptronsRHS:
37
+ perceptronLHS.connectRHS(self)
38
+
39
+ def disconnectRHS(self, perceptronRHS: Self) -> None:
40
+ if perceptronRHS in self.perceptronsRHS:
41
+ self.perceptronsRHS.remove(perceptronRHS)
42
+
43
+ if self in perceptronRHS.perceptronsLHS:
44
+ perceptronRHS.disconnectLHS(self)
45
+
46
+ if len(self.perceptronsRHS) == 0:
47
+ for perceptron in self.perceptronsLHS:
48
+ perceptron.disconnectRHS(self)
49
+
50
+ def disconnectLHS(self, perceptronLHS: Self) -> None:
51
+ if perceptronLHS in self.perceptronsLHS:
52
+ self.perceptronsLHS.remove(perceptronLHS)
53
+
54
+ if self in perceptronLHS.perceptronsRHS:
55
+ perceptronLHS.disconnectRHS(self)
56
+
57
+ if len(self.perceptronsLHS) == 0:
58
+ for perceptron in self.perceptronsRHS:
59
+ perceptron.disconnectLHS(self)
60
+
61
+ def activate(self, t: float, p: Self = None) -> None:
62
+
63
+ if self.activation_count == 0:
64
+ self.activation = {}
65
+
66
+ self.activation.update({p: self.m * t})
67
+ self.activation_count = self.activation_count + 1
68
+
69
+ if len(self.perceptronsLHS) == 0 or self.activation_count == len(self.perceptronsLHS):
70
+ self.value = sum(self.activation.values())
71
+ for perceptron in self.perceptronsRHS:
72
+ perceptron.activate(self.value, self)
73
+ self.activation_count = 0
74
+
75
+ def propagate(self, error: float, p: Self = None) -> None:
76
+
77
+ self.propagation.update({p: error})
78
+
79
+ if len(self.perceptronsRHS) == 0 or len(self.propagation) == len(self.perceptronsRHS):
80
+
81
+ error_total = sum(self.propagation.values())
82
+ for error in self.propagation.values():
83
+ self.m = self.m - (error * self.step)
84
+
85
+ for p in self.perceptronsLHS:
86
+ p_activation_value = self.activation[p]
87
+
88
+ if p_activation_value > 0 and error_total > 0 or p_activation_value < 0 and error_total < 0:
89
+ p.propagate(error_total, self)
90
+ else:
91
+ p.propagate(math.copysign(1, error_total), self)
92
+
93
+ self.propagation = {}
File without changes
@@ -0,0 +1,65 @@
1
+ import unittest
2
+ import json
3
+ from random import random, randint
4
+ from sklearn.metrics import r2_score
5
+ from neuralplex import Network, Layer, Perceptron
6
+
7
+ class Test(unittest.TestCase):
8
+
9
+ def test_nibbles(self):
10
+
11
+ ITERATION = int(1e5 / 2)
12
+ STEP = 1e-4
13
+
14
+ l1 = Layer(perceptrons=[Perceptron(m=random()) for i in range(0, 4)], step=STEP)
15
+
16
+ l2 = Layer(perceptrons=[Perceptron(m=random()) for i in range(0, 8)], step=STEP)
17
+
18
+ l3 = Layer(perceptrons=[Perceptron(m=random(), name="out-0")], step=STEP)
19
+
20
+ n1 = Network(
21
+ [
22
+ l1,
23
+ l2,
24
+ l3,
25
+ ]
26
+ )
27
+
28
+ print("Training the model.")
29
+ for i in range(0, ITERATION):
30
+
31
+ if i % 100000 == 0:
32
+ print(f"Training iteration: {i}")
33
+
34
+ rn = randint(1, 15)
35
+
36
+ b = [int(n) for n in bin(rn)[2:]]
37
+
38
+ while len(b) < 4:
39
+ b = [0] + b
40
+
41
+ n1.train(b, [rn])
42
+
43
+
44
+ ys = []
45
+ ys_p = []
46
+ for i in range(1, 16):
47
+
48
+ b = [int(n) for n in bin(i)[2:]]
49
+
50
+ while len(b) < 4:
51
+ b = [0] + b
52
+
53
+ pn = n1.predict(b)
54
+
55
+ ys.append(i)
56
+ ys_p.append(pn[0])
57
+
58
+ print(f"{i} input: {json.dumps(b)}, truth: {i} prediction: {json.dumps(pn)}")
59
+
60
+ R2 = r2_score(ys, ys_p)
61
+
62
+ print(f"R2: {R2}")
63
+
64
+ if __name__ == '__main__':
65
+ unittest.main()
@@ -1,3 +0,0 @@
1
- # Neural-pleX
2
-
3
- An object oriented neural network implementation.
@@ -1,43 +0,0 @@
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]
@@ -1,77 +0,0 @@
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 = {}
@@ -1,73 +0,0 @@
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
File without changes