Skip to content
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

Accumulating loggers #135

Merged
merged 32 commits into from
Jan 9, 2020
Merged

Accumulating loggers #135

merged 32 commits into from
Jan 9, 2020

Conversation

shwang
Copy link
Member

@shwang shwang commented Dec 7, 2019

Add mean-accumulating log context for tracking discrim and generator stats together even though they are trained serially and with different numbers of kv logs.

  • See how this looks on our Sacred scripts
  • Probably should forward _AccumulatingLogger.logkv_mean as well.

@codecov
Copy link

codecov bot commented Dec 18, 2019

Codecov Report

Merging #135 into master will increase coverage by 0.57%.
The diff coverage is 89.58%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #135      +/-   ##
==========================================
+ Coverage   86.83%   87.41%   +0.57%     
==========================================
  Files          63       62       -1     
  Lines        4468     4465       -3     
==========================================
+ Hits         3880     3903      +23     
+ Misses        588      562      -26
Impacted Files Coverage Δ
src/imitation/util/util.py 99.13% <100%> (ø) ⬆️
src/imitation/rewards/discrim_net.py 97.9% <100%> (+3.16%) ⬆️
tests/test_trainer.py 100% <100%> (ø) ⬆️
src/imitation/algorithms/adversarial.py 90.47% <67.85%> (+0.47%) ⬆️
src/imitation/util/logger.py 93.67% <83.33%> (+1.36%) ⬆️
src/imitation/rewards/reward_net.py 95.78% <0%> (+5.26%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6510553...142c2ae. Read the comment docs.

@AdamGleave AdamGleave self-requested a review December 18, 2019 04:15
Copy link
Member

@AdamGleave AdamGleave left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for implementing this, big improvement.

I'm a bit uneasy with the amount of global state in imitation.util.logger: made some suggestions on how to reduce this.

Otherwise some fairly minor comments.

src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
tests/test_logger.py Show resolved Hide resolved
tests/test_logger.py Show resolved Hide resolved
tests/test_logger.py Outdated Show resolved Hide resolved
src/imitation/algorithms/adversarial.py Outdated Show resolved Hide resolved
@shwang shwang requested a review from AdamGleave December 19, 2019 21:35
Copy link
Member

@AdamGleave AdamGleave left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the changes, looks good, left few minor comments

src/imitation/algorithms/adversarial.py Outdated Show resolved Hide resolved
src/imitation/scripts/train_adversarial.py Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
@shwang shwang requested a review from AdamGleave January 4, 2020 03:10
Copy link
Member

@AdamGleave AdamGleave left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seem like some bugs in current implementation but design looks ok. LMK when tests are passing and ready for review again.

(If I'm unresponsive, review by Cody/Sam is fine too.)

src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Outdated Show resolved Hide resolved
src/imitation/util/logger.py Show resolved Hide resolved
@shwang shwang requested a review from AdamGleave January 7, 2020 01:05
@shwang shwang requested a review from qxcv January 8, 2020 22:27
Copy link
Member

@qxcv qxcv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should clear up what the expected behaviour of .logkv_mean() and .log() should be before we merge this (see comments), but other than that I'm okay (comment on the log key prefix is not a deal-breaker for me).

def logkv(self, key, val):
if self.current_logger is not None:
assert self._subdir is not None
raw_key = os.path.join("raw", self._subdir, key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is bike-shedding a little, but is it really necessary to have the raw/{subdir}/ prefix on all of the entries in the self.current_logger log? As I understand it we'll end up with a bunch of log files in which all log entries start with raw/subdir/, which would be redundant given that you can infer what kind of entries they are from the directory hierarchy (i.e. the raw log file is already in a raw/subdir folder).

(overall I still like the design!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adam thought this was weird too, we had a comment thread about this here.

Reasons for redundant-looking prefix:
(1) So that in Tensorboard plots, mean plots are automatically separated from raw plots (which have a different x axis). (TB plots are grouped by key name).
(2) To distinguish between raw and mean keys in stdout logging (otherwise they look identical).

(1) is my primary motivation. Adam was convinced by (2). Though now that I think about it, it might be better to just turn off raw stdout logs and show mean stdout logs only.

else:
return self.default_logger

def logkv_mean(self, key, val):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this nest correctly? e.g. say I was in a discriminator context ("disc") and I did .logkv_mean("foo", <value>) J times, did a .dumpkvs(), then did .logkv_mean() J more times, and repeated that process K times. If I looked at the raw logs, I'd expect them to contain K entries of the form raw/disc/foo: <mean of J values>, while in the logs for the parent, I'd expect one entry of the form mean/disc/foo: <mean of J*K values>. As I understand it, the current implementation will write straight through to the "raw" child logger without putting anything in the parent, and without writing any key prefixes. Perhaps it's safer to remove this implementation & raise NotImplementedError() instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, on reflection the correct thing to do is probably raise NotImplementedError when self.current_logger is not None, else pass through to self.default_logger.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't thought too carefully about the inside-context logkv_mean case.

I'm a bit hesitant about raising NotImplementedError while inside the generator context. What if gen_policy.learn() (ie some arbitrary Stable Baselines algorithm) wants to call logkv_mean for some reason?.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it, the current implementation will write straight through to the "raw" child logger without putting anything in the parent, and without writing any key prefixes.

This understanding seems correct, thanks for catching this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@qxcv
How does this solution sound? Because we don't want to error out if some third-party package calls log or logkv_mean inside the context, and HierachicalLogger only claims to modify logkv behavior, we can just
(1) redirect log, logkv_mean to the default logger, unchanged and without prefixes and
(2) note this prominently in the documentation?

self._logger.dumpkvs()

def log(self, *args, **kwargs):
self._logger.log(*args, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above; this won't do the expected name prefixing. Perhaps just prohibit calls to this with a NotImplementedError?

Copy link
Member Author

@shwang shwang Jan 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Response in #135 (comment)

src/imitation/util/logger.py Show resolved Hide resolved
@shwang
Copy link
Member Author

shwang commented Jan 9, 2020

Thanks for the review. I've pushed my proposed fixes here

@shwang shwang requested a review from qxcv January 9, 2020 01:56
Copy link
Member

@qxcv qxcv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@shwang shwang merged commit 63db8e9 into master Jan 9, 2020
@shwang shwang deleted the accumulating_log branch January 9, 2020 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants