-
Notifications
You must be signed in to change notification settings - Fork 120
Customize Model via subclassing, clean up public-facing Model+Viz api #10
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
Conversation
* Changes to Model + subclasses
- Define public attributes as properties
- Rename class attributes to be all-caps
- Make it so that to use a model, you subclass the relevant interface and
override its attributes (e.g., `preprocess`, `predict`), rather than pass
these attributes in as arguments to the constructor via the path to the
function and the function's name.
- Call `load` in the constructor, since (1) none of instance's attributes
have defined values before `load` is called which is weird, (2) we only
expect to call `load` once, (3) we always call `load` right after
initializing the instance anyway.
- Make `load` private (--> `_load`)
- Update `generate_model` --> `get_model` and how config files are loaded
accordingly.
- Rename `preprocess(targets)` --> `preprocess(raw_inputs)` [why did we
call it targets in the first place?]
- Get rid of `predict` which isn't used, and rename `_predict` to `predict`
(which still isn't used, but at least now we don't have an unused wrapper
around the unused method).
- Get rid of `postprocess`, since it is specific to SaliencyMap, and we can
also achieve the same without defining that function by inspecting the
shape of the model's input image tensor.
- In examples, don't override decode_prob if the implementation matches the
default. Accordingly, I got rid of the warnings in the interface.
- Rename `Model` to `BaseModel` to match BaseVisualization
- Move lines outside of try/except block if they're not meant to be caught
* Changes to BaseVisualization + subclasses
- Define public instance attributes as properties
- Rename class attributes to be all-caps
- To see if an attribute was overridden in the subclass, define the attribute
to be `None` in the interface, then check for `None` rather than checking
if the attribute exists
* Formatting (I only fixed this when I saw it)
- Remove end-of-line backslashes
- In generator expressions, when 'for x in y' is split into multiple lines,
put the 'for' on a new line
- Instead of writing dict.update({'key': value}) when updating with a single
key, write dict['key'] = value
- Add periods to comments, esp in docstrings (comments look more complete
this way. Not a big deal, but a good habit leftover from my DE Shaw
internship boss, who is a Python guru)
|
Proposals (these are probably more controversial):
|
|
Future (I can add these as issues)
|
Codecov Report
@@ Coverage Diff @@
## master #10 +/- ##
==========================================
- Coverage 89.27% 84.03% -5.25%
==========================================
Files 11 11
Lines 457 426 -31
==========================================
- Hits 408 358 -50
- Misses 49 68 +19 |
|
@rhsimplex I think the code coverage will be alright once you merge #9 in, and I rebase on top. |
|
We'll split this up into smaller parts when you get back -- it's too difficult to merge with the trickle of bug fixes coming in which require continuous rebasing. Also I don't want the I suggest we do it this way, which should minimize work for you and make it very easy to merge:
I hope it's clear why I'm requesting this. If not, let me know. |
|
OK @rhsimplex I will go ahead and refactor the PR as you asked. I like the way you broke up the changes. I see the benefits of the clearer history/review. In my head, I still have a bias against breaking up this PR since I tend to put higher weight on reducing code change overhead than on keeping clear git history/reviews. Clear git history is nice, but I don't like when it discourages micro improvements to code. I will keep track of how long it ends up taking me to do so and re-evaluate my bias - I always have room to learn here. As for your suggestion on having I agree with you in that I don't like the constructor being so costly, but I also don't like letting users initialize an object whose attributes and methods don't mean anything until |
|
Also @rhsimplex can you comment on my proposals (2nd comment in this PR)? |
|
I just spent 1hr 30min trying to separate out the PR :( Let's talk in meatspace tomorrow! |
Changes to Model + subclasses
override its attributes (e.g.,
preprocess,predict), rather than passthese attributes in as arguments to the constructor.
Callloadin the constructor, since (1) none of instance's attributeshave defined values before
loadis called which is weird, (2) we onlyexpect to call
loadonce, (3) we always callloadright afterinitializing the instance anyway.
Makeloadprivate (-->_load) since it's only called in the constructor.generate_model-->get_modeland how config files are loadedaccordingly.
preprocess(targets)-->preprocess(raw_inputs)[why did wecall it targets in the first place?]
predictwhich isn't used, and rename_predicttopredict(which still isn't used, but at least now we don't have an unused wrapper
around the unused method).
postprocess, since it is specific to SaliencyMap, and we canalso achieve the same without defining that function by inspecting the
shape of the model's input image tensor.
default. Accordingly, I got rid of the warnings in the interface.
ModeltoBaseModelto match BaseVisualizationChanges to BaseVisualization + subclasses
to be
Nonein the interface, then check forNonerather than checkingif the attribute exists
Formatting (I only fixed this when I saw it)
put the 'for' on a new line
this way. Not a big deal, but a good habit leftover from my DE Shaw
internship boss, who is a Python guru)
key, write dict['key'] = value