Generalization Investigation: Position Bias, the x=10 Dead Zone, and the Background-Dependency Finding
The prequel to the background-diversity experiment โ three sessions (Aug 17โ20, 2026) of testing, dead-end theories, one real fix, and the finding that actually mattered
1. Starting Point: Position Bias and Rebalancing
A severe position bias was identified after extending the original single-position dataset unevenly (36 vs. ~6 episodes for different positions) โ a trained model consistently drifted back toward the over-represented position, even in rollouts where it had correctly located the object elsewhere. Fixed by rebuilding a fully balanced, position/orientation-varied dataset: 5 positions ร 3 orientations ร repeats, 120 episodes total (~24 per position), with the original single-position episodes deliberately excluded rather than merged in. This established so101_pickplace_v10_balanced as the new baseline checkpoint for everything that follows.
2. Model Lineage at This Point
Two active branches, both transfer-learned from v10_balanced, deliberately kept separate to avoid mixing grasping techniques in one dataset:
- Branch A (top-down grasp technique):
v10_balancedโv12_boosted(P4/P5 boost) โv14_o1fixed(O1 orientation boost) โ the more mature, most-tested branch - Branch B (side-approach/wide-grip technique):
v15_sideapproachโ fresh 30-episode set, same 5-position/3-orientation structure
Setup reference (for continuity)
- Follower arm:
/dev/tty.usbserial-11320ยท Leader arm:/dev/tty.usbserial-11310 - Main camera: index 0, 640ร480 ยท Gripper camera: index 1, 320ร240
- Always include
"fourcc": "MJPG"in camera configs โ recurring garbled-frame bug otherwise - Workspace: cutting mat with grid, target box at (25,10), positions tested on a roughly 0โ27 (x) ร 0โ20 (y) coordinate grid
- Physical reach limits found: y=5 is near the edge; corners around (0,10), (10,0), (10,20) are outside reliable reach/camera view entirely
- Confirmed via source inspection: vanilla ACT has no language-conditioning pathway โ the
--taskstring passed to rollout/training is never actually fed to the model. Prompt text is cosmetic only for this architecture.
3. Open Findings as of Aug 17
- Orientation weakness (O1/straight, 0ยฐ): consistently underperforms angled grasps (30ยฐ/45ยฐ) across three separate models (v10, v14, v15), despite different fixes attempted (more data, targeted boosting, a different grip technique). Suspected genuine physical/geometric grasp-margin issue with the elongated object, not a data problem.
- x=10 "dead zone": positions along x=10 underperform neighboring x=5/x=15 across multiple y-values, including trained position P3=(10,15). Manually checked and ruled out as a kinematic/joint-limit issue (pose looks normal at that column). Cause unexplained at this point.
- "Origin-drift" hypothesis: a small, consistent movement toward the origin position observed during final grasp approach. Theory: a persistent low-level model bias that only becomes failure-critical in low-margin cases (straight orientation, and possibly the x=10 zone) โ not yet confirmed via direct rollout video review.
- Overfitting check on v15: trained for 7+ epochs on only 30 episodes (higher than usual). Tested and does not show catastrophic memorization โ handles multiple positions reasonably โ but the O1 weakness persists even here, suggesting it isn't simply a data-volume artifact.
4. Day 1 (Aug 18) โ SmolVLA RunPod Pipeline Validation
Before committing to any local GPU hardware, the SmolVLA training pipeline was validated cheaply on rented cloud compute first โ a deliberate sequencing choice, not an afterthought.
- RunPod instance: RTX A6000, 48GB VRAM, $0.54/hour (an RTX 3090 instance wasn't available at the time)
- Fresh LeRobot install required three separate extras:
".[feetech]", then".[dataset]", then".[smolvla]"โ same incremental pattern as the original Mac setup - Transferred the
v4-matdataset (30 episodes, ~326MB) viascpโ one stall/resume, completed fine
--policy.use_amp = False) and a smaller batch size (8, not 64) was used. The 1000-step run was cancelled once the true cost became clear (would have been 8โ10 hours, not a quick test).Reran capped at 100 steps instead โ completed in 40m46s (~24.5s/step average once warmed up). Correct reference command for the installed version (lerobot 0.6.2, confirmed via --help rather than docs, which vary by version):
lerobot-train \
--dataset.repo_id=<repo_id> \
--dataset.root=<local_path_to_dataset> \
--policy.type=smolvla \
--policy.pretrained_path=lerobot/smolvla_base \
--output_dir=<output_dir> \
--job_name=<name> \
--policy.device=cuda \
--steps=100 \
--batch_size=8 \
--policy.push_to_hub=false
Result: pipeline validated end-to-end โ dataset loads correctly from a local path, pretrained SmolVLA base downloads and initializes, training runs without error, checkpoint saves correctly. This was not a meaningfully trained model (100 steps, single-position data) โ pure plumbing validation. Checkpoint (~1.1GB) downloaded locally before pod termination. Total cost: ~$0.50โ0.70 for the whole session.
5. Day 2 (Aug 19) โ v17 (x10-fix) Training & Testing
Recorded 12 targeted episodes at the x=10 column (y=7,10,12,15 ร 3 orientations), merged with v15-sideapproach โ v17-x10fixed (42 episodes total). Transfer-learned from the v15_sideapproach checkpoint, 15,000 steps.
Training took 8h41m โ roughly double the ~4h estimate. Per-step timing was stable (~1.3s/step) until step ~13,600, then degraded sharply (up to 2+ hours for 200 steps at one point) before recovering toward the end โ likely something competing for Mac resources overnight (background process, thermal), not a training issue itself. Final loss 0.094 after ~5 epochs โ good convergence.
5.1 x=10 dead zone: confirmed fixed
| Position | Result |
|---|---|
| (10,10,30ยฐ) | 2/3 |
| (10,12,45ยฐ) | 2/3 |
| (10,15,0ยฐ) | 3/3 |
| (10,15,30ยฐ) | 2/3 |
| (10,15,45ยฐ) | 2/3 |
P5 sanity check (old trained position): O1: 1/3, O2: 2/3, O3: 2/2 โ O1 continues to underperform, consistent with every prior model in this lineage (v10, v14, v15, v17).
5.2 O1 gripper-rotation investigation โ four theories, no clean answer
The gripper was observed visibly rotating slightly during 0ยฐ-orientation approaches, specifically causing off-center grasps. Investigated as a possible root cause of the persistent O1 weakness:
- Wrist-roll wraparound theory โ checked via calibration file + sampled training data
wrist_rollvalues. Calibration range is the full raw 0โ4095 range (expected for a continuously-rotating joint), but actual recorded values cluster tightly around -34ยฐ to +68ยฐ, nowhere near a wraparound boundary. Not supported by data. - Live observation: the rotation appears specifically at P1/P2 (previously good-performing positions) about 5 seconds into descent, but does not appear at P5 (a weaker-performing position) โ doesn't cleanly correlate with the overall O1 weakness pattern.
Conclusion: four theories now tested overall (kinematic strain, camera occlusion, wrist-roll wraparound, position-correlated rotation), with no single unifying explanation found. Decision made to stop chasing this for now and log it as an open finding rather than continuing to invest time without a clear next hypothesis.
5.3 Camera brightness confound (resolved)
After the white-background test below, a "back on mat" retest showed apparently degraded performance. A brightness check found the camera reading 85 โ well below the healthy 100โ180 range โ meaning it hadn't fully re-adjusted exposure after the paper swap. A second check after a longer settle time showed 135, confirming full recovery.
Lesson: always re-verify camera brightness after any background swap before trusting rollout results โ a confound this simple could easily be mistaken for a real regression.
5.4 White background test โ the major finding
v17-x10fixed was tested on plain white/brown paper โ never seen in any training data across the entire model lineage.
Working hypothesis: the grid-patterned cutting mat may function as an implicit coordinate system the model has learned to rely on for position estimation, rather than learning to localize the object independently of its background. This would explain several otherwise-puzzling observations at once:
- Why the mat enabled such strong position-precision improvements throughout the project
- Why the model fails so completely without it, despite the object remaining clearly visible
- Why repeated mat-based training reinforcement never improved background generalization โ every fix reinforced the same underlying dependency rather than resolving it
Flagged at the time as the most significant unresolved finding of the whole project, worth treating as a priority discussion topic separate from the position-specific tuning work that had occupied most of this session's effort.
5.5 Minor observation, not prioritized
For positions with x>14 (near the sparse/far end of the trained range), the first grasp attempt often slightly undershoots (e.g. reaches ~12โ13 instead of 14โ15), but the second attempt self-corrects to roughly the right spot. Interpreted as a mild, self-correcting closed-loop behavior rather than a hard failure โ logged, not investigated further at the time.
6. Infrastructure & Housekeeping (Aug 20)
- Server IP changed to
192.168.2.42(was192.168.11.153) - Archive completed: superseded datasets (
v15-sideapproach,v16-x10boost,test-pickplace) and checkpoints (v10_balanced,v12_boosted) moved tostorage1/training/lerobot/on the server โ confirmed 10GB+10GB transferred and verified before local deletion. Datasets/checkpoints still active locally at this point:v14-o1fixed,v17-x10fixed,v15_sideapproach. - New PC decision made โ after the RunPod validation above confirmed the pipeline and gave a real sense of compute requirements, an initial configuration was settled on around this date. (The final ordered spec evolved slightly further before purchase โ see the roadmap's Hardware Notes section for the version actually ordered.) The sequencing itself is the point worth preserving: validate cheaply on rented compute first, buy hardware only once the actual requirement is known empirically, not guessed.
- LeKiwi: STS3215 servos arrived, 3D-printed parts completed by a friend's engineering team; assembly not yet started at this point.
7. What This Motivated
The white-background finding (ยง5.4) is the direct origin of the background-diversity experiment (so101_bgdiv_v1). The planned experiment at this stage was intentionally scoped small โ 5 backgrounds, 2 positions each, 3 orientations, 30 episodes total โ deliberately kept testable in a single session rather than attempting a full factorial design immediately. It was not yet decided at this point whether to train from scratch, transfer-learn from v17-x10fixed, or treat it as a fully separate branch.
The experiment that actually ran ended up considerably larger than this initial plan (5 positions ร 4 orientations ร 3 reps = 300 total episodes, trained from scratch) โ see the full report for what changed and why, and for the results.