Repository navigation
fix(core/lifelong): correct rounds condition to fix HAS_COMPLETED_INITIAL_TRAINING in standard mode - #573
fix(core/lifelong): correct rounds condition to fix HAS_COMPLETED_INITIAL_TRAINING in standard mode#573g-k-s-03 wants to merge 2 commits into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: g-k-s-03 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Code Review
This pull request adds validation to ensure the aggregation module is present and initialized in federated learning, raising a ValueError if not. It also modifies the condition for checking if initial training has completed in lifelong learning from rounds < 1 to rounds <= 1. However, this change to rounds <= 1 introduces a regression in no-inference and hard-example-mining modes where the first round starts at r=0. A suggestion is provided to conditionally determine the initial training round based on the active mode.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if rounds <= 1: | ||
| os.environ["HAS_COMPLETED_INITIAL_TRAINING"] = 'False' | ||
| else: | ||
| os.environ["HAS_COMPLETED_INITIAL_TRAINING"] = 'True' |
There was a problem hiding this comment.
Changing the condition to rounds <= 1 fixes the issue in standard mode (where the first round starts at r=1), but it introduces a regression in no-inference and hard-example-mining modes. In those modes, the first round starts at r=0 and the second round is r=1. With rounds <= 1, the second round (r=1) will be incorrectly treated as the initial training round (HAS_COMPLETED_INITIAL_TRAINING set to 'False').
To support both loop starting points correctly, we should determine whether it is the initial training round based on the active mode.
| if rounds <= 1: | |
| os.environ["HAS_COMPLETED_INITIAL_TRAINING"] = 'False' | |
| else: | |
| os.environ["HAS_COMPLETED_INITIAL_TRAINING"] = 'True' | |
| mode = (self.model_eval_config or {}).get('model_metric', {}).get('mode') | |
| is_initial = rounds < 1 if mode in ('no-inference', 'hard-example-mining') else rounds <= 1 | |
| if is_initial: | |
| os.environ['HAS_COMPLETED_INITIAL_TRAINING'] = 'False' | |
| else: | |
| os.environ['HAS_COMPLETED_INITIAL_TRAINING'] = 'True' |
There was a problem hiding this comment.
Valid point — updated the fix to be mode-aware. The condition now uses rounds < 1 for no-inference and hard-example-mining modes (preserving original behavior) and rounds <= 1 for standard mode (the actual fix). This avoids the regression you identified
9adcc5f to
f042092
Compare
|
@jaypume The PR description above reflects the initial approach. The actual fix is mode-aware it uses rounds < 1 for no-inference and hard-example-mining modes (preserving original behaviour) and rounds <= 1 for standard mode. See the latest commit for the final implementation |
|
/assign |
There was a problem hiding this comment.
PR Review — #573 Lifelong Initial-Training State
Target: kubeedge/ianvs#573
Reviewed head: 96522f6b14fcfd408f2f9d3c7e94fc1bbde829ce
Base comparison: main@37a9c60a9747af0cfe3170f84249bc349c56e8d5
Recommendation
Accepted as it is.
The latest head correctly distinguishes the zero-based training loops used by no-inference and hard-example-mining from the one-based standard loop. I have two non-blocking follow-up suggestions: add a parameterized regression test and update the PR description so that it reflects the final mode-aware implementation.
Existing Review Boundary
The original one-line rounds <= 1 change was already shown to regress the second round of the two zero-based modes. That problem was identified in the existing Gemini inline review, and the author incorporated the suggested mode-aware implementation in the latest commit.
I am not presenting that existing finding as a new contribution. This review verifies the corrected latest head against the actual mode matrix.
Executed Verification
I executed the real LifelongLearning._train() method from both locked source revisions with a CPU-only fake job. The fake job recorded the value returned by Sedna Context.get_parameters("HAS_COMPLETED_INITIAL_TRAINING") immediately inside job.train().
The test covered the first and next training calls for all three relevant mode conventions:
| Mode | Round | Desired value | main@37a9c60 |
PR head 96522f6 |
|---|---|---|---|---|
no-inference |
0 |
False |
False |
False |
no-inference |
1 |
True |
True |
True |
hard-example-mining |
0 |
False |
False |
False |
hard-example-mining |
1 |
True |
True |
True |
| standard | 1 |
False |
True |
False |
| standard | 2 |
True |
True |
True |
Both verification scripts exited with code 0:
- the main-branch run reproduced the incorrect standard-mode first-round state;
- the PR-head run matched the desired matrix in every tested case.
This confirms that the latest head fixes the reported standard-mode defect without reintroducing the already-reviewed regression in the two zero-based modes.
Source-Level Assessment
The current standard branch calls _train() first with r=1, while no-inference and hard-example-mining begin their initial training with r=0. The latest implementation maps those existing loop conventions correctly:
mode = (self.model_eval_config or {}).get('model_metric', {}).get('mode')
is_initial = rounds < 1 if mode in ('no-inference', 'hard-example-mining') else rounds <= 1The state is established before the Sedna job is built and before job.train() consumes it, so the timing is correct for this target.
Non-Blocking Follow-Ups
1. Add an executable mode matrix
The current diff does not add a regression test. A parameterized Core test should lock in at least these cases:
standard: r=1 -> False, r=2 -> True
no-inference: r=0 -> False, r=1 -> True
hard-example-mining: r=0 -> False, r=1 -> True
The assertion should observe the value at job.train(), rather than only testing a duplicated helper expression.
2. Update the PR description
The PR description still explains the earlier unconditional rounds <= 1 approach and states that the zero-based modes are unaffected. The latest head no longer uses that implementation. Updating the description and test section would make the final review history unambiguous.
Verification Boundary
Executed:
- real Ianvs Core
_train()from locked main and PR checkouts; - Sedna environment lookup;
- CPU-only fake job and data object;
- six mode/round cases;
- both scripts completed with exit code
0.
Not Executed: full GPU/model training, external datasets, complete end-to-end Lifelong Example benchmarks, pushed CI, or production deployment.
Evidence Attachment
The GIF is an animated replay generated from the saved execution logs; the raw text logs and exit codes remain the source of truth.
The screenshot was visually verified for legibility and contains the saved main-versus-PR mode matrix. The underlying text logs and source trace were also preserved for reproducibility.
|
Reviewed against Evidence that this fix is required, from running a different PRWhile reviewing #645 I checked it out into an isolated worktree and ran Sedna took the So this is the blocker that remains once the module-representation fix is in place. That is a On the mode-aware revisionThe Two small notes
Verification boundaryExecuted: the #645 run described above, on |
|
Reviewing this as part of LFX 2026 Term 3 pretest bonus coverage (full review in Discussion #964). The fix correctly distinguishes standard mode's one-based loop from the zero-based no-inference/hard-example-mining modes — I know an earlier naive version of this (rounds <= 1) would've regressed the zero-based modes, and the mode-aware version here avoids that. Worth double-checking this holds across all three modes in testing, not just standard mode, since that's the case that originally motivated the fix. (Static/traced review — haven't executed the mode matrix myself.) |
|
@jaypume this is ready for your approval when you get a chance. |
|
/assign @jaypume Description updated to lead with the final mode-aware implementation, per Re @suhaan-24's note on overlap with #441: that PR fixes the same flag at the |
|
@jaypume, any update on whether this pr is ok or do I need to change anything? |
_train told Sedna that initial training had already happened unless the round number was below 1. The default mode trains first in round 1, so Sedna took the update path on the very first call and failed with "index.pkl not exists!". The condition is now mode-aware: the default mode treats round 1 as initial training, and no-inference and hard-example-mining keep treating round 0 as initial training. The mode-aware condition follows kubeedge#573 by g-k-s-03. Part of stage S3 of the Phase IV proposal (kubeedge#1000). Adds tests/core/ test_lifelong_paradigm.py: 7 preservation tests and 1 change test. Refs: kubeedge#572, kubeedge#573 Signed-off-by: Suhaan <suhaanrk73@gmail.com>
…TIAL_TRAINING in standard mode, Issue 572 Signed-off-by: g-k-s-03 <govindsingh97704@gmail.com>
…L_TRAINING Signed-off-by: g-k-s-03 <govindsingh97704@gmail.com>
96522f6 to
3f0d7d9
Compare
Description
In standard benchmark mode (
elif mode != 'multi-inference'), thetraining loop starts at
r=1. The_train()method usesrounds < 1to determine whether initial training has completed. Since
1 < 1isalways
False,HAS_COMPLETED_INITIAL_TRAININGis set to'True'on the very first call — before any training has occurred.
This is a silent correctness bug. Every lifelong learning algorithm
receives an incorrect signal on the first training round, causing it
to either attempt loading a non-existent checkpoint or skip
knowledge-base initialization. Benchmark metrics (BWT, FWT, Matrix)
are silently corrupted as a result.
Root Cause
The condition
rounds < 1only evaluates toTruewhenr=0. Thestandard mode loop starts at
r=1, so the condition is neverTrueon the first call.
Fix (final, mode-aware)
An initial one-line change (
rounds <= 1unconditionally) was shown inreview to regress the zero-based
no-inferenceandhard-example-miningmodes, whose first round starts at
r=0rather thanr=1.The final implementation determines the correct predicate per mode:
This uses
rounds < 1(original, preserved behavior) for the twozero-based modes, and
rounds <= 1(the actual fix) for standard mode,which starts at
r=1.Files Changed
core/testcasecontroller/algorithm/paradigm/lifelong_learning/lifelong_learning.pyTesting
Verified by reviewer zjr060424-lab against the full mode matrix
(standard, no-inference, hard-example-mining), confirming the fix
resolves the standard-mode defect without regressing the zero-based
modes. See review discussion below for details.
Fixes #572