-
Notifications
You must be signed in to change notification settings - Fork 18.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose all netstate options (for all-in-one nets) #3863
Expose all netstate options (for all-in-one nets) #3863
Conversation
670ac9a
to
7b2638f
Compare
While I agree that the new interface is more Pythonic, I personally think that the old interface can be maintained with a little bit of massaging. All that needs to be edited is the Modify the end of # Original Boost.Python Net.__init__ function
_Net_init_boost = Net.__init__
def _Net_init(self, *args, **kwargs):
""" Construct a caffe.Net """
# Transform the arguments to handle the legacy API
if len(args) == 2 and not kwargs:
# Handle case: Net(param_file, phase)
_Net_init_boost(self, args[0], weights_file=None, phase=args[1])
elif len(args) == 3 and not kwargs:
# Handle case: Net(param_file, weights_file, phase)
_Net_init_boost(self, args[0], weights_file=args[1], phase=args[2])
else:
# Handle new API:
# Net('net.prototxt', weights_file='weights.caffemodel', phase=caffe.TEST, level=1, stages=['deploy'])
_Net_init_boost(self, *args, **kwargs)
# Attach methods to Net.
Net.__init__ = _Net_init
... The above code makes One other note: It seems that if you wanted to use a kwarg for every argument, then in some place it's named |
@@ -25,6 +25,7 @@ class Net { | |||
public: | |||
explicit Net(const NetParameter& param, const Net* root_net = NULL); | |||
explicit Net(const string& param_file, Phase phase, | |||
const int level = 0, const vector<string>* stages = NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also insert the new arguments (level, stages) after root_net? Otherwise, this breaks calling code that instantiates Net with root_net non-null:
Net(param_file, phase, root_net);
I'm not sure how common this is, but it's pretty trivial to avoid it by just inserting the new optional arguments at the end of the declaration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, that seems like the safer choice. I wonder why no tests failed? Seems like a test hole.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does anyone use the root_net
parameter? I'd like to keep the phase
, level
and stages
parameters next to each other since they're naturally grouped. If anything, I'd prefer to move root_net
before phase
, but that would definitely break existing code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per Evan's comments below, I reverted back to the original behavior of moving root_net
to the end.
EDIT - Oh, I see what you were pointing out. I was being internally inconsistent with my own code. Whoops! |
a8d1c46
to
7a162bf
Compare
@seanbell I think I've found a nice compromise between our solutions. I've left the old Now all of these constructors work as expected: ### Legacy style
net = caffe.Net('network.prototxt', caffe.TRAIN)
net = caffe.Net('network.prototxt', 'weights.caffemodel', caffe.TEST)
# pattern matches to Net(network_file, weights_file, phase)
# prints deprecation warning
### New style
net = caffe.Net('network.prototxt', phase=caffe.TRAIN)
net = caffe.Net('network.prototxt', weights_file='weights.caffemodel', phase=caffe.TEST)
net = caffe.Net('network.prototxt', phase=caffe.TEST, weights_file='weights.caffemodel')
net = caffe.Net('network.prototxt', caffe.TRAIN, 0)
# pattern matches to Net(network_file, phase, level)
net = caffe.Net('network.prototxt', caffe.TEST, 0, [], 'weights.caffemodel') Made changes and rebased to address merge conflict from #3982. |
7a162bf
to
0daee4a
Compare
Is there anything in particular holding back this PR? Does the re-arranging of the Is my Python constructor compromise not satisfactory? |
0daee4a
to
8397212
Compare
|
LGTM. Cool stuff @lukeyeager! |
Will review after NIPS deadline 05/20. Thanks for this @lukeyeager and thanks for review @ajtulloch! |
bp::default_call_policies(), (bp::arg("network_file"), "phase", | ||
bp::arg("level")=0, bp::arg("stages")=bp::object(), | ||
bp::arg("weights_file")=bp::object()))) | ||
// XXX Legacy constructor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for XXX
-- the comment is clear as it is.
8397212
to
dab822c
Compare
Re: |
Although I originally voted for net states and these varied ways of expressing them, I'm now of two minds. On one hand phase, level, and stage states make all-in-one definitions possible and potentially make variations easier to express, but on the other these are just more special cases in the definition of nets. That said, they do seem to address a need in practice and since they are in the library they should at least be properly exposed to its interfaces. Thoughts @jeffdonahue @longjon? While I now use and suggest net spec, net states have their purposes so thanks for extending them throughout the interfaces @lukeyeager. For merge:
Let me know if there are other concerns. |
I've addressed (1) and (2). (3) Gulp. Time to dive into gtest ... (4) Don't care |
None of those invocations need updating - they use a different constructor which expects a |
Done
Done |
#3863 (comment) Right, sorry about that. With #3863 (comment) this looks good to me. @longjon will double-check for merge. |
This internal functionality will be exposed through the various interfaces in subsequent commits Also adds C++ tests for all-in-one nets
Adds command-line flags for phase, level and stage train -- override level and stages for test_state from solver test -- set level and stages time -- set phase, level and stages
Uses Boost.Python's pattern matching to differentiate between constructors Also adds Python tests for all-in-one nets
56c316e
to
19adc7a
Compare
Rebased after conflict from #4227 |
Merging after offline discussion. Thanks @lukeyeager! p.s. @jeffdonahue noted that this not strictly necessary since the |
Sure, but it's nice to be able to change it without editing
Thanks! |
…-options Expose all netstate options (for all-in-one nets)
Was #3736
There are 3 configurable dimensions to a network's NetState: phase (TRAIN or TEST), level and stage. Currently, only phase is exposed through common interfaces. This PR exposes level and stage to the user, further enabling all-in-one nets (#1245)
New CLI:
New pycaffe interface:
EDIT: PR has been updated not to break old code
This is a breaking change (see #1790 (comment) for an explanation). Users will need to transform pycaffe code like:to:With some effort, this could probably be done without breaking the interface (but I'd need some help with the Boost.Python code). However, I am actually in favor of breaking the interface in order to make it simpler and more "Pythonic".