Skip to content

Commit b303efb

Browse files
authored
#1063 fix: Training parameters slider was not working properly. (#1071)
1 parent 9f0c439 commit b303efb

File tree

15 files changed

+539
-100
lines changed

15 files changed

+539
-100
lines changed

web_ui/src/pages/project-details/components/project-models/train-model-dialog/advanced-settings/advanced-settings.component.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ interface AdvancedSettingsProps {
3939
) => void;
4040
trainFromScratch: boolean;
4141
onTrainFromScratchChange: (trainFromScratch: boolean) => void;
42+
defaultTrainingConfiguration: TrainingConfiguration;
4243
}
4344

4445
interface TabProps {
@@ -58,6 +59,7 @@ export const AdvancedSettings: FC<AdvancedSettingsProps> = ({
5859
onTrainFromScratchChange,
5960
trainingConfiguration,
6061
onUpdateTrainingConfiguration,
62+
defaultTrainingConfiguration,
6163
}) => {
6264
const TABS: TabProps[] = [
6365
{
@@ -78,13 +80,15 @@ export const AdvancedSettings: FC<AdvancedSettingsProps> = ({
7880
hasSupportedModels={hasSupportedModels}
7981
trainingConfiguration={trainingConfiguration}
8082
onUpdateTrainingConfiguration={onUpdateTrainingConfiguration}
83+
defaultTrainingConfiguration={defaultTrainingConfiguration}
8184
/>
8285
),
8386
},
8487
{
8588
name: 'Training',
8689
children: (
8790
<Training
91+
defaultTrainingConfiguration={defaultTrainingConfiguration}
8892
trainFromScratch={trainFromScratch}
8993
onTrainFromScratchChange={onTrainFromScratchChange}
9094
isReshufflingSubsetsEnabled={isReshufflingSubsetsEnabled}

web_ui/src/pages/project-details/components/project-models/train-model-dialog/advanced-settings/data-management/data-management.component.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import { TrainingSubsets } from './training-subsets/training-subsets.component';
1414

1515
interface DataManagementProps {
1616
hasSupportedModels: boolean;
17+
18+
defaultTrainingConfiguration: TrainingConfiguration;
19+
1720
trainingConfiguration: TrainingConfiguration;
1821
onUpdateTrainingConfiguration: (
1922
updateFunction: (config: TrainingConfiguration | undefined) => TrainingConfiguration | undefined
@@ -32,6 +35,7 @@ export const DataManagement: FC<DataManagementProps> = ({
3235
hasSupportedModels,
3336
trainingConfiguration,
3437
onUpdateTrainingConfiguration,
38+
defaultTrainingConfiguration,
3539
}) => {
3640
const augmentationParameters = getAugmentationParameters(trainingConfiguration);
3741
const subsetSplitParameters = trainingConfiguration.datasetPreparation.subsetSplit;
@@ -44,6 +48,7 @@ export const DataManagement: FC<DataManagementProps> = ({
4448
{!isEmpty(subsetSplitParameters) && (
4549
<TrainingSubsets
4650
hasSupportedModels={hasSupportedModels}
51+
defaultSubsetParameters={defaultTrainingConfiguration.datasetPreparation.subsetSplit}
4752
subsetsParameters={trainingConfiguration.datasetPreparation.subsetSplit}
4853
onUpdateTrainingConfiguration={onUpdateTrainingConfiguration}
4954
/>

web_ui/src/pages/project-details/components/project-models/train-model-dialog/advanced-settings/data-management/training-subsets/training-subsets.component.tsx

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
// Copyright (C) 2022-2025 Intel Corporation
22
// LIMITED EDGE SOFTWARE DISTRIBUTION LICENSE
33

4-
import { FC, useRef, useState } from 'react';
4+
import { FC, useState } from 'react';
55

66
import { Content, Flex, Grid, Heading, InlineAlert, minmax, Text, View } from '@geti/ui';
77
import { isEqual } from 'lodash-es';
88

99
import {
1010
ConfigurationParameter,
11-
NumberParameter,
1211
TrainingConfiguration,
1312
} from '../../../../../../../../core/configurable-parameters/services/configuration.interface';
1413
import { Accordion } from '../../ui/accordion/accordion.component';
1514
import { ResetButton } from '../../ui/reset-button.component';
1615
import { SubsetsDistributionSlider } from './subsets-distribution-slider/subsets-distribution-slider.component';
17-
import { areSubsetsSizesValid, getSubsetsSizes, MAX_RATIO_VALUE } from './utils';
16+
import {
17+
areSubsetsSizesValid,
18+
getSubsets,
19+
getSubsetsSizes,
20+
MAX_RATIO_VALUE,
21+
TEST_SUBSET_KEY,
22+
TRAINING_SUBSET_KEY,
23+
VALIDATION_SUBSET_KEY,
24+
} from './utils';
1825

1926
import styles from './training-subsets.module.scss';
2027

@@ -71,7 +78,6 @@ interface SubsetsDistributionProps {
7178
onSubsetsDistributionChange: (values: number[]) => void;
7279
onSubsetsDistributionChangeEnd: (values: number[]) => void;
7380
onSubsetsDistributionReset: () => void;
74-
subsetParameters: SubsetsParameters;
7581
}
7682

7783
const SubsetsDistribution: FC<SubsetsDistributionProps> = ({
@@ -82,24 +88,15 @@ const SubsetsDistribution: FC<SubsetsDistributionProps> = ({
8288
onSubsetsDistributionChange,
8389
onSubsetsDistributionChangeEnd,
8490
onSubsetsDistributionReset,
85-
subsetParameters,
8691
}) => {
8792
const handleSubsetDistributionChange = (values: number[] | number): void => {
8893
if (Array.isArray(values)) {
89-
if (!areSubsetsSizesValid(subsetParameters, values)) {
90-
return;
91-
}
92-
9394
onSubsetsDistributionChange(values);
9495
}
9596
};
9697

9798
const handleSubsetDistributionChangeEnd = (values: number[] | number): void => {
9899
if (Array.isArray(values)) {
99-
if (!areSubsetsSizesValid(subsetParameters, values)) {
100-
return;
101-
}
102-
103100
onSubsetsDistributionChangeEnd(values);
104101
}
105102
};
@@ -141,40 +138,24 @@ type SubsetsParameters = TrainingConfiguration['datasetPreparation']['subsetSpli
141138

142139
interface TrainingSubsetsProps {
143140
hasSupportedModels: boolean;
141+
142+
defaultSubsetParameters: SubsetsParameters;
143+
144144
subsetsParameters: SubsetsParameters;
145145
onUpdateTrainingConfiguration: (
146146
updateFunction: (config: TrainingConfiguration | undefined) => TrainingConfiguration | undefined
147147
) => void;
148148
}
149149

150-
const TEST_SUBSET_KEY = 'test';
151-
const VALIDATION_SUBSET_KEY = 'validation';
152-
const TRAINING_SUBSET_KEY = 'training';
153-
154-
const getSubsets = (subsetsParameters: SubsetsParameters) => {
155-
const validationSubset = subsetsParameters.find(
156-
(parameter) => parameter.key === VALIDATION_SUBSET_KEY
157-
) as NumberParameter;
158-
const trainingSubset = subsetsParameters.find(
159-
(parameter) => parameter.key === TRAINING_SUBSET_KEY
160-
) as NumberParameter;
161-
162-
return {
163-
trainingSubset,
164-
validationSubset,
165-
};
166-
};
167-
168150
const TrainingSubsetsUnavailable = () => {
169151
return (
170152
<InlineAlert variant={'notice'}>
171-
<Heading>Training subsets configuration unavailable</Heading>
153+
<Heading>Invalid training subsets configuration</Heading>
172154
<Content>
173-
The training, validation, and testing subsets are currently unavailable because the project does not
174-
contain enough media items to support a proper split.
155+
Training subsets do not contain enough media items to support a configurable split between training,
156+
validation, and testing subsets.
175157
<br />
176-
To enable subset configuration, please add more media items so that each subset contains at least one
177-
item.
158+
Please add more media items to ensure each subset contains at least one item.
178159
</Content>
179160
</InlineAlert>
180161
);
@@ -196,12 +177,13 @@ const TrainingSubsetsChangedDistributionWarning = () => {
196177

197178
export const TrainingSubsets: FC<TrainingSubsetsProps> = ({
198179
hasSupportedModels,
180+
defaultSubsetParameters,
199181
subsetsParameters,
200182
onUpdateTrainingConfiguration,
201183
}) => {
202184
const { trainingSubset, validationSubset } = getSubsets(subsetsParameters);
203185

204-
const prevSubsetParameters = useRef(subsetsParameters);
186+
const areTrainingSubsetParametersChanged = !isEqual(defaultSubsetParameters, subsetsParameters);
205187

206188
const [subsetsDistribution, setSubsetsDistribution] = useState<number[]>([
207189
trainingSubset.value,
@@ -274,9 +256,8 @@ export const TrainingSubsets: FC<TrainingSubsetsProps> = ({
274256
testSubsetRatio
275257
);
276258

277-
const subsetsSizesValid = areSubsetsSizesValid(subsetsParameters, subsetsDistribution);
278-
const isChangedDistributionWarningVisible =
279-
hasSupportedModels && !isEqual(prevSubsetParameters.current, subsetsParameters);
259+
const subsetsSizesInvalid = areTrainingSubsetParametersChanged && !areSubsetsSizesValid(subsetsParameters);
260+
const isChangedDistributionWarningVisible = hasSupportedModels && areTrainingSubsetParametersChanged;
280261

281262
return (
282263
<Accordion>
@@ -295,9 +276,8 @@ export const TrainingSubsets: FC<TrainingSubsetsProps> = ({
295276
Each subset must have at least one media item.
296277
</Accordion.Description>
297278
<Accordion.Divider marginY={'size-250'} />
298-
<View UNSAFE_className={subsetsSizesValid ? undefined : styles.disabled}>
279+
<View>
299280
<SubsetsDistribution
300-
subsetParameters={subsetsParameters}
301281
subsetsDistribution={subsetsDistribution}
302282
onSubsetsDistributionChange={setSubsetsDistribution}
303283
testSubsetSize={testSubsetSize}
@@ -309,7 +289,7 @@ export const TrainingSubsets: FC<TrainingSubsetsProps> = ({
309289
</View>
310290

311291
<Flex direction={'column'} gap={'size-200'} marginTop={'size-200'}>
312-
{!subsetsSizesValid && <TrainingSubsetsUnavailable />}
292+
{subsetsSizesInvalid && <TrainingSubsetsUnavailable />}
313293
{isChangedDistributionWarningVisible && <TrainingSubsetsChangedDistributionWarning />}
314294
</Flex>
315295
</Accordion.Content>

web_ui/src/pages/project-details/components/project-models/train-model-dialog/advanced-settings/data-management/training-subsets/training-subsets.module.scss

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,3 @@
1111
.totalStats {
1212
font-weight: var(--spectrum-global-font-weight-bold);
1313
}
14-
15-
.disabled {
16-
pointer-events: none;
17-
opacity: 0.5;
18-
}

web_ui/src/pages/project-details/components/project-models/train-model-dialog/advanced-settings/data-management/training-subsets/training-subsets.test.tsx

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ describe('TrainingSubsets', () => {
136136
<TrainingSubsets
137137
hasSupportedModels={hasSupportedModels}
138138
subsetsParameters={trainingConfiguration?.datasetPreparation.subsetSplit ?? subsetParameters}
139+
defaultSubsetParameters={subsetParameters}
139140
onUpdateTrainingConfiguration={handleUpdateTrainingConfiguration}
140141
/>
141142
);
@@ -203,26 +204,6 @@ describe('TrainingSubsets', () => {
203204
});
204205
});
205206

206-
it('ensures that all subsets remain non-empty when updating subset sizes', () => {
207-
const iterationCount = Number(validationSubset.value);
208-
209-
render(<App subsetParameters={subsetsParameters} />);
210-
211-
for (let i = 0; i < iterationCount; i++) {
212-
fireEvent.keyDown(screen.getByLabelText('End range'), { key: 'Left' });
213-
}
214-
215-
const updatedValidationSubsetSize = Math.floor(datasetSize * 0.02);
216-
const updatedTestSubsetSize = Math.floor(datasetSize * 0.28);
217-
const updatedTrainingSubsetSize = datasetSize - updatedValidationSubsetSize - updatedTestSubsetSize;
218-
219-
expectSubsetSizes({
220-
trainingSize: updatedTrainingSubsetSize,
221-
validationSize: updatedValidationSubsetSize,
222-
testSize: updatedTestSubsetSize,
223-
});
224-
});
225-
226207
it('shows warning that training subsets is unavailable when there are not enough media items', () => {
227208
const mockedSubsetsParameters = [
228209
getMockedConfigurationParameter({
@@ -287,10 +268,14 @@ describe('TrainingSubsets', () => {
287268

288269
render(<App subsetParameters={mockedSubsetsParameters} />);
289270

271+
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
272+
273+
fireEvent.keyDown(screen.getByLabelText('End range'), { key: 'Left' });
274+
290275
const alert = screen.getByRole('alert');
291276

292277
expect(alert).toBeInTheDocument();
293-
expect(within(alert).getByRole('heading')).toHaveTextContent('Training subsets configuration unavailable');
278+
expect(within(alert).getByRole('heading')).toHaveTextContent('Invalid training subsets configuration');
294279

295280
const validationSize = Math.floor(mockedDatasetSize * (Number(mockedValidationSubset.value) / 100));
296281
const testSize = Math.floor(mockedDatasetSize * (Number(mockedTestSubset.value) / 100));

0 commit comments

Comments
 (0)