Functional layers that are trainable with backpropagation.
Gabor layer
Convolutional layer that forces a functional Gabor form for its filters. Every parameter of the Gabor can be learnt.
Managing dtype
Tensorflow is a bit picky when it comes to dtype, so it can be useful to define a function that will ensure that every parameter is casted to the same dtype:
a, b = tf.convert_to_tensor(1), tf.convert_to_tensor(1.1)print(a.dtype, b.dtype)# assert a.dtype != b.dtype
<dtype: 'int32'> <dtype: 'float32'>
2022-09-20 12:35:22.979033: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
2022-09-20 12:35:22.979117: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:169] retrieving CUDA diagnostic information for host: megatron
2022-09-20 12:35:22.979137: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:176] hostname: megatron
2022-09-20 12:35:22.979295: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:200] libcuda reported version is: 470.57.2
2022-09-20 12:35:22.979361: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:204] kernel reported version is: 470.57.2
2022-09-20 12:35:22.979377: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:310] kernel version seems to match DSO: 470.57.2
c, d = cast_all(a, b)print(c.dtype, d.dtype)assert c.dtype == d.dtype
<dtype: 'float32'> <dtype: 'float32'>
Creating a Gabor filter in TensorFlow
First of all we need to be able to generate Gabor filters as TensorflowTensor:
2022-09-20 12:35:24.252491: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)
Creating a set of Gabor filters
It can be a little bit tricky to translate plain Python for loops into tf.function.
In plain Python, if we wanted to create a set of filters we could initialize an empty array or list and fill it with the different filters generated inside a for loop, but we can’t do that inside a tf.function because Tensorflow tries to build the computational graph and starts to nest graphs inside graphs and the performance is terrible. Luckily for us, they implement a tf.TensorArray that can be used inside a tf.function to this effect.
2022-09-20 12:35:26.542940: W tensorflow/core/framework/op_kernel.cc:1692] OP_REQUIRES failed at functional_ops.cc:374 : Internal: No function library
2022-09-20 12:35:26.545272: W tensorflow/core/framework/op_kernel.cc:1692] OP_REQUIRES failed at functional_ops.cc:374 : Internal: No function library
2022-09-20 12:35:26.547083: W tensorflow/core/framework/op_kernel.cc:1692] OP_REQUIRES failed at functional_ops.cc:374 : Internal: No function library
2022-09-20 12:35:28.025355: W tensorflow/core/framework/op_kernel.cc:1692] OP_REQUIRES failed at functional_ops.cc:374 : Internal: No function library
2022-09-20 12:35:28.026635: W tensorflow/core/framework/op_kernel.cc:1692] OP_REQUIRES failed at functional_ops.cc:374 : Internal: No function library
2022-09-20 12:35:28.027776: W tensorflow/core/framework/op_kernel.cc:1692] OP_REQUIRES failed at functional_ops.cc:374 : Internal: No function library
The Gabor filters are stored in the GaborLayer.filters attribute and while they are re-calculated at each step of training (as should be), they are not re-calculated during inference. At inference time, the last calculated filters are used.
WARNING:tensorflow:5 out of the last 5 calls to <function create_multiple_different_rot_gabor_tf> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.
We can check that the parameters are trainable and thus the gradient is propagated properly:
WARNING:tensorflow:6 out of the last 6 calls to <function create_multiple_different_rot_gabor_tf> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.