SimpleNN / nn.py
ricardo-lsantos's picture
Fixed minor bugs. Fixed the Ui parameters to be more easy to train.
b7f5a9c
raw
history blame
No virus
4.8 kB
import random
import json
from typing import Any
from utils import sigmoid, sigmoid_prime
EPOCHS = 1000000
ALPHAS = 20
WEPOCHS = EPOCHS // 100
VARIANCE_W = 0.5
VARIANCE_B = 1
class NeuralNetwork:
def __init__(self):
self._w11 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._w21 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._b1 = VARIANCE_B
self._w12 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._w22 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._b2 = VARIANCE_B
self._w13 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._w23 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._b3 = VARIANCE_B
self._o1 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._o2 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._o3 = random.uniform(-VARIANCE_W,VARIANCE_W)
self._ob = VARIANCE_B
def predict(self, i1, i2, activation=sigmoid):
s1 = self._w11 * i1 + self._w21 * i2 + self._b1
s1 = activation(s1)
s2 = self._w12 * i1 + self._w22 * i2 + self._b2
s2 = activation(s2)
s3 = self._w13 * i1 + self._w23 * i2 + self._b3
s3 = activation(s3)
output = s1 * self._o1 + s2 * self._o2 + s3 * self._o3 + self._ob
output = activation(output)
return output
def learn(self, i1, i2, target, activation=sigmoid, activation_prime=sigmoid_prime, alpha=0.2):
s1 = self._w11 * i1 + self._w21 * i2 + self._b1
s1 = activation(s1)
s2 = self._w12 * i1 + self._w22 * i2 + self._b2
s2 = activation(s2)
s3 = self._w13 * i1 + self._w23 * i2 + self._b3
s3 = activation(s3)
output = s1 * self._o1 + s2 * self._o2 + s3 * self._o3 + self._ob
output = activation(output)
error = target - output
derror = error * activation_prime(output)
ds1 = derror * self._o1 * activation_prime(s1)
ds2 = derror * self._o2 * activation_prime(s2)
ds3 = derror * self._o3 * activation_prime(s3)
self._o1 += alpha * s1 * derror
self._o2 += alpha * s2 * derror
self._o3 += alpha * s3 * derror
self._ob += alpha * derror
self._w11 += alpha * i1 * ds1
self._w21 += alpha * i2 * ds1
self._b1 += alpha * ds1
self._w12 += alpha * i1 * ds2
self._w22 += alpha * i2 * ds2
self._b2 += alpha * ds2
self._w13 += alpha * i1 * ds3
self._w23 += alpha * i2 * ds3
self._b3 += alpha * ds3
def train(self, inputs=[], outputs=[], epochs=EPOCHS, alpha=ALPHAS):
if len(inputs) > 0 and len(outputs) > 0:
for epoch in range(1,epochs+1):
indexes = [0,1,2,3]
random.shuffle(indexes)
for j in indexes:
self.learn(inputs[j][0],inputs[j][1],outputs[j][0], activation=sigmoid, activation_prime=sigmoid_prime, alpha=alpha)
# Print cost every 100 epochs for debug
if epoch%WEPOCHS == 0:
cost = 0
for j in range(4):
o = self.predict(inputs[j][0],inputs[j][1], activation=sigmoid)
cost += (outputs[j][0] - o) ** 2
cost /= 4
print("epoch", epoch, "mean squared error:", cost)
def save_model(self, filename):
model = self.getModelJson()
with open(filename, 'w') as json_file:
json.dump(model, json_file)
def getModelJson(self):
return {
"w11": self._w11,
"w21": self._w21,
"b1": self._b1,
"w12": self._w12,
"w22": self._w22,
"b2": self._b2,
"w13": self._w13,
"w23": self._w23,
"b3": self._b3,
"o1": self._o1,
"o2": self._o2,
"o3": self._o3,
"ob": self._ob
}
def __str__(self):
return self.getModelJson()
## Main
def main():
INPUTS = [[0,0],[0,1],[1,0],[1,1]]
OUTPUTS = [[0],[1],[1],[0]]
# Train model
nn = NeuralNetwork()
print("Neural Network created")
nn.train(inputs=INPUTS, outputs=OUTPUTS, epochs=EPOCHS, alpha=ALPHAS)
print("Model trained")
print("Printing Model:")
print(nn._getModelJson())
# Save model to files
nn.save_model("model.json")
print("Model saved to model.json")
for i in range(4):
result = nn.predict(INPUTS[i][0],INPUTS[i][1], activation=sigmoid)
print("for input", INPUTS[i], "expected", OUTPUTS[i][0], "predicted", f"{result:4.4}", "which is", "correct" if round(result)==OUTPUTS[i][0] else "incorrect")
if __name__ == "__main__":
main()