# DAVIDSTUTZ

Check out the latest superpixel benchmark — Superpixel Benchmark (2016) — and let me know your opinion! @david_stutz
19thFEBRUARY2017

## Creating the Double Type and Double Operations in Theano

Following the Theano documentation, this snippet illustrates the creation of a new Theano type, namely the Double type. Based on this type, the add operation is implemented. Originally, I intended this as a quick tutorial on how to define more complex types with differentiable operations. However, as also discussed here, this turned out to be more involved than expected.

`double.py`
```"""
Creating a double type for theano following http://deeplearning.net/software/theano/extending/type.html.
Also see for discussion: http://stackoverflow.com/questions/41858327/how-to-define-custom-theano-types-allowing-differentiation
"""

import theano

class Double(theano.gof.Type):
"""
Double type for theano.
"""

dtype = 'float64'

def filter(self, value, strict = False, allow_downcast = None):
"""
Cast to double.
"""

if strict:
# we need to return a type, but if the value is incompatible raise an exception
if isinstance(value, float):
return value
else:
raise TypeError('Expected a float!')
elif allow_downcast:
return float(value)
else:
value_float = float(value)
if value_float == value:
return value_float
else:
raise TypeError('The double type cannot be accurately represent %s of type %s' % (value, type(value)))

def values_eq_approx(self, value_a, value_b, tolerance = 1e-6):
"""
Check whether values are approximately equal.
"""

return abs(value_a - value_b) / (abs(value_a) + abs(value_b)) < tolerance

def ones_like(self, model, dtype):
print(model)
print(dtype)
return double('1')

# using this method causes the type to not be hashable anymore?! - strange ...
#def __eq__(self, value):
"""
To allow using ==.
"""
#return type(self) is Double and type(value) is Double

# is already used in the operations below
double = Double()

"""
"""

__props__ = ()

def make_node(self, x, y):
"""
Define output variables.
"""

# check input types
if isinstance(x, (int, float)):
x = theano.gof.Constant(double, x)
if isinstance(y, (int, float)):
y = theano.gof.Constant(double, y)

if x.type != double or y.type != double:
raise TypeError('DoubleAddOp only works on doubles.')

return theano.gof.Apply(self, [x, y], [double()])

def perform(self, node, inputs, output_storage):
"""
"""

x = inputs[0]
y = inputs[1]
z = output_storage[0]
z[0] = x + y

def infer_shape(self, node, input_shapes):
"""
Used to infer the shape before performing the operation.
"""

return [input_shapes[0]]

"""
Compute the gradients w.r.t. both inputs.
"""

def __str__(self):
"""
Identification.
"""

```
`double_tests.py`
```"""
Tests for the double type and its operations.
"""

import theano
import random
import unittest

class TestDoubleOps(unittest.TestCase):
"""
Test operations on doubles.
"""

# update to the latest Theano if the test cause unclosed files errors
x = double('x')
y = double('y')
f = theano.function([x, y], z)

for i in range(100):
x_value = random.random()
y_value = random.random()
self.assertAlmostEqual(f(x_value, y_value), x_value + y_value)

x = double('x')
y = double('y')
f = theano.function([x, y], [gx, gy])

for i in range(100):
x_value = random.random()
y_value = random.random()

gx_value, gy_value = f(x_value, y_value)
self.assertAlmostEqual(gx_value, 1)
self.assertAlmostEqual(gy_value, 1)

if __name__ == '__main__':
unittest.main()
```

What is your opinion on the code snippet? Is it working? Let me know your thoughts in the comments below or using the following platforms: