File size: 4,800 Bytes
9cecb44
 
b7f5a9c
 
9cecb44
 
 
 
 
 
b7f5a9c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9cecb44
b7f5a9c
 
 
 
 
 
 
 
 
 
 
 
9cecb44
 
b7f5a9c
 
 
 
 
 
 
 
 
 
 
 
9cecb44
b7f5a9c
 
 
 
 
 
 
 
 
9cecb44
b7f5a9c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9cecb44
 
 
 
b7f5a9c
 
9cecb44
b7f5a9c
 
 
 
 
 
 
 
 
 
9cecb44
 
b7f5a9c
9cecb44
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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()