Skip to content

Commit ec2111a

Browse files
dmeoliantmarakis
authored andcommitted
removed unnecessary imports and substituted clip function with np.clip (#1146)
1 parent 22dd82c commit ec2111a

7 files changed

+82
-110
lines changed

deep_learning4e.py

+36-34
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
from keras.preprocessing import sequence
1010

1111
from utils4e import (Sigmoid, dot_product, softmax1D, conv1D, gaussian_kernel, element_wise_product, vector_add,
12-
random_weights, scalar_vector_product, matrix_multiplication, map_vector, mse_loss)
12+
random_weights, scalar_vector_product, matrix_multiplication, map_vector, mean_squared_error_loss)
1313

1414

1515
class Node:
1616
"""
1717
A node in a computational graph contains the pointer to all its parents.
18-
:param val: value of current node.
19-
:param parents: a container of all parents of current node.
18+
:param val: value of current node
19+
:param parents: a container of all parents of current node
2020
"""
2121

2222
def __init__(self, val=None, parents=None):
@@ -55,40 +55,40 @@ def forward(self, inputs):
5555
raise NotImplementedError
5656

5757

58-
class OutputLayer(Layer):
59-
"""1D softmax output layer in 19.3.2"""
58+
class InputLayer(Layer):
59+
"""1D input layer. Layer size is the same as input vector size."""
6060

6161
def __init__(self, size=3):
6262
super().__init__(size)
6363

6464
def forward(self, inputs):
65+
"""Take each value of the inputs to each unit in the layer."""
6566
assert len(self.nodes) == len(inputs)
66-
res = softmax1D(inputs)
67-
for node, val in zip(self.nodes, res):
68-
node.val = val
69-
return res
67+
for node, inp in zip(self.nodes, inputs):
68+
node.val = inp
69+
return inputs
7070

7171

72-
class InputLayer(Layer):
73-
"""1D input layer. Layer size is the same as input vector size."""
72+
class OutputLayer(Layer):
73+
"""1D softmax output layer in 19.3.2."""
7474

7575
def __init__(self, size=3):
7676
super().__init__(size)
7777

7878
def forward(self, inputs):
79-
"""Take each value of the inputs to each unit in the layer."""
8079
assert len(self.nodes) == len(inputs)
81-
for node, inp in zip(self.nodes, inputs):
82-
node.val = inp
83-
return inputs
80+
res = softmax1D(inputs)
81+
for node, val in zip(self.nodes, res):
82+
node.val = val
83+
return res
8484

8585

8686
class DenseLayer(Layer):
8787
"""
8888
1D dense layer in a neural network.
89-
:param in_size: input vector size, int.
90-
:param out_size: output vector size, int.
91-
:param activation: activation function, Activation object.
89+
:param in_size: (int) input vector size
90+
:param out_size: (int) output vector size
91+
:param activation: (Activation object) activation function
9292
"""
9393

9494
def __init__(self, in_size=3, out_size=3, activation=None):
@@ -124,7 +124,7 @@ def __init__(self, size=3, kernel_size=3):
124124
node.weights = gaussian_kernel(kernel_size)
125125

126126
def forward(self, features):
127-
# each node in layer takes a channel in the features.
127+
# each node in layer takes a channel in the features
128128
assert len(self.nodes) == len(features)
129129
res = []
130130
# compute the convolution output of each channel, store it in node.val
@@ -154,7 +154,8 @@ def forward(self, features):
154154
for i in range(len(self.nodes)):
155155
feature = features[i]
156156
# get the max value in a kernel_size * kernel_size area
157-
out = [max(feature[i:i + self.kernel_size]) for i in range(len(feature) - self.kernel_size + 1)]
157+
out = [max(feature[i:i + self.kernel_size])
158+
for i in range(len(feature) - self.kernel_size + 1)]
158159
res.append(out)
159160
self.nodes[i].val = out
160161
return res
@@ -270,13 +271,13 @@ def adam(dataset, net, loss, epochs=1000, rho=(0.9, 0.999), delta=1 / 10 ** 8,
270271

271272
def BackPropagation(inputs, targets, theta, net, loss):
272273
"""
273-
The back-propagation algorithm for multilayer networks in only one epoch, to calculate gradients of theta
274-
:param inputs: a batch of inputs in an array. Each input is an iterable object.
275-
:param targets: a batch of targets in an array. Each target is an iterable object.
276-
:param theta: parameters to be updated.
277-
:param net: a list of predefined layer objects representing their linear sequence.
278-
:param loss: a predefined loss function taking array of inputs and targets.
279-
:return: gradients of theta, loss of the input batch.
274+
The back-propagation algorithm for multilayer networks in only one epoch, to calculate gradients of theta.
275+
:param inputs: a batch of inputs in an array. Each input is an iterable object
276+
:param targets: a batch of targets in an array. Each target is an iterable object
277+
:param theta: parameters to be updated
278+
:param net: a list of predefined layer objects representing their linear sequence
279+
:param loss: a predefined loss function taking array of inputs and targets
280+
:return: gradients of theta, loss of the input batch
280281
"""
281282

282283
assert len(inputs) == len(targets)
@@ -325,9 +326,9 @@ def BackPropagation(inputs, targets, theta, net, loss):
325326
class BatchNormalizationLayer(Layer):
326327
"""Batch normalization layer."""
327328

328-
def __init__(self, size, epsilon=0.001):
329+
def __init__(self, size, eps=0.001):
329330
super().__init__(size)
330-
self.epsilon = epsilon
331+
self.eps = eps
331332
# self.weights = [beta, gamma]
332333
self.weights = [0, 0]
333334
self.inputs = None
@@ -341,7 +342,7 @@ def forward(self, inputs):
341342
res = []
342343
# get normalized value of each input
343344
for i in range(len(self.nodes)):
344-
val = [(inputs[i] - mu) * self.weights[0] / np.sqrt(self.epsilon + stderr ** 2) + self.weights[1]]
345+
val = [(inputs[i] - mu) * self.weights[0] / np.sqrt(self.eps + stderr ** 2) + self.weights[1]]
345346
res.append(val)
346347
self.nodes[i].val = val
347348
return res
@@ -375,7 +376,7 @@ def NeuralNetLearner(dataset, hidden_layer_sizes=None, learning_rate=0.01, epoch
375376
raw_net.append(DenseLayer(hidden_input_size, output_size))
376377

377378
# update parameters of the network
378-
learned_net = optimizer(dataset, raw_net, mse_loss, epochs, l_rate=learning_rate,
379+
learned_net = optimizer(dataset, raw_net, mean_squared_error_loss, epochs, l_rate=learning_rate,
379380
batch_size=batch_size, verbose=verbose)
380381

381382
def predict(example):
@@ -394,7 +395,7 @@ def predict(example):
394395
return predict
395396

396397

397-
def PerceptronLearner(dataset, learning_rate=0.01, epochs=100, verbose=None):
398+
def PerceptronLearner(dataset, learning_rate=0.01, epochs=100, optimizer=gradient_descent, batch_size=1, verbose=None):
398399
"""
399400
Simple perceptron neural network.
400401
"""
@@ -405,7 +406,8 @@ def PerceptronLearner(dataset, learning_rate=0.01, epochs=100, verbose=None):
405406
raw_net = [InputLayer(input_size), DenseLayer(input_size, output_size)]
406407

407408
# update the network
408-
learned_net = gradient_descent(dataset, raw_net, mse_loss, epochs, l_rate=learning_rate, verbose=verbose)
409+
learned_net = optimizer(dataset, raw_net, mean_squared_error_loss, epochs, l_rate=learning_rate,
410+
batch_size=batch_size, verbose=verbose)
409411

410412
def predict(example):
411413
layer_out = learned_net[1].forward(example)
@@ -419,7 +421,7 @@ def SimpleRNNLearner(train_data, val_data, epochs=2):
419421
RNN example for text sentimental analysis.
420422
:param train_data: a tuple of (training data, targets)
421423
Training data: ndarray taking training examples, while each example is coded by embedding
422-
Targets: ndarray taking targets of each example. Each target is mapped to an integer.
424+
Targets: ndarray taking targets of each example. Each target is mapped to an integer
423425
:param val_data: a tuple of (validation data, targets)
424426
:param epochs: number of epochs
425427
:return: a keras model

learning.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ def ada_boost(dataset, L, K):
968968
h.append(h_k)
969969
error = sum(weight for example, weight in zip(examples, w) if example[target] != h_k(example))
970970
# avoid divide-by-0 from either 0% or 100% error rates
971-
error = clip(error, eps, 1 - eps)
971+
error = np.clip(error, eps, 1 - eps)
972972
for j, example in enumerate(examples):
973973
if example[target] == h_k(example):
974974
w[j] *= error / (1 - error)

learning4e.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ def ada_boost(dataset, L, K):
742742
h.append(h_k)
743743
error = sum(weight for example, weight in zip(examples, w) if example[target] != h_k(example))
744744
# avoid divide-by-0 from either 0% or 100% error rates
745-
error = clip(error, eps, 1 - eps)
745+
error = np.clip(error, eps, 1 - eps)
746746
for j, example in enumerate(examples):
747747
if example[target] == h_k(example):
748748
w[j] *= error / (1 - error)

tests/test_deep_learning4e.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ def test_neural_net():
1111
iris = DataSet(name='iris')
1212
classes = ['setosa', 'versicolor', 'virginica']
1313
iris.classes_to_numbers(classes)
14-
nnl_adam = NeuralNetLearner(iris, [4], learning_rate=0.001, epochs=200, optimizer=adam)
1514
nnl_gd = NeuralNetLearner(iris, [4], learning_rate=0.15, epochs=100, optimizer=gradient_descent)
15+
nnl_adam = NeuralNetLearner(iris, [4], learning_rate=0.001, epochs=200, optimizer=adam)
1616
tests = [([5.0, 3.1, 0.9, 0.1], 0),
1717
([5.1, 3.5, 1.0, 0.0], 0),
1818
([4.9, 3.3, 1.1, 0.1], 0),
@@ -22,25 +22,28 @@ def test_neural_net():
2222
([7.5, 4.1, 6.2, 2.3], 2),
2323
([7.3, 4.0, 6.1, 2.4], 2),
2424
([7.0, 3.3, 6.1, 2.5], 2)]
25-
assert grade_learner(nnl_adam, tests) >= 1 / 3
2625
assert grade_learner(nnl_gd, tests) >= 1 / 3
27-
assert err_ratio(nnl_adam, iris) < 0.21
2826
assert err_ratio(nnl_gd, iris) < 0.21
27+
assert grade_learner(nnl_adam, tests) >= 1 / 3
28+
assert err_ratio(nnl_adam, iris) < 0.21
2929

3030

3131
def test_perceptron():
3232
iris = DataSet(name='iris')
3333
classes = ['setosa', 'versicolor', 'virginica']
3434
iris.classes_to_numbers(classes)
35-
pl = PerceptronLearner(iris, learning_rate=0.01, epochs=100)
35+
pl_gd = PerceptronLearner(iris, learning_rate=0.01, epochs=100, optimizer=gradient_descent)
36+
pl_adam = PerceptronLearner(iris, learning_rate=0.01, epochs=100, optimizer=adam)
3637
tests = [([5, 3, 1, 0.1], 0),
3738
([5, 3.5, 1, 0], 0),
3839
([6, 3, 4, 1.1], 1),
3940
([6, 2, 3.5, 1], 1),
4041
([7.5, 4, 6, 2], 2),
4142
([7, 3, 6, 2.5], 2)]
42-
assert grade_learner(pl, tests) > 1 / 2
43-
assert err_ratio(pl, iris) < 0.4
43+
assert grade_learner(pl_gd, tests) > 1 / 2
44+
assert err_ratio(pl_gd, iris) < 0.4
45+
assert grade_learner(pl_adam, tests) > 1 / 2
46+
assert err_ratio(pl_adam, iris) < 0.4
4447

4548

4649
def test_rnn():

tests/test_utils.py

-8
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,6 @@ def test_normalize():
173173
assert normalize([1, 2, 1]) == [0.25, 0.5, 0.25]
174174

175175

176-
def test_clip():
177-
assert [clip(x, 0, 1) for x in [-1, 0.5, 10]] == [0, 0.5, 1]
178-
179-
180176
def test_gaussian():
181177
assert gaussian(1, 0.5, 0.7) == 0.6664492057835993
182178
assert gaussian(5, 2, 4.5) == 0.19333405840142462
@@ -201,10 +197,6 @@ def test_distance_squared():
201197
assert distance_squared((1, 2), (5, 5)) == 25.0
202198

203199

204-
def test_vector_clip():
205-
assert vector_clip((-1, 10), (0, 0), (9, 9)) == (0, 9)
206-
207-
208200
def test_turn_heading():
209201
assert turn_heading((0, 1), 1) == (-1, 0)
210202
assert turn_heading((0, 1), -1) == (1, 0)

utils.py

+18-27
Original file line numberDiff line numberDiff line change
@@ -233,34 +233,38 @@ def euclidean_distance(x, y):
233233
return np.sqrt(sum((_x - _y) ** 2 for _x, _y in zip(x, y)))
234234

235235

236+
def manhattan_distance(x, y):
237+
return sum(abs(_x - _y) for _x, _y in zip(x, y))
238+
239+
240+
def hamming_distance(x, y):
241+
return sum(_x != _y for _x, _y in zip(x, y))
242+
243+
236244
def cross_entropy_loss(x, y):
237-
return (-1.0 / len(x)) * sum(x * np.log(y) + (1 - x) * np.log(1 - y) for x, y in zip(x, y))
245+
return (-1.0 / len(x)) * sum(_x * np.log(_y) + (1 - _x) * np.log(1 - _y) for _x, _y in zip(x, y))
246+
247+
248+
def mean_squared_error_loss(x, y):
249+
return (1.0 / len(x)) * sum((_x - _y) ** 2 for _x, _y in zip(x, y))
238250

239251

240252
def rms_error(x, y):
241253
return np.sqrt(ms_error(x, y))
242254

243255

244256
def ms_error(x, y):
245-
return mean((x - y) ** 2 for x, y in zip(x, y))
257+
return mean((_x - _y) ** 2 for _x, _y in zip(x, y))
246258

247259

248260
def mean_error(x, y):
249-
return mean(abs(x - y) for x, y in zip(x, y))
250-
251-
252-
def manhattan_distance(x, y):
253-
return sum(abs(_x - _y) for _x, _y in zip(x, y))
261+
return mean(abs(_x - _y) for _x, _y in zip(x, y))
254262

255263

256264
def mean_boolean_error(x, y):
257265
return mean(_x != _y for _x, _y in zip(x, y))
258266

259267

260-
def hamming_distance(x, y):
261-
return sum(_x != _y for _x, _y in zip(x, y))
262-
263-
264268
def normalize(dist):
265269
"""Multiply each number by a constant such that the sum is 1.0"""
266270
if isinstance(dist, dict):
@@ -277,20 +281,15 @@ def random_weights(min_value, max_value, num_weights):
277281
return [random.uniform(min_value, max_value) for _ in range(num_weights)]
278282

279283

280-
def clip(x, lowest, highest):
281-
"""Return x clipped to the range [lowest..highest]."""
282-
return max(lowest, min(x, highest))
284+
def sigmoid(x):
285+
"""Return activation value of x with sigmoid function."""
286+
return 1 / (1 + np.exp(-x))
283287

284288

285289
def sigmoid_derivative(value):
286290
return value * (1 - value)
287291

288292

289-
def sigmoid(x):
290-
"""Return activation value of x with sigmoid function."""
291-
return 1 / (1 + np.exp(-x))
292-
293-
294293
def elu(x, alpha=0.01):
295294
return x if x > 0 else alpha * (np.exp(x) - 1)
296295

@@ -389,13 +388,6 @@ def distance_squared(a, b):
389388
return (xA - xB) ** 2 + (yA - yB) ** 2
390389

391390

392-
def vector_clip(vector, lowest, highest):
393-
"""Return vector, except if any element is less than the corresponding
394-
value of lowest or more than the corresponding value of highest, clip to
395-
those values."""
396-
return type(vector)(map(clip, vector, lowest, highest))
397-
398-
399391
# ______________________________________________________________________________
400392
# Misc Functions
401393

@@ -484,7 +476,6 @@ def failure_test(algorithm, tests):
484476
to check for correctness. On the other hand, a lot of algorithms output something
485477
particular on fail (for example, False, or None).
486478
tests is a list with each element in the form: (values, failure_output)."""
487-
from statistics import mean
488479
return mean(int(algorithm(x) != y) for x, y in tests)
489480

490481

0 commit comments

Comments
 (0)