Optimizer package for Graph mode#28
Conversation
|
@Craigacp , just quickly like that, it looks like you'll need to rebase your PR to resolve a conflict |
|
@Craigacp cool stuff! Did you mean to commit the files under |
|
I rebased the branch and the deterministic generation commits went away with the associated conflict, but I seem to have picked up the ci changes that got merged in earlier today. |
karllessard
left a comment
There was a problem hiding this comment.
Thanks @Craigacp , this is a very great addition to TF Java. I didn't went through the logic behind the optimizers themselves yet but just dropped quickly a few suggestions you might want to review before applying your next changes.
tensorflow-core/tensorflow-core-api/src/gen/java/org/tensorflow/op/core/VariableWithInit.java
Outdated
Show resolved
Hide resolved
tensorflow-core/tensorflow-core-api/src/gen/java/org/tensorflow/op/core/VariableWithInit.java
Outdated
Show resolved
Hide resolved
tensorflow-core/tensorflow-core-api/src/gen/java/org/tensorflow/op/core/VariableWithInit.java
Outdated
Show resolved
Hide resolved
tensorflow-core/tensorflow-core-api/src/gen/java/org/tensorflow/op/core/VariableWithInit.java
Outdated
Show resolved
Hide resolved
tensorflow-training/src/main/java/org/tensorflow/training/examples/MNISTTest.java
Outdated
Show resolved
Hide resolved
tensorflow-training/src/main/java/org/tensorflow/training/examples/MNISTTest.java
Outdated
Show resolved
Hide resolved
| @@ -0,0 +1,92 @@ | |||
| /* | |||
| * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. | |||
There was a problem hiding this comment.
2020, also shouldn't it be copyright to The Tensorflow Authors like all other files in the project?
There was a problem hiding this comment.
We don't have an authors file in this repo, plus this is the text that Oracle Legal requires on all outbound source contributions. I'm not sure if putting it in the AUTHORS file will be sufficient for them. It looks like the main TF repo has an AUTHORS, but then it says to look at CONTRIBUTORS which doesn't exist, so maybe someone at Google should figure out what they want it to look like for all the TF related repos.
|
|
||
| private final float rho; | ||
|
|
||
| private final float epsilon; |
There was a problem hiding this comment.
I don't think we need to enforce it but just FYI, pretty much all TF classes declare their members in this order, including both fields and methods: public, protected, default, private
There was a problem hiding this comment.
Do you mean all the public methods & fields, then protected etc, or all the public methods, protected methods, ... then public fields, protected fields etc?
There was a problem hiding this comment.
Well in this format, things are grouped per scope, meaning:
- public fields
- public methods
- protected fields
- protected methods
- ... and so on
Again, I don't necessarily want to continue enforcing this in our new repo but maybe we can apply it at least in the core, so that all classes of a single artifact follows the same pattern?
|
|
||
| protected Optimizer(Graph graph) { | ||
| this.graph = graph; | ||
| this.tf = Ops.create(graph).withName(getOptimizerName()); |
There was a problem hiding this comment.
would it be easy to allow the user override the name of the scope for the optimizer ops (instead of getOptimizerName())? Also, maybe a user would like to pass its own instance of Ops (which might already be a subscope of another block or contains control dependencies, etc.)?
There was a problem hiding this comment.
It's locked off to Graph at the moment as I don't think any of this works in eager mode, so the type system enforces that. I can allow a hook for the name, and we could relax the Graph check to an instanceof check throwing IllegalArgumentException to supply an ops. Should I keep the Graph entry point as well?
There was a problem hiding this comment.
Yes I think it is ok that to have an entry point that accept a Graph but maybe add another that accept an Ops as well, so the user has full control on the name and control dependencies of the optmizers? Or maybe just a String for the name
For instance, does it make sense that a user would want to create two different optimizers of the same type (but with different parameters) for handling different variables? If so, then he'll need to give them different names or he will endup with a name conflict.
I think you understand my questioning here, I'll let you decide what would be the best approach to handle those corner cases.
There was a problem hiding this comment.
I added an additional constructor which accepts a Graph and a String for the base name of the operations.
195deff to
7e3459b
Compare
|
I've rebased on the latest master, fixed the style issues, put the try with resources in, and updated it to use the |
tensorflow-core/tensorflow-core-api/src/gen/annotations/org/tensorflow/op/Ops.java
Outdated
Show resolved
Hide resolved
| * and return one of them. | ||
| */ | ||
| @Operator | ||
| public abstract class CoreOps { |
There was a problem hiding this comment.
This class name is a bit misleading, as all other *Ops classes are generated and exposes tf.* endpoints. Here, we are dealing with the endpoint implementations.
I've never been a huge fan of the *Ops name for the generated classes neither (even if that was my idea if I recall correctly...) and we could rename them instead. Like TensorFlowApi, TensorFlowLinearApi, TensorFlowSparseApi, etc. would be better picks.
But if we don't want to do this breaking change then I think we need to come up with something else for this new class.
There was a problem hiding this comment.
I renamed it to Helpers, but that's also not a great name.
tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/op/core/CoreOps.java
Show resolved
Hide resolved
tensorflow-training/src/main/java/org/tensorflow/training/examples/MNISTTest.java
Outdated
Show resolved
Hide resolved
|
|
||
| private final float rho; | ||
|
|
||
| private final float epsilon; |
There was a problem hiding this comment.
Well in this format, things are grouped per scope, meaning:
- public fields
- public methods
- protected fields
- protected methods
- ... and so on
Again, I don't necessarily want to continue enforcing this in our new repo but maybe we can apply it at least in the core, so that all classes of a single artifact follows the same pattern?
tensorflow-training/src/main/java/org/tensorflow/training/optimizers/Optimizer.java
Outdated
Show resolved
Hide resolved
|
|
||
| protected Optimizer(Graph graph) { | ||
| this.graph = graph; | ||
| this.tf = Ops.create(graph).withName(getOptimizerName()); |
There was a problem hiding this comment.
Yes I think it is ok that to have an entry point that accept a Graph but maybe add another that accept an Ops as well, so the user has full control on the name and control dependencies of the optmizers? Or maybe just a String for the name
For instance, does it make sense that a user would want to create two different optimizers of the same type (but with different parameters) for handling different variables? If so, then he'll need to give them different names or he will endup with a name conflict.
I think you understand my questioning here, I'll let you decide what would be the best approach to handle those corner cases.
| List<Operation> variables = new ArrayList<>(); | ||
| Iterator<Operation> opItr = graph.operations(); | ||
| while (opItr.hasNext()) { | ||
| Operation op = opItr.next(); |
There was a problem hiding this comment.
graph.operations().forEachRemaining maybe?
Also, is it OK that an optimizer is always applied to all variables in the graph? Is this true for all kind of graphs?
There was a problem hiding this comment.
That's how they work in Python. It's really hard to make it work any other way without a lot of ceremony.
tensorflow-training/src/main/java/org/tensorflow/training/optimizers/Optimizer.java
Show resolved
Hide resolved
tensorflow-training/src/main/java/org/tensorflow/training/optimizers/RMSProp.java
Outdated
Show resolved
Hide resolved
|
Please don’t forget to rebase your PR before pushing a new version as I just merged some other breaking changes (mainly renaming ˋtf.constant |
02c25c2 to
6ae5ace
Compare
… the constructors, removing the MNISTTtest.
This adds a new subproject
tensorflow-trainingwhich currently containsorg.tensorflow.training.optimizersa package of gradient optimizers which apply the underlying gradient update ops to a TF Graph.In addition to the optimizers it makes a few small changes in the
tensorflow-core-apipackage: it adds a variables initialiser list toGraph, a method which constructs an initialiser node which initialises all the variables in the graph, plus avariableWithInitmethod which accepts anOperandwhich is used to provide the shape, type and initial value for the variable.There's also an MNIST CNN test in there, which we can move out to wherever it needs to go, and be combined with the other ones.
Before this gets merged it needs better Javadoc in the Optimizer class, and the global variables used by some of the optimizers need wiring into the globals field in the base class. I'll fix those things next week.