Skip to content

Commit

Permalink
Max Pooling now prettier!
Browse files Browse the repository at this point in the history
  • Loading branch information
NEGU93 committed Jan 20, 2021
1 parent 27fa760 commit b1a7959
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 29 deletions.
2 changes: 1 addition & 1 deletion cvnn/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.0.0'
__version__ = '1.0.1'
15 changes: 5 additions & 10 deletions cvnn/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -945,17 +945,12 @@ def pool_function(self, inputs, ksize, strides, padding, data_format):
# The max is calculated with the absolute value. This will still work on real values.
abs_in = tf.math.abs(inputs)
output, argmax = tf.nn.max_pool_with_argmax(input=abs_in, ksize=ksize, strides=strides,
padding=padding, data_format=data_format)
padding=padding, data_format=data_format,
include_batch_in_index=True)
if inputs.shape[0] is None:
return output
# Flatten input and argmax to make them equivalent
flat_in = tf.reshape(inputs, [tf.shape(inputs)[0], tf.math.reduce_prod(tf.shape(inputs)[1:])])
flat_argmax = tf.reshape(argmax, [tf.shape(argmax)[0], tf.math.reduce_prod(tf.shape(argmax)[1:])])
# TODO: Using numpy in the next line seems quite inneficient, is there a better way?
# Get the max values using the indeces of argmax
res = [tf.convert_to_tensor(flat_in.numpy()[i][arg_ind]) for i, arg_ind in enumerate(flat_argmax.numpy())]
# for i, arg_ind in enumerate(flat_argmax.numpy()):
tf_res = tf.reshape(res, output.shape)
shape = output.shape
tf_res = tf.reshape(tf.gather(tf.reshape(inputs, [-1]), argmax), shape)
# assert np.all(tf_res == output) # For debugging when the input is real only!
assert tf_res.dtype == inputs.dtype
return tf_res
Expand Down Expand Up @@ -989,7 +984,7 @@ def get_real_equivalent(self):
__copyright__ = 'Copyright 2020, {project_name}'
__credits__ = ['{credit_list}']
__license__ = '{license}'
__version__ = '1.0.0'
__version__ = '1.0.1'
__maintainer__ = 'J. Agustin BARRACHINA'
__email__ = 'joseagustin.barra@gmail.com; jose-agustin.barrachina@centralesupelec.fr'
__status__ = '{dev_status}'
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Complex-Valued Neural Network (CVNN)
====================================

:Author: J. Agustin Barrachina
:Version: 1.0.0 of 01/05/2021
:Version: 1.0.1 of 01/20/2021


Content
Expand Down
21 changes: 10 additions & 11 deletions tests/test_custom_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ def dropout():
[7.5 + 7.5j, 8.75 + 8.75j],
[10. + 10.j, 0. + 0.j]]
)
set_trace()
assert np.all(data == layer(data, training=False))
assert np.all(outputs == expected_out)
ds_train, ds_test = get_dataset()
Expand All @@ -161,7 +160,7 @@ def get_img():
[0, 2, 2],
[0, 5, 7]
], [
[0, 4, 5],
[0, 7, 5],
[3, 7, 9],
[4, 5, 3]
]]).astype(np.float32)
Expand All @@ -181,7 +180,7 @@ def get_img():

def complex_max_pool_2d():
img = get_img()
max_pool = ComplexMaxPooling2D(strides=1)
max_pool = ComplexMaxPooling2D(strides=1, data_format="channels_last")
res = max_pool(img.astype(np.complex64))
expected_res = np.array([
[[
Expand All @@ -190,13 +189,13 @@ def complex_max_pool_2d():
[[2. + 7.j],
[2. + 9.j]]],
[[
[7. + 2.j],
[7. + 4.j],
[9. + 2.j]],
[
[5. + 8.j],
[3. + 9.j]]
]])
assert (res == expected_res.astype(np.complex64)).numpy().all()
[5. + 8.j],
[3. + 9.j]]]
])
assert (res.numpy() == expected_res.astype(np.complex64)).all()
x = tf.constant([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]])
Expand All @@ -211,15 +210,15 @@ def complex_avg_pool():
avg_pool = ComplexAvgPooling2D(strides=1)
res = avg_pool(img.astype(np.complex64))
expected_res = np.array([[[[0.75 + 3.5j], [1.75 + 6.25j]], [[1.75 + 4.75j], [4. + 6.j]]],
[[[3.5 + 2.25j], [6.25 + 3.25j]], [[4.75 + 4.25j], [6. + 5.25j]]]])
assert (res == expected_res.astype(np.complex64)).numpy().all()
[[[4.25+2.25j], [7 + 3.25j]], [[4.75 + 4.25j], [6. + 5.25j]]]])
assert (res.numpy() == expected_res.astype(np.complex64)).all()


def test_layers():
complex_max_pool_2d()
dropout()
complex_avg_pool()
shape_ad_dtype_of_conv2d()
complex_max_pool_2d()
dense_example()


Expand Down
48 changes: 42 additions & 6 deletions tests/test_several_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from tensorflow.keras import datasets, models
from cvnn.initializers import ComplexGlorotUniform
from cvnn.layers import ComplexDense, ComplexFlatten, ComplexInput
import cvnn.layers as complex_layers
from cvnn import layers
from cvnn.montecarlo import run_gaussian_dataset_montecarlo

Expand Down Expand Up @@ -84,12 +85,13 @@ def cifar10_test():
test_images = test_images.astype(dtype_1)
train_labels = train_labels.astype(dtype_1)
test_labels = test_labels.astype(dtype_1)

model = models.Sequential()
model.add(layers.ComplexInput(input_shape=(32, 32, 3), dtype=dtype_1)) # Never forget this!!!
model.add(layers.ComplexConv2D(32, (3, 3), activation='cart_relu'))
model.add(layers.ComplexAvgPooling2D((2, 2)))
model.add(layers.ComplexMaxPooling2D((2, 2))) # TODO: This is changing the dtype!
model.add(layers.ComplexConv2D(64, (3, 3), activation='cart_relu'))
model.add(layers.ComplexMaxPooling2D((2, 2))) # TODO: This is changing the dtype!
model.add(layers.ComplexAvgPooling2D((2, 2)))
model.add(layers.ComplexConv2D(64, (3, 3), activation='cart_relu'))
model.add(layers.ComplexFlatten())
model.add(layers.ComplexDense(64, activation='cart_relu'))
Expand All @@ -101,12 +103,46 @@ def cifar10_test():
history = model.fit(train_images, train_labels, epochs=2, validation_data=(test_images, test_labels))


def random_dataset():
x_train = np.complex64(tf.complex(tf.random.uniform([640, 65, 82, 1]), tf.random.uniform([640, 65, 82, 1])))
x_test = np.complex64(tf.complex(tf.random.uniform([200, 65, 82, 1]), tf.random.uniform([200, 65, 82, 1])))
y_train = np.uint8(np.random.randint(5, size=(640, 1)))
y_test = np.uint8(np.random.randint(5, size=(200, 1)))

model = tf.keras.models.Sequential()
model.add(complex_layers.ComplexInput(input_shape=(65, 82, 1))) # Always use ComplexInput at the start
model.add(complex_layers.ComplexConv2D(8, (5, 5), activation='cart_relu'))
model.add(complex_layers.ComplexMaxPooling2D((2, 2)))
model.add(complex_layers.ComplexConv2D(16, (5, 5), activation='cart_relu'))
model.add(complex_layers.ComplexFlatten())
model.add(complex_layers.ComplexDense(256, activation='cart_relu'))
model.add(complex_layers.ComplexDropout(0.1))
model.add(complex_layers.ComplexDense(64, activation='cart_relu'))
model.add(complex_layers.ComplexDropout(0.1))
model.add(complex_layers.ComplexDense(5, activation='convert_to_real_with_abs'))
# An activation that casts to real must be used at the last layer.
# The loss function cannot minimize a complex number

# Compile it
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'],
# run_eagerly=True
)
model.summary()

# Train and evaluate
history = model.fit(x_train, y_train, epochs=100, validation_data=(x_test, y_test))
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)


def test_datasets():
cifar10_test()
fashion_mnist_example()
mnist_example()
run_gaussian_dataset_montecarlo(epochs=2, iterations=1)
random_dataset()
# fashion_mnist_example()
# mnist_example()
# run_gaussian_dataset_montecarlo(epochs=2, iterations=1)


if __name__ == '__main__':
test_datasets()
test_datasets()

0 comments on commit b1a7959

Please sign in to comment.