1 | import time |
2 | import h5py |
3 | import numpy as np |
4 |
|
5 |
|
6 |
|
7 | def load_data(): |
8 | train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r") |
9 | train_set_x_orig = np.array(train_dataset["train_set_x"][:]) |
10 | train_set_y_orig = np.array(train_dataset["train_set_y"][:]) |
11 | test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r") |
12 | test_set_x_orig = np.array(test_dataset["test_set_x"][:]) |
13 | test_set_y_orig = np.array(test_dataset["test_set_y"][:]) |
14 | classes = np.array(test_dataset["list_classes"][:]) |
15 | train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0])) |
16 | test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0])) |
17 | return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes |
18 |
|
19 |
|
20 |
|
21 | def sigmoid(z): |
22 | return 1. / (1.+np.exp(-z)) |
23 |
|
24 |
|
25 |
|
26 | def relu(Z): |
27 | A = np.maximum(0,Z) |
28 | return A |
29 |
|
30 |
|
31 |
|
32 | def leaky_relu(Z): |
33 | A = np.maximum(0,Z) |
34 | A[Z < 0] = 0.01 * Z |
35 | return A |
36 |
|
37 |
|
38 |
|
39 | class DeepNeuralNetwork(): |
40 | def __init__(self, layers_dim, activations): |
41 | np.random.seed(1) |
42 | self.layers_dim = layers_dim |
43 | self.__num_layers = len(layers_dim) |
44 | self.activations = activations |
45 | self.input_size = layers_dim[0] |
46 | self.parameters = self.__parameters_initializer(layers_dim) |
47 | self.output_size = layers_dim[-1] |
48 |
|
49 | |
50 | def __parameters_initializer(self, layers_dim): |
51 | L = len(layers_dim) |
52 | parameters = {} |
53 | for l in range(1, L): |
54 | parameters['W'+str(l)] = np.random.randn(layers_dim[l], layers_dim[l-1]) / np.sqrt(layers_dim[l-1]) |
55 | parameters['b'+str(l)] = np.zeros((layers_dim[l], 1)) |
56 | return parameters |
57 |
|
58 | |
59 | def __one_layer_forward(self, A_prev, W, b, activation): |
60 | Z = np.dot(W, A_prev) + b |
61 | if activation == 'sigmoid': |
62 | A = sigmoid(Z) |
63 | if activation == 'relu': |
64 | A = relu(Z) |
65 | if activation == 'leaky_relu': |
66 | A = leaky_relu(Z) |
67 | if activation == 'tanh': |
68 | A = np.tanh(Z) |
69 | cache = {'Z': Z, 'A': A} |
70 | return A, cache |
71 |
|
72 | |
73 | def __forward_propagation(self, X): |
74 | caches = [] |
75 | A_prev = X |
76 | caches.append({'A': A_prev}) |
77 | for l in range(1, len(self.layers_dim)): |
78 | W, b = self.parameters['W'+str(l)], self.parameters['b'+str(l)] |
79 | A_prev, cache = self.__one_layer_forward(A_prev, W, b, self.activations[l-1]) |
80 | caches.append(cache) |
81 | AL = caches[-1]['A'] |
82 | return AL, caches |
83 |
|
84 | |
85 | def __compute_cost(self, AL, Y): |
86 | m = Y.shape[1] |
87 | cost = -np.sum(Y*np.log(AL) + (1-Y)*np.log(1-AL)) / m |
88 | return cost |
89 |
|
90 | |
91 | def cost_function(self, X, Y): |
92 | assert (self.input_size == X.shape[0]) |
93 | AL, _ = self.__forward_propagation(X) |
94 | return self.__compute_cost(AL, Y) |
95 |
|
96 | |
97 | def sigmoid_backward(self, dA, Z): |
98 | s = sigmoid(Z) |
99 | dZ = dA * s*(1-s) |
100 | return dZ |
101 |
|
102 | |
103 | def relu_backward(self, dA, Z): |
104 | dZ = np.array(dA, copy=True) |
105 | dZ[Z <= 0] = 0 |
106 | return dZ |
107 |
|
108 | |
109 | def leaky_relu_backward(self, dA, Z): |
110 | dZ = np.array(dA, copy=True) |
111 | dZ[Z <= 0] = 0.01 |
112 | return dZ |
113 |
|
114 | |
115 | def tanh_backward(self, dA, Z): |
116 | s = np.tanh(Z) |
117 | dZ = 1 - s*s |
118 | return dZ |
119 |
|
120 | |
121 | def __linear_backward(self, dZ, A_prev, W): |
122 | m = A_prev.shape[1] |
123 | dW = np.dot(dZ, A_prev.T) / m |
124 | db = np.sum(dZ, axis=1, keepdims=True) / m |
125 | dA_prev = np.dot(W.T, dZ) |
126 | return dA_prev, dW, db |
127 |
|
128 | |
129 | def __activation_backward(self, dA, Z, activation): |
130 | assert (dA.shape == Z.shape) |
131 | if activation == 'sigmoid': |
132 | dZ = self.sigmoid_backward(dA, Z) |
133 | if activation == 'relu': |
134 | dZ = self.relu_backward(dA, Z) |
135 | if activation == 'leaky_relu': |
136 | dZ = self.leaky_relu_backward(dA, Z) |
137 | if activation == 'tanh': |
138 | dZ = self.tanh_backward(dA, Z) |
139 | return dZ |
140 |
|
141 | |
142 | def __backward_propagation(self, caches, Y): |
143 | m = Y.shape[1] |
144 | L = self.__num_layers |
145 | grads = {} |
146 | AL, A_prev = caches[L-1]['A'], caches[L-2]['A'] |
147 | grads['dZ'+str(L-1)] = AL - Y |
148 | grads['dA'+str(L-2)], grads['dW'+str(L-1)], grads['db'+str(L-1)] = self.__linear_backward(grads['dZ'+str(L-1)], A_prev, self.parameters['W'+str(L-1)]) |
149 | for l in reversed(range(1, L-1)): |
150 | grads['dZ'+str(l)] = self.__activation_backward(grads['dA'+str(l)], caches[l]['Z'], self.activations[l-1]) |
151 | A_prev = caches[l-1]['A'] |
152 | grads['dA'+str(l-1)], grads['dW'+str(l)], grads['db'+str(l)] = self.__linear_backward(grads['dZ'+str(l)], A_prev, self.parameters['W'+str(l)]) |
153 | return grads |
154 |
|
155 | |
156 | def __update_parameters(self, grads, learning_rate): |
157 | for l in range(1, self.__num_layers): |
158 | self.parameters['W'+str(l)] -= learning_rate * grads['dW'+str(l)] |
159 | self.parameters['b'+str(l)] -= learning_rate * grads['db'+str(l)] |
160 |
|
161 | |
162 | def fit(self, X, Y, num_iterations, learning_rate, print_cost=False, print_num=100): |
163 | for i in range(num_iterations): |
164 | AL, caches = self.__forward_propagation(X) |
165 | cost = self.__compute_cost(AL, Y) |
166 | grads = self.__backward_propagation(caches, Y) |
167 | self.__update_parameters(grads, learning_rate) |
168 | if i % print_num == 0 and print_cost: |
169 | print ("Cost after iteration %i: %f" %(i, cost)) |
170 | return self |
171 |
|
172 | |
173 | def predict_prob(self, X): |
174 | A, _ = self.__forward_propagation(X) |
175 | return A |
176 |
|
177 | |
178 | def predict(self, X, threshold=0.5): |
179 | pred_prob = self.predict_prob(X) |
180 | threshold_func = np.vectorize(lambda x: 1 if x > threshold else 0) |
181 | Y_prediction = threshold_func(pred_prob) |
182 | return Y_prediction |
183 |
|
184 | |
185 | def accuracy_score(self, X, Y): |
186 | pred = self.predict(X) |
187 | return len(Y[pred == Y]) / Y.shape[1] |
188 |
|
189 |
|
190 |
|
191 | np.random.seed(1) |
192 | train_x_orig, train_y, test_x_orig, test_y, classes = load_data() |
193 | m_train = train_x_orig.shape[0] |
194 | num_px = train_x_orig.shape[1] |
195 | m_test = test_x_orig.shape[0] |
196 | print ("Number of training examples: " + str(m_train)) |
197 | print ("Number of testing examples: " + str(m_test)) |
198 | print ("Each image is of size: (" + str(num_px) + ", " + str(num_px) + ", 3)") |
199 | print ("train_x_orig shape: " + str(train_x_orig.shape)) |
200 | print ("train_y shape: " + str(train_y.shape)) |
201 | print ("test_x_orig shape: " + str(test_x_orig.shape)) |
202 | print ("test_y shape: " + str(test_y.shape)) |
203 |
|
204 |
|
205 | train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T |
206 | test_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1).T |
207 | train_x = train_x_flatten/255. |
208 | test_x = test_x_flatten/255. |
209 | print ("train_x's shape: " + str(train_x.shape)) |
210 | print ("test_x's shape: " + str(test_x.shape)) |
211 |
|
212 |
|
213 | layers_dims = (12288, 20, 7, 5, 1) |
214 | activations = ['relu', 'relu', 'relu','sigmoid'] |
215 | num_iter = 2500 |
216 | learning_rate = 0.0075 |
217 |
|
218 | clf = DeepNeuralNetwork(layers_dims, activations).fit(train_x, train_y, num_iter, learning_rate, True, 100) |
219 | print('train accuracy: {:.2f}%'.format(clf.accuracy_score(train_x, train_y)*100)) |
220 | print('test accuracy: {:.2f}%'.format(clf.accuracy_score(test_x, test_y)*100)) |