1
0
Fork 0

Split from monorepo

This commit is contained in:
Nicola Zangrandi 2024-02-08 09:55:43 +01:00
commit 4b12aa44f2
Signed by: wasp
GPG key ID: 43C1470D890F23ED
5 changed files with 305 additions and 0 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

104
.gitignore vendored Normal file
View file

@ -0,0 +1,104 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.idea/inspectionProfiles/Project_Default.xml
.idea/misc.xml
.idea/modules.xml
.idea/workspace.xml
.idea/NeuralNetwork.iml

84
Matrix.py Normal file
View file

@ -0,0 +1,84 @@
import random
class Matrix:
def __init__(self, rows, cols):
self.rows = rows
self.cols = cols
self.data = []
for i in range(0, rows):
self.data.append([0 for _ in range(0, cols)])
@staticmethod
def from_list(lst):
m = Matrix(len(lst), 1)
m.map(lambda x, i, j: lst[i])
return m
@staticmethod
def product(a, b):
"""Matrix product"""
if a.cols != b.rows:
return None
result = Matrix(a.rows, b.cols)
result.map(lambda x, i, j: sum([a.data[i][k] * b.data[k][j] for k in range(0, a.cols)]))
return result
@staticmethod
def transpose(m):
"""Transpose a matrix"""
result = Matrix(m.cols, m.rows)
result.map(lambda x, i, j: m.data[j][i])
return result
@staticmethod
def subtract(a, b):
result = Matrix(a.rows, a.cols)
result.map(lambda x, i, j: a.data[i][j] - b.data[i][j])
return result
@staticmethod
def clone(m):
result = Matrix(m.rows, m.cols)
result.map(lambda x, i, j: m.data[i][j])
return result
def map(self, fun):
"""Execute a function on every element of the list, use the return value as the new value of the element"""
for i in range(0, self.rows):
for j in range(0, self.cols):
self.data[i][j] = fun(self.data[i][j], i, j)
def randomize(self):
"""Fill the matrix with random integers"""
self.map(lambda x, i, j: random.randint(-1, 1))
def multiply(self, n):
"""Hadamard or scalar product"""
if type(n) is Matrix:
self.map(lambda x, i, j: x * n.data[i][j])
else:
self.map(lambda x, i, j: x * n)
def add(self, n):
"""Entrywise or scalar addition"""
if type(n) is Matrix:
self.map(lambda x, i, j: x + n.data[i][j])
else:
self.map(lambda x, i, j: x + n)
def print(self):
"""Pretty print the matrix"""
for row in self.data:
for elem in row:
print(elem, end='\t')
print()
def to_list(self):
"""Returns the internal matrix as a list"""
lst = []
self.map(lambda x, i, j: lst.append(x))
return lst

83
NeuralNetwork.py Normal file
View file

@ -0,0 +1,83 @@
import math
from Matrix import Matrix
def sigmoid(x):
"""The Sigmoid function"""
return 1 / (1 + math.exp(-x))
def dsigmoid(x):
"""The derivative of the Sigmoid function"""
return sigmoid(x) * (1 - sigmoid(x))
class NeuralNetwork:
def __init__(self, num_i, num_h, num_o):
self.learning_rate = 0.1
self.input_nodes = num_i
self.hidden_nodes = num_h
self.output_nodes = num_o
self.weights_ih = Matrix(self.hidden_nodes, self.input_nodes)
self.weights_ho = Matrix(self.output_nodes, self.hidden_nodes)
self.bias_h = Matrix(self.hidden_nodes, 1)
self.bias_o = Matrix(self.output_nodes, 1)
self.weights_ih.randomize()
self.weights_ho.randomize()
self.bias_h.randomize()
self.bias_o.randomize()
def feedforward(self, input_list):
"""Feedforward algorithm, basically the hidden layer"""
inputs = Matrix.from_list(input_list)
hidden = Matrix.product(self.weights_ih, inputs)
hidden.add(self.bias_h)
hidden.map(lambda x, i, j: sigmoid(x))
output = Matrix.product(self.weights_ho, hidden)
output.add(self.bias_o)
output.map(lambda x, i, j: sigmoid(x))
return output.to_list()
def train(self, input_list, answer):
"""Train the NN on a known input/answer combination"""
inputs = Matrix.from_list(input_list)
hidden = Matrix.product(self.weights_ih, inputs)
hidden.add(self.bias_h)
hidden.map(lambda x, i, j: sigmoid(x))
outputs = Matrix.product(self.weights_ho, hidden)
outputs.add(self.bias_o)
outputs.map(lambda x, i, j: sigmoid(x))
targets = Matrix.from_list(answer)
output_errors = Matrix.subtract(targets, outputs)
gradients = Matrix.clone(outputs)
gradients.map(lambda x, i, j: x * (1 - x))
gradients.multiply(output_errors)
gradients.multiply(self.learning_rate)
hidden_t = Matrix.transpose(hidden)
weight_ho_deltas = Matrix.product(gradients, hidden_t)
self.weights_ho.add(weight_ho_deltas)
self.bias_o.add(gradients)
who_t = Matrix.transpose(self.weights_ho)
hidden_errors = Matrix.product(who_t, output_errors)
hidden_gradient = Matrix.clone(hidden)
hidden_gradient.map(lambda x, i, j: x * (1 - x))
hidden_gradient.multiply(hidden_errors)
hidden_gradient.multiply(self.learning_rate)
inputs_t = Matrix.transpose(inputs)
weight_ih_deltas = Matrix.product(hidden_gradient, inputs_t)
self.weights_ih.add(weight_ih_deltas)
self.bias_h.add(hidden_gradient)

32
Perceptron.py Normal file
View file

@ -0,0 +1,32 @@
import random
class Perceptron:
def __init__(self, n):
self.weights = [random.randint(-1, 1) for _ in range(0, n)]
self.lr = 0.1
@staticmethod
def sign(output):
if output >= 0:
return 1
else:
return -1
def guess(self, inputs):
s = 0
for i, inp in enumerate(inputs):
s += inp * self.weights[i]
return Perceptron.sign(s)
def guessY(self, x):
w0 = self.weights[0]
w1 = self.weights[1]
w2 = self.weights[2]
return -(w2 / w1) - (w0 / w1) * x
def train(self, inputs, target):
error = target - self.guess(inputs)
for i, w in enumerate(self.weights):
self.weights[i] += error * inputs[i] * self.lr