1
1
import numpy as np
2
+ from numba .experimental import jitclass
3
+ from numba import types , typed
2
4
import z_helper as h
3
5
import time
4
6
5
7
8
+ def make_neural_network (layer_sizes , layer_activations , learning_rate = 0.05 , low = - 2 , high = 2 ):
9
+
10
+ # Initialize typed layer sizes list.
11
+ typed_layer_sizes = typed .List ()
12
+ for size in layer_sizes :
13
+ typed_layer_sizes .append (size )
14
+ # print(typeof(typed_layer_sizes))
15
+
16
+ # Initialie typed layer activation method strings list.
17
+ typed_layer_activations = typed .List ()
18
+ for activation in layer_activations :
19
+ typed_layer_activations .append (activation )
20
+ # print(typeof(typed_layer_activations))
21
+
22
+ # Initialize weights between every neuron in all adjacent layers.
23
+ typed_weights = typed .List ()
24
+ for i in range (1 , len (layer_sizes )):
25
+ typed_weights .append (np .random .uniform (low , high , (layer_sizes [i - 1 ], layer_sizes [i ])))
26
+ # print(typeof(typed_weights))
27
+
28
+ # Initialize biases for every neuron in all layers
29
+ typed_biases = typed .List ()
30
+ for i in range (1 , len (layer_sizes )):
31
+ typed_biases .append (np .random .uniform (low , high , (layer_sizes [i ], 1 )))
32
+ # print(typeof(typed_biases))
33
+
34
+ # Initialize empty list of output of every neuron in all layers.
35
+ typed_layer_outputs = typed .List ()
36
+ for i in range (len (layer_sizes )):
37
+ typed_layer_outputs .append (np .zeros ((layer_sizes [i ], 1 )))
38
+ # print(typeof(typed_layer_outputs))
39
+
40
+ return NeuralNetwork (typed_layer_sizes , typed_layer_activations , typed_weights , typed_biases , typed_layer_outputs , learning_rate , low , high )
41
+
42
+
43
+ spec = [
44
+ ("layer_sizes" , types .ListType (types .int64 )),
45
+ ("layer_activations" , types .ListType (types .string )),
46
+ ("weights" , types .ListType (types .float64 [:, ::1 ])),
47
+ ("biases" , types .ListType (types .float64 [:, ::1 ])),
48
+ ("layer_outputs" , types .ListType (types .float64 [:, ::1 ])),
49
+ ("learning_rate" , types .float64 ),
50
+ ("low" , types .int64 ),
51
+ ("high" , types .int64 )
52
+ ]
53
+ @jitclass (spec )
6
54
class NeuralNetwork :
7
- def __init__ (self , layer_sizes , layer_activations , learning_rate = 0.1 , low = - 2 , high = 2 ):
55
+ def __init__ (self , layer_sizes , layer_activations , weights , biases , layer_outputs , learning_rate , low , high ):
8
56
assert len (layer_sizes ) >= 2
9
57
assert len (layer_sizes )- 1 == len (layer_activations )
10
58
11
- # Initialize weights between every neuron in all adjacent layers.
12
- self .weights = np .array ([np .random .uniform (low , high , (layer_sizes [i - 1 ], layer_sizes [i ])) for i in range (1 , len (layer_sizes ))])
13
- # Initialize biases for every neuron in all layers
14
-
15
- self .biases = np .array ([np .random .uniform (low , high , (layer_sizes [i ], 1 )) for i in range (1 , len (layer_sizes ))])
16
- # Initialize empty list of output of every neuron in all layers.
17
- self .layer_outputs = np .array ([np .zeros ((layer_sizes [i ], 1 )) for i in range (len (layer_sizes ))])
59
+ self .layer_sizes = layer_sizes
18
60
61
+ # Initialize list with activation functions per layer.
19
62
self .layer_activations = layer_activations
20
- self .layer_sizes = layer_sizes
63
+ self .weights = weights
64
+ self .biases = biases
65
+ self .layer_outputs = layer_outputs
66
+
21
67
self .learning_rate = learning_rate
22
68
23
69
def calculate_output (self , input_data ):
@@ -26,22 +72,24 @@ def calculate_output(self, input_data):
26
72
y = input_data
27
73
self .layer_outputs [0 ] = y
28
74
29
- for i in range (self .weights . shape [ 0 ] ):
30
- y = self . layer_activations [ i ] (np .dot (self .weights [i ].T , y ) + self .biases [i ], False )
75
+ for i in range (len ( self .weights ) ):
76
+ y = h . activation (np .dot (self .weights [i ].T , y ) + self .biases [ i ], self . layer_activations [i ], False )
31
77
self .layer_outputs [i + 1 ] = y
32
78
return y
33
79
34
- def train (self , input_data , desired_output_data ):
35
- assert input_data . shape [ 0 ] == self .layer_sizes [0 ]
36
- assert desired_output_data . shape [ 0 ] == self .layer_sizes [- 1 ]
80
+ def train_single (self , input_data , desired_output_data ):
81
+ assert len ( input_data ) == self .layer_sizes [0 ]
82
+ assert len ( desired_output_data ) == self .layer_sizes [- 1 ]
37
83
self .calculate_output (input_data )
38
84
39
- error = (desired_output_data - self .layer_outputs [- 1 ]) * self .layer_activations [- 1 ]( self .layer_outputs [- 1 ], True )
85
+ error = (desired_output_data - self .layer_outputs [- 1 ]) * h . activation ( self .layer_outputs [- 1 ], self .layer_activations [- 1 ], True )
40
86
self .weights [- 1 ] += (self .learning_rate * self .layer_outputs [- 2 ] * error .T )
41
87
self .biases [- 1 ] += self .learning_rate * error
42
88
43
- for i in reversed (range (self .weights .shape [0 ]- 1 )):
44
- error = np .dot (self .weights [i + 1 ], error ) * self .layer_activations [i ](self .layer_outputs [i + 1 ], True )
89
+ length_weights = len (self .weights )
90
+ for i in range (1 , length_weights ):
91
+ i = length_weights - i - 1
92
+ error = np .dot (self .weights [i + 1 ], error ) * h .activation (self .layer_outputs [i + 1 ], self .layer_activations [i ], True )
45
93
self .weights [i ] += (self .learning_rate * self .layer_outputs [i ] * error .T )
46
94
self .biases [i ] += self .learning_rate * error
47
95
@@ -50,51 +98,71 @@ def calculate_SSE(self, input_data, desired_output_data):
50
98
assert desired_output_data .shape [0 ] == self .layer_sizes [- 1 ]
51
99
return np .sum (np .power (desired_output_data - self .calculate_output (input_data ), 2 ))
52
100
53
- def calculate_MSE (self , input_data , output_data ):
54
- assert input_data .shape [0 ] == output_data .shape [0 ]
101
+ def calculate_MSE (self , input_data , desired_output_data ):
102
+ assert input_data .shape [0 ] == desired_output_data .shape [0 ]
55
103
size = input_data .shape [0 ]
56
104
sum_error = 0
57
105
for i in range (size ):
58
- sum_error += self .calculate_SSE (input_data [i ], output_data [i ])
106
+ sum_error += self .calculate_SSE (input_data [i ], desired_output_data [i ])
59
107
return sum_error / size
60
108
109
+ def train (self , test_input_data , test_desired_output_data , validate_input_data , validate_output_data ):
110
+ previous_mse = 1.0
111
+ current_mse = 0.0
112
+ epochs = 0
113
+ while (current_mse < previous_mse ):
114
+ epochs += 1
115
+ previous_mse = self .calculate_MSE (validate_input_data , validate_output_data )
116
+ for i in range (len (test_input_data )):
117
+ self .train_single (test_input_data [i ], test_desired_output_data [i ])
118
+ current_mse = self .calculate_MSE (validate_input_data , validate_output_data )
119
+ return epochs , current_mse
120
+
121
+ def evaluate (self , input_data , desired_output_data ):
122
+ corrects , wrongs = 0 , 0
123
+ for i in range (len (input_data )):
124
+ output = self .calculate_output (input_data [i ])
125
+ output_max = output .argmax ()
126
+ desired_output_max = desired_output_data [i ].argmax ()
127
+ if output_max == desired_output_max :
128
+ corrects += 1
129
+ else :
130
+ wrongs += 1
131
+ return corrects / (corrects + wrongs )
132
+
61
133
def print_weights_and_biases (self ):
62
134
print (self .weights )
63
135
print (self .biases )
64
136
65
137
66
138
np .set_printoptions (linewidth = 200 )
67
139
68
- data_input = h .import_from_csv ("data/features.txt" , float )
69
- data_output = h .import_from_csv ("data/targets.txt" , int )
70
- data_output = np .array ([h .class_to_array (np .amax (data_output ), x ) for x in data_output ])
140
+ data_input = np .load ("data/ci_inputs.npy" )
141
+ data_output = np .load ("data/ci_outputs.npy" )
71
142
72
- data_input = data_input .reshape ((len (data_input ), - 1 , 1 ))
73
- data_output = data_output .reshape ((len (data_input ), - 1 , 1 ))
143
+ print ("Begin compiling!" )
144
+ begin_time = time .time_ns ()
145
+ compile_nn = make_neural_network (layer_sizes = [data_input .shape [1 ], data_output .shape [1 ]], layer_activations = ["sigmoid" ])
146
+ compile_nn .train (data_input [:1 ], data_output [:1 ], data_input [1 : 2 ], data_output [1 : 2 ])
147
+ end_time = time .time_ns ()
148
+ print ("Compile time:" , (end_time - begin_time ) / 1e9 )
74
149
75
- for i in range (4 ):
76
- random_seed = 10
150
+ for i in range (10 ):
151
+
152
+ random_seed = np .random .randint (10 , 1010 )
77
153
np .random .seed (random_seed )
78
154
79
155
train_input , validate_input , test_input = h .kfold (4 , data_input , random_seed )
80
156
train_output , validate_output , test_output = h .kfold (4 , data_output , random_seed )
81
157
82
- nn = NeuralNetwork (layer_sizes = [10 , 15 , 7 ], layer_activations = [h .sigmoid , h .sigmoid ])
83
- # test_mse = nn.calculate_MSE(test_input, test_output)
84
- # print("TEST MSE:", test_mse)
158
+ nn = make_neural_network (layer_sizes = [train_input .shape [1 ], 20 , train_output .shape [1 ]], layer_activations = ["sigmoid" , "sigmoid" ])
85
159
86
- previous_mse = 1
87
- current_mse = 0
88
- epochs = 0
89
160
begin_time = time .time_ns ()
90
- while (current_mse < previous_mse ):
91
- epochs += 1
92
- previous_mse = nn .calculate_MSE (validate_input , validate_output )
93
- for i in range (len (train_input )):
94
- nn .train (train_input [i ], train_output [i ])
95
- current_mse = nn .calculate_MSE (validate_input , validate_output )
161
+ epochs , current_mse = nn .train (train_input , train_output , validate_input , validate_output )
96
162
end_time = time .time_ns ()
97
163
98
164
train_mse = nn .calculate_MSE (train_input , train_output )
99
165
test_mse = nn .calculate_MSE (test_input , test_output )
100
- print ("Seed:" , random_seed , "Epochs:" , epochs , "Time:" , (end_time - begin_time )/ 1e9 , "Tr:" , train_mse , "V:" , current_mse , "T:" , test_mse )
166
+
167
+ accuracy_test = nn .evaluate (test_input , test_output )
168
+ print ("Seed:" , random_seed , "Epochs:" , epochs , "Time:" , (end_time - begin_time )/ 1e9 , "Accuracy:" , accuracy_test , "Tr:" , train_mse , "V:" , current_mse , "T:" , test_mse )
0 commit comments