Fix evaluator-accuracy and confusion-matrix misalignment when a rating fails to parse - #10
Open
arthi-arumugam-git wants to merge 2 commits into
Conversation
The evaluator-accuracy metrics and the confusion matrix index each user's prediction by their position within their conspiracy group, but they read that position out of filtered_ratings_by_turn, which has had non-numeric ratings (the "Format error" sentinel from extract_rating) removed. Dropping an entry shrinks that list and shifts every later user, so predictions get scored against the wrong users' intended degrees and the trailing users fall off the end. With one unparseable rating, a perfectly accurate evaluator can be reported as 0.0 accuracy. Add get_aligned_prediction(), which reads the raw (unfiltered) ratings so a user's position indexes their own prediction, and returns None for a missing or non-numeric rating so callers skip it in place. Use it for both the accuracy metrics and the confusion matrix. Add tests covering the format-error case.
The confusion matrix written to JSON by calc_metrics was fixed to read the raw ratings, but create_visualizations builds the confusion matrix it renders to persuasion_degree_confusion_matrix.png separately, and that copy still indexed into filtered_ratings_by_turn by the user's position within their conspiracy group. Non-numeric ratings have already been dropped from that list, so one "Format error" shrinks the group and shifts every later user, and the saved heatmap plots predictions against the wrong users' true persuasion degrees while the trailing users fall off the end entirely. The JSON and the PNG could therefore disagree with each other after the earlier fix. Reuse get_aligned_prediction here so the plotted matrix is built exactly the way the metrics matrix is. This also resolves the pre-existing "todo: fix off by one error here" comment on that block, so it is removed. The turn index is unaffected: filtered_ratings_by_turn and ratings_by_turn always have one entry per turn, so last_turn_idx still points at the final turn. Add tests that assert on the array handed to imshow, so they cover the rendered plot rather than the metrics path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
calc_metricsscores the evaluator's predicted persuasion degrees against the intended ones, per user. Both the accuracy metrics (evaluator_accuracy_metrics.json) and the confusion matrix (all_metrics.json) locate a user's prediction by their position within their conspiracy group, but they read that position out offiltered_ratings_by_turn, which has had non-numeric ratings removed.extract_ratingreturns the string"Format error"whenever the judge's output cannot be parsed as... | N. Filtering that out shrinks the group's rating list and shifts every later user's position by one, so:position >= len(...)and are silently dropped.The result is wrong
overall_accuracy_by_turn,mean_absolute_error_by_turn,mean_squared_error_by_turn,degree_specific_accuracy, and confusion matrices, with nothing raised.Reproduction
Three users share one conspiracy with true degrees
[0, 1, 2]. The evaluator predicts every parseable one correctly, but user 0's rating is a"Format error":A perfectly accurate evaluator is reported as completely inaccurate: after filtering, user 0 (true 0) reads
[1, 2][0] = 1, user 1 (true 1) reads[1, 2][1] = 2, and user 2 falls off the end. Both remaining users are scored wrong, so accuracy is0/2and MAE is2/2.Fix
Add
get_aligned_prediction(), which reads the raw (unfiltered)ratings_by_turnso a user's position indexes their own prediction, and returnsNonefor a missing or non-numeric rating so callers skip it in place instead of compacting the list. Both the accuracy loop and the confusion-matrix loop use it. Per-title averages and distributions keep usingfiltered_ratings_by_turn, since those are order-independent.The plotted confusion matrix had the same bug
The confusion matrix written to
evaluator_accuracy_metrics.jsonand the one rendered topersuasion_degree_confusion_matrix.pngare built by two separate pieces of code. Fixing only the metrics one would have left the PNG misaligned and made the two artifacts disagree with each other, so this also updatescreate_visualizations.That block indexed
filtered_ratings_by_turnby each user's position within their conspiracy group, exactly as the metrics code did, with the same consequences. It now calls the sameget_aligned_predictionhelper.This resolves the pre-existing
# todo: fix off by one error herecomment on that block, which is removed. The turn index was already correct and is unchanged:ratings_by_turnandfiltered_ratings_by_turnalways have one entry per turn, solast_turn_idxstill selects the final turn and the "(Final Turn)" title stays accurate.Tests
tests/test_calc_metrics.pycovers the format-error case at both the helper and full-calc_metricslevel, plus an all-numeric control.tests/test_visualizations.pyis new and covers the rendered plot rather than the metrics path: it monkeypatchesAxes.imshowand asserts on the array actually handed to the plot.test_plotted_confusion_matrix_skips_format_errors_without_shiftingtest_plotted_confusion_matrix_all_numeric_unchangedBoth fail without the visualization change, with the mass landing off the diagonal. Five tests pass together:
black,isort(--profile black), andflake8(--ignore=E203,E704,E501,W503) are clean, run with the args from.pre-commit-config.yaml.mypyreports no issues on the touched files under--python-version 3.13. Under the repo's configuredpython_version = 3.11mypy fails inside numpy's own stubs (numpy/__init__.pyi:737: Type statement is only supported in Python 3.12 and greater); that reproduces on files this PR does not touch, so it looks like a local numpy version issue rather than anything here.tests/test_main.pywas not run, since it importsgenerate_conversationsand pulls in torch.Related sites, deliberately not in this PR
While tracing this I found the same root cause in about ten other places, and I would rather name them than quietly widen the diff:
src/utils/utils.py,print_results_to_terminal: zips filtered ratings positionally againstrefusals_by_turn, which is built in raw user order, so refusal flags get attributed to the wrong users and the last user's refusal is never checked. This is a ratings-vs-refusals pairing rather than ratings-vs-users, and the loop has nouser_idx, soget_aligned_predictiondoes not drop in cleanly.visualizations.py, plusmain.py(the logviz per-sample rating) andgenerate_persuasion_degree_plots.py, use the same positional pattern. Most are the refusals variant above.Fixing all of them turns a focused bugfix into a repo-wide refactor that is hard to review. Happy to open a follow-up issue, or to fold them in here if you would prefer one pass.