Add support for tensorflow together with ODL#972
Conversation
|
Phew.. My review here against your review on #861? :-P |
|
It's on its way :) But you wait until I rebase from master, this is actually quite a small PR. |
|
Is this ready for review or should I wait? |
|
Still havn't merged from master, but you can easily get started if you want to. |
kohr-h
left a comment
There was a problem hiding this comment.
I guess since this code is battle-tested there's not very much to say about the implementation itself. I just wonder if temporaries would make sense to speed up things, but that might quickly become infeasible. Dunno.
In general I find the wrapping code hard to digest, not because of complexity (it's really not that elaborate) but more because of all the inline function definitions that take up quite some space. If there's a way to make this a bit less nested, I'd appreciate it.
Anyway, docs could use some cleanup. Other than that it looks good (nice detective work on the ninja-style workarounds).
|
|
||
|
|
||
| What is vectorization? | ||
| ====================== |
There was a problem hiding this comment.
Has this stuff moved here from some other file?
In any case, can you convert it to the "one sentence - one line" RST style?
| ============ | ||
|
|
||
| Python functions are in most cases used as input to a discretization process. For example, we may | ||
| want to discretize a two-dimensional Gaussian function: |
| @@ -0,0 +1,38 @@ | |||
| """Example of how to convert an ODL operator to a tensorflow layer.""" | |||
|
|
|||
| import tensorflow as tf | |||
There was a problem hiding this comment.
Are we sure that odl.contrib.tensorflow is never confused with tensorflow (e.g. odl.contrib.tensorflow.tensorflow)?
If tensorflow wasn't already so long I'd suggest using a bindings suffix.. Maybe a shorter package name like tf_bindings will cut it?
There was a problem hiding this comment.
I'm quite sure that is a nonproblem. With that said I'll change this whole thing to a submodule and split it, that allows better long-term extensions.
|
|
||
| # Create tensorflow layer from odl operator | ||
| odl_op_layer = odl.contrib.tensorflow.as_tensorflow_layer( | ||
| odl_op, 'MatrixOperator') |
| print(odl_op(x)) | ||
|
|
||
| # Evaluate the adjoint of the derivative, called gradient in tensorflow | ||
| print(tf.gradients(y_tf, [x_tf], z_tf)[0].eval().ravel()) |
There was a problem hiding this comment.
Perhaps use keyword arguments to make the code more self-explanatory. Now it's a bit of guesswork as to what variable stands for what.
| self.name = name | ||
|
|
||
| def _lincomb(self, a, x1, b, x2, out): | ||
| with tf.name_scope('{}_lincomb'.format(self.name)): |
There was a problem hiding this comment.
Will this clash if you use the same name twice?
There was a problem hiding this comment.
No, it becomes _lincomb_2 etc
| return isinstance(other, TensorflowSpace) and other.shape == self.shape | ||
|
|
||
| def __repr__(self): | ||
| return 'TensorflowSpace({})'.format(self.shape) |
| self._data = value | ||
|
|
||
| def __repr__(self): | ||
| return '{}.element({})'.format(self.space, self.data) |
|
|
||
| """Wrap ODL operator so that it acts on TensorflowSpace elements.""" | ||
|
|
||
| def __init__(self, domain, range, func, adjoint=None, linear=False): |
There was a problem hiding this comment.
Better use the same name for parameter and stored attribute.
| return tensorflow_layer | ||
|
|
||
|
|
||
| class TensorflowSpace(LinearSpace): |
There was a problem hiding this comment.
A bit more docs for the fellas here and below wouldn't hurt.
|
And, to repeat one of the review comments, a top-level README is quite important for this stuff. |
|
Thanks for the review, I'll try to get this done and merged rather soon but I'm waiting for the FOM pull (and more free time for me) since I'll move some stuff into there. |
77d83d0 to
b563410
Compare
|
Fixed the comments, added some tests etc. IMO this can go in now. |
kohr-h
left a comment
There was a problem hiding this comment.
Some final comments, merge when done.
Clearly a very cool addition!
|
|
||
| ## Example usage | ||
|
|
||
| The [examples](examples) folder contains example on how to use the above functionality. |
| * [tensorflow_layer_matrix.py](examples/tensorflow_layer_matrix.py) shows how an ODL `MatrixOperator` can be converted to a tensorflow layer. | ||
| * [tensorflow_layer_productspace.py](examples/tensorflow_layer_productspace.py) shows how an ODL operator acting on `ProductSpace`s can be converted to a tensorflow layer. | ||
| * [tensorflow_layer_ray_transform.py](examples/tensorflow_layer_ray_transform.py) shows how a `RayTransform` can be converted to a tensorflow layer. | ||
| * [tensorflow_operator_matrix.py](examples/tensorflow_operator_matrix.py) shows how `tf.matmul` can be used as a ODL operator. |
|
|
||
| step = learning_rate * np.sqrt(1 - beta2) / (1 - beta1) | ||
|
|
||
| x.lincomb(1, x, -step, m / (np.sqrt(v) + eps)) |
There was a problem hiding this comment.
Did you check this with the paper? Regarding your earlier answer to my review comment, yes, I read the paper, and I couldn't match the expressions there with the implementation here.
There was a problem hiding this comment.
I'll review this once more then I guess!
|
|
||
| # Create a mutually exclusive lock so that two callers cant use the | ||
| # same shared resource at the same time. | ||
| self.mutex = Lock() |
There was a problem hiding this comment.
bump (prefer this a bit more hidden, _mutex)
| working_slc[axis] = intersec_slc[axis] | ||
|
|
||
|
|
||
| def zscore(arr): |
There was a problem hiding this comment.
Is that your naming or is it a standard notion?
There was a problem hiding this comment.
https://se.mathworks.com/help/stats/zscore.html
Is the motivation.
There is also:
https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.stats.mstats.zscore.html
But it does not handle constants "well".
|
Merge after CI |
TODO: summary