Skip to content

fix: vision/audio argv builders silently drop or duplicate transform flags - #30

Merged
Adithya-Thonse merged 2 commits into
TexasInstruments:mainfrom
musicalplatypus:pr/vision-audio-argv-builder-bugs
Aug 5, 2026
Merged

fix: vision/audio argv builders silently drop or duplicate transform flags#30
Adithya-Thonse merged 2 commits into
TexasInstruments:mainfrom
musicalplatypus:pr/vision-audio-argv-builder-bugs

Conversation

@musicalplatypus

Copy link
Copy Markdown
Contributor

Summary

Two independent bugs in the vision/audio ai_modules' train/test argv builders — both variations of the same underlying defect: the train-time and test-time argv construction for the same parameter disagreeing with each other.

image_base.py: train/test disagree on data_proc_transforms's wire format

Train argv rendered it through an f-string (stringified list, e.g. "['BINARIZE']"), while test argv passed the real list object.

prepare_transforms() (tinyml-tinyverse's train_base.py) only combines data_proc_transforms into args.transforms when isinstance(args.data_proc_transforms, list) is true, with no else branch — so the stringified form silently skipped it during training while testing still applied it. Pure train/test skew for anyone customizing this parameter, with no error or warning.

timeseries_base.py already passes the raw list on both sides correctly; image_base.py's train side now matches it. feat_ext_transform/augmentation_transform don't have this defect — they're parsed via _normalize_transform_list's literal_eval fallback, which tolerates both string and list forms — and were left untouched (not a real bug, no need to change working code).

audio_base.py: --data-proc-transforms/--feat-ext-transform declared twice

Both the train and test argv builders declared these two flags twice: once correctly as a raw list, and again later as a stringified f-string. argparse's last-occurrence-wins semantics meant the later, stringified declaration always won — making the earlier, correct declaration dead code. Same underlying defect as above, just duplicated instead of split across two methods.

Removed the dead duplicate declarations in both _build_common_train_argv and _build_common_test_argv, keeping the single correct raw-list version each already had.

Verification

Unit tests against the argv-building methods directly (constructed via unittest.mock.MagicMock for self — these methods only read self.params, no full ModelRunner instance needed). All 4 tests fail on the unmodified code with the exact symptoms described above (stringified list where a real list was expected; --data-proc-transforms appearing twice in the argv) and pass after the fix.

🤖 Generated with Claude Code

t5fkg8d44d-beep and others added 2 commits August 4, 2026 18:34
…flags

Two independent bugs in the vision/audio ai_modules' train/test argv builders:

1. image_base.py's train argv rendered data_proc_transforms through an
   f-string (stringified list, e.g. "['BINARIZE']"), while test argv passed
   the real list object -- the two builders disagreed on the wire format for
   the same parameter. prepare_transforms() (tinyml-tinyverse's
   train_base.py) only combines data_proc_transforms into args.transforms
   when isinstance(args.data_proc_transforms, list) is true, with no else
   branch, so the stringified form silently skipped it during training while
   testing still applied it -- pure train/test skew for anyone customizing
   this parameter, with no error or warning. timeseries_base.py already
   passes the raw list on both sides correctly; image_base.py's train side
   now matches it. feat_ext_transform/augmentation_transform don't have this
   defect (parsed via _normalize_transform_list's literal_eval fallback,
   which tolerates both forms) and were left untouched.

2. audio_base.py's train and test argv builders each declared
   --data-proc-transforms/--feat-ext-transform twice: once correctly as a
   raw list, and again later as a stringified f-string. argparse's
   last-occurrence-wins semantics meant the later, stringified declaration
   always won, making the earlier, correct one dead code -- the same
   underlying defect as (1), just duplicated instead of split across two
   methods. Removed the dead duplicate declarations in both methods,
   keeping the single correct raw-list version each already had.

Verified with unit tests against the argv-building methods directly (no
full ModelRunner instance needed -- these only read self.params). All 4
tests fail on the unmodified code with the exact symptoms described above
(stringified list where a real list was expected; --data-proc-transforms
appearing twice in the argv) and pass after the fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
An independent Opus peer review caught that fixing --data-proc-transforms
(making it a raw list, matching test-time argv) introduced a new crash:
prepare_transforms() (tinyml-tinyverse/references/common/train_base.py)
does

    args.transforms = args.data_proc_transforms + args.feat_ext_transform

whenever args.data_proc_transforms is a list. image_base.py's train argv
builder still stringified --feat-ext-transform (and
--augmentation-transform), so once --data-proc-transforms became a real
list, this became `list + str`, raising:

    TypeError: can only concatenate list (not "str") to list

on every image-classification training run (the vision default for
data_proc_transforms is [], and even an empty list still enters this
branch, so this wasn't conditional on the user setting anything).

An earlier comment in this file claimed feat_ext_transform "doesn't have
this defect: it's parsed via _normalize_transform_list's literal_eval
fallback, which tolerates both string and list forms" -- that's true of a
different consumer (image_dataset.py's Dataset construction, later in the
pipeline) but not of prepare_transforms(), which runs first and reads
feat_ext_transform directly with no such tolerance. Fixed by passing
--feat-ext-transform and --augmentation-transform as raw lists too,
matching _build_common_test_argv (which already did this) and
timeseries_base.py's reference implementation.

Adds a test that drives the REAL prepare_transforms() against the argv
builder's actual output, rather than only asserting argv shape (which is
exactly why the previous test suite didn't catch this -- MagicMock-based
shape checks never fed the argv through the function that actually
crashes). Verified to fail on the pre-this-commit code with the exact
TypeError above and pass post-fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@musicalplatypus

Copy link
Copy Markdown
Contributor Author

An independent peer review caught that this PR's own fix broke every image-classification training run. Pushed a follow-up commit (72196d6):

Making --data-proc-transforms a raw list (correctly, per the original fix) exposed a latent issue: prepare_transforms() in tinyml-tinyverse does args.data_proc_transforms + args.feat_ext_transform whenever data_proc_transforms is a list. --feat-ext-transform (and --augmentation-transform) were still stringified in the train argv builder, so this became list + str, raising TypeError: can only concatenate list (not "str") to list on every training run -- not conditional on any user setting, since the default data_proc_transforms=[] still enters that branch.

My earlier comment claiming feat_ext_transform "tolerates both string and list forms via _normalize_transform_list" was true of a different consumer (image_dataset.py's Dataset construction, later in the pipeline) but not of prepare_transforms(), which reads it directly with no such tolerance and runs first.

Fixed by passing both flags as raw lists too, matching _build_common_test_argv (already correct) and timeseries_base.py.

Added a test that drives the real prepare_transforms() against the argv builder's actual output rather than only checking argv shape -- confirmed to fail pre-fix with the exact TypeError above and pass post-fix.

@Adithya-Thonse
Adithya-Thonse merged commit 56e77dc into TexasInstruments:main Aug 5, 2026
0 of 3 checks passed
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