-
Notifications
You must be signed in to change notification settings - Fork 1.3k
exp show: handle extending/renaming of metrics/params. #7264
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -65,6 +65,9 @@ def _collect_names(all_experiments, **kwargs): | |||||||||||||||||||||||||||||||||||||||||
| def _collect_rows( | ||||||||||||||||||||||||||||||||||||||||||
| base_rev, | ||||||||||||||||||||||||||||||||||||||||||
| experiments, | ||||||||||||||||||||||||||||||||||||||||||
| all_headers, | ||||||||||||||||||||||||||||||||||||||||||
| metric_headers, | ||||||||||||||||||||||||||||||||||||||||||
| param_headers, | ||||||||||||||||||||||||||||||||||||||||||
| metric_names, | ||||||||||||||||||||||||||||||||||||||||||
| param_names, | ||||||||||||||||||||||||||||||||||||||||||
| deps_names, | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -87,24 +90,26 @@ def _collect_rows( | |||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| new_checkpoint = True | ||||||||||||||||||||||||||||||||||||||||||
| for i, (rev, results) in enumerate(experiments.items()): | ||||||||||||||||||||||||||||||||||||||||||
| fill_value = FILL_VALUE_ERRORED if results.get("error") else fill_value | ||||||||||||||||||||||||||||||||||||||||||
| row_dict = {k: fill_value for k in all_headers} | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| exp = results.get("data", {}) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if exp.get("running"): | ||||||||||||||||||||||||||||||||||||||||||
| state = "Running" | ||||||||||||||||||||||||||||||||||||||||||
| elif exp.get("queued"): | ||||||||||||||||||||||||||||||||||||||||||
| state = "Queued" | ||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||
| state = fill_value | ||||||||||||||||||||||||||||||||||||||||||
| executor = exp.get("executor", fill_value) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| is_baseline = rev == "baseline" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if is_baseline: | ||||||||||||||||||||||||||||||||||||||||||
| name_rev = base_rev[:7] if Git.is_sha(base_rev) else base_rev | ||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||
| name_rev = rev[:7] | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| exp_name = exp.get("name", "") | ||||||||||||||||||||||||||||||||||||||||||
| tip = exp.get("checkpoint_tip") | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| parent_rev = exp.get("checkpoint_parent", "") | ||||||||||||||||||||||||||||||||||||||||||
| parent_exp = experiments.get(parent_rev, {}).get("data", {}) | ||||||||||||||||||||||||||||||||||||||||||
| parent_tip = parent_exp.get("checkpoint_tip") | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -130,26 +135,28 @@ def _collect_rows( | |||||||||||||||||||||||||||||||||||||||||
| if not is_baseline: | ||||||||||||||||||||||||||||||||||||||||||
| new_checkpoint = not (tip and tip == parent_tip) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| row = [ | ||||||||||||||||||||||||||||||||||||||||||
| exp_name, | ||||||||||||||||||||||||||||||||||||||||||
| name_rev, | ||||||||||||||||||||||||||||||||||||||||||
| typ, | ||||||||||||||||||||||||||||||||||||||||||
| _format_time(exp.get("timestamp"), fill_value, iso), | ||||||||||||||||||||||||||||||||||||||||||
| parent, | ||||||||||||||||||||||||||||||||||||||||||
| state, | ||||||||||||||||||||||||||||||||||||||||||
| executor, | ||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||
| fill_value = FILL_VALUE_ERRORED if results.get("error") else fill_value | ||||||||||||||||||||||||||||||||||||||||||
| row_dict["Experiment"] = exp.get("name", "") | ||||||||||||||||||||||||||||||||||||||||||
| row_dict["rev"] = name_rev | ||||||||||||||||||||||||||||||||||||||||||
| row_dict["typ"] = typ | ||||||||||||||||||||||||||||||||||||||||||
| row_dict["Created"] = _format_time( | ||||||||||||||||||||||||||||||||||||||||||
| exp.get("timestamp"), fill_value, iso | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
| row_dict["parent"] = parent | ||||||||||||||||||||||||||||||||||||||||||
| row_dict["State"] = state | ||||||||||||||||||||||||||||||||||||||||||
| row_dict["Executor"] = exp.get("executor", fill_value) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+138
to
+146
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now this requires us to keep headers in sync in two places. (we did that before by forcing an order anyway though).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's true but, as you mentioned, the sync was required before. By using dict keys, at least the sync is explicit (and prevents bug being fixed)
Comment on lines
+138
to
+146
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a nitpicky suggestion, what do you think of using
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean like the following?
Suggested change
No strong preference, is
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @daavoo, I meant it more like following, to use dict arg than as kwargs: row_dict.update({
"Experiment": exp.get("name", ""),
"rev": name_rev,
"typ": typ,
"Created": _format_time(exp.get("timestamp"), fill_value, iso),
"parent": parent,
"State": state,
"Executor": exp.get("executor", fill_value),
...
})It's a matter of personal preference, I guess. As I said, I am fine as-is too. |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| _extend_row( | ||||||||||||||||||||||||||||||||||||||||||
| row, | ||||||||||||||||||||||||||||||||||||||||||
| row_dict, | ||||||||||||||||||||||||||||||||||||||||||
| metric_names, | ||||||||||||||||||||||||||||||||||||||||||
| metric_headers, | ||||||||||||||||||||||||||||||||||||||||||
| exp.get("metrics", {}).items(), | ||||||||||||||||||||||||||||||||||||||||||
| precision, | ||||||||||||||||||||||||||||||||||||||||||
| fill_value=fill_value, | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
| _extend_row( | ||||||||||||||||||||||||||||||||||||||||||
| row, | ||||||||||||||||||||||||||||||||||||||||||
| row_dict, | ||||||||||||||||||||||||||||||||||||||||||
| param_names, | ||||||||||||||||||||||||||||||||||||||||||
| param_headers, | ||||||||||||||||||||||||||||||||||||||||||
| exp.get("params", {}).items(), | ||||||||||||||||||||||||||||||||||||||||||
| precision, | ||||||||||||||||||||||||||||||||||||||||||
| fill_value=fill_value, | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -158,8 +165,8 @@ def _collect_rows( | |||||||||||||||||||||||||||||||||||||||||
| hash_info = exp.get("deps", {}).get(dep, {}).get("hash") | ||||||||||||||||||||||||||||||||||||||||||
| if hash_info is not None: | ||||||||||||||||||||||||||||||||||||||||||
| hash_info = hash_info[:7] | ||||||||||||||||||||||||||||||||||||||||||
| row.append(hash_info or fill_value) | ||||||||||||||||||||||||||||||||||||||||||
| yield row | ||||||||||||||||||||||||||||||||||||||||||
| row_dict[dep] = hash_info | ||||||||||||||||||||||||||||||||||||||||||
| yield list(row_dict.values()) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def _sort_column(sort_by, metric_names, param_names): | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -225,13 +232,9 @@ def _format_time(datetime_obj, fill_value=FILL_VALUE, iso=False): | |||||||||||||||||||||||||||||||||||||||||
| return datetime_obj.strftime(fmt) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def _extend_row(row, names, items, precision, fill_value=FILL_VALUE): | ||||||||||||||||||||||||||||||||||||||||||
| def _extend_row(row, names, headers, items, precision, fill_value=FILL_VALUE): | ||||||||||||||||||||||||||||||||||||||||||
| from dvc.compare import _format_field, with_value | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if not items: | ||||||||||||||||||||||||||||||||||||||||||
| row.extend(fill_value for keys in names.values() for _ in keys) | ||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| for fname, data in items: | ||||||||||||||||||||||||||||||||||||||||||
| item = data.get("data", {}) | ||||||||||||||||||||||||||||||||||||||||||
| item = flatten(item) if isinstance(item, dict) else {fname: item} | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -243,7 +246,11 @@ def _extend_row(row, names, items, precision, fill_value=FILL_VALUE): | |||||||||||||||||||||||||||||||||||||||||
| # wrap field data in ui.rich_text, otherwise rich may | ||||||||||||||||||||||||||||||||||||||||||
| # interpret unescaped braces from list/dict types as rich | ||||||||||||||||||||||||||||||||||||||||||
| # markup tags | ||||||||||||||||||||||||||||||||||||||||||
| row.append(ui.rich_text(str(_format_field(value, precision)))) | ||||||||||||||||||||||||||||||||||||||||||
| value = ui.rich_text(str(_format_field(value, precision))) | ||||||||||||||||||||||||||||||||||||||||||
| if name in headers: | ||||||||||||||||||||||||||||||||||||||||||
| row[name] = value | ||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||
| row[f"{fname}:{name}"] = value | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def experiments_table( | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -264,14 +271,15 @@ def experiments_table( | |||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from dvc.compare import TabularData | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| td = TabularData( | ||||||||||||||||||||||||||||||||||||||||||
| lconcat(headers, metric_headers, param_headers, deps_names), | ||||||||||||||||||||||||||||||||||||||||||
| fill_value=fill_value, | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
| all_headers = lconcat(headers, metric_headers, param_headers, deps_names) | ||||||||||||||||||||||||||||||||||||||||||
| td = TabularData(all_headers, fill_value=fill_value) | ||||||||||||||||||||||||||||||||||||||||||
| for base_rev, experiments in all_experiments.items(): | ||||||||||||||||||||||||||||||||||||||||||
| rows = _collect_rows( | ||||||||||||||||||||||||||||||||||||||||||
| base_rev, | ||||||||||||||||||||||||||||||||||||||||||
| experiments, | ||||||||||||||||||||||||||||||||||||||||||
| all_headers, | ||||||||||||||||||||||||||||||||||||||||||
| metric_headers, | ||||||||||||||||||||||||||||||||||||||||||
| param_headers, | ||||||||||||||||||||||||||||||||||||||||||
| metric_names, | ||||||||||||||||||||||||||||||||||||||||||
| param_names, | ||||||||||||||||||||||||||||||||||||||||||
| deps_names, | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
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.
Would it be possible to just use
TabularData.row_from_dict()here? The parameters are getting complicated here.Uh oh!
There was an error while loading. Please reload this page.
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.
Tried adding a change using
row_from_dictbut it only saves us from passingall_headers.Unfortunately, we still need
metric_headersandparam_headerslater in this function because of the bug being fixed.The overall handling of metrics and params could be simplified but feels out of the scope of this fix.
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.
Makes sense. Thanks.
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.
We should simplify these parameters soon though, as it is getting complicated as
exp showis becoming complex.May get more confusing in the future. Anyway, thanks for looking into it. π