Skip to content

Commit

Permalink
UI: Add early stopping to submit Experiment by parameters (#1373)
Browse files Browse the repository at this point in the history
  • Loading branch information
andreyvelich authored Nov 2, 2020
1 parent 499856f commit 052ca25
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 1 deletion.
29 changes: 29 additions & 0 deletions pkg/ui/v1beta1/frontend/src/actions/generalActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,35 @@ export const changeStatus = (filter, checked) => ({
checked,
});

export const CHANGE_EARLY_STOPPING_ALGORITHM = 'CHANGE_EARLY_STOPPING_ALGORITHM';

export const changeEarlyStoppingAlgorithm = algorithmName => ({
type: CHANGE_EARLY_STOPPING_ALGORITHM,
algorithmName,
});

export const ADD_EARLY_STOPPING_SETTING = 'ADD_EARLY_STOPPING_SETTING';

export const addEarlyStoppingSetting = () => ({
type: ADD_EARLY_STOPPING_SETTING,
});

export const CHANGE_EARLY_STOPPING_SETTING = 'CHANGE_EARLY_STOPPING_SETTING';

export const changeEarlyStoppingSetting = (index, field, value) => ({
type: CHANGE_EARLY_STOPPING_SETTING,
index,
field,
value,
});

export const DELETE_EARLY_STOPPING_SETTING = 'DELETE_EARLY_STOPPING_SETTING';

export const deleteEarlyStoppingSetting = index => ({
type: DELETE_EARLY_STOPPING_SETTING,
index,
});

export const CHANGE_TRIAL_TEMPLATE_SOURCE = 'CHANGE_TRIAL_TEMPLATE_SOURCE';

export const changeTrialTemplateSource = source => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import React from 'react';
import { connect } from 'react-redux';

import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Grid from '@material-ui/core/Grid';
import Tooltip from '@material-ui/core/Tooltip';
import HelpOutlineIcon from '@material-ui/icons/HelpOutline';
import Typography from '@material-ui/core/Typography';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import InputLabel from '@material-ui/core/InputLabel';
import TextField from '@material-ui/core/TextField';
import IconButton from '@material-ui/core/IconButton';
import DeleteIcon from '@material-ui/icons/Delete';

import {
changeEarlyStoppingAlgorithm,
addEarlyStoppingSetting,
changeEarlyStoppingSetting,
deleteEarlyStoppingSetting,
} from '../../../../actions/generalActions';

import { GENERAL_MODULE } from '../../../../constants/constants';

const useStyles = makeStyles({
textField: {
width: '80%',
},
help: {
padding: 4 / 2,
verticalAlign: 'middle',
marginRight: 5,
},
parameter: {
padding: 2,
marginBottom: 10,
},
icon: {
padding: 4,
margin: '0 auto',
verticalAlign: 'middle !important',
},
formControl: {
width: '100%',
},
addButton: {
margin: 10,
},
});

const EarlyStopping = props => {
const classes = useStyles();

const onEarlyStoppingAlgorithmChange = event => {
props.changeEarlyStoppingAlgorithm(event.target.value);
};

const onAddEarlyStoppingSetting = () => {
props.addEarlyStoppingSetting();
};

const onChangeEarlyStoppingSetting = (field, index) => event => {
props.changeEarlyStoppingSetting(index, field, event.target.value);
};

const onDeleteEarlyStoppingSetting = index => event => {
props.deleteEarlyStoppingSetting(index);
};
return (
<div>
<Button
variant={'contained'}
color={'primary'}
className={classes.addButton}
onClick={onAddEarlyStoppingSetting}
>
Add early stopping setting
</Button>
<div className={classes.parameter}>
<Grid container alignItems={'center'}>
<Grid item xs={12} sm={3}>
<Typography>
<Tooltip title={'Name for the Early Stopping Algorithm'}>
<HelpOutlineIcon className={classes.help} color={'primary'} />
</Tooltip>
{'Early Stopping Algorithm Name'}
</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel>Algorithm Name</InputLabel>
<Select
value={props.earlyStoppingAlgorithm}
onChange={onEarlyStoppingAlgorithmChange}
label="Algorithm Name"
>
{props.allEarlyStoppingAlgorithms.map((algorithm, i) => {
return (
<MenuItem value={algorithm} key={i}>
{algorithm}
</MenuItem>
);
})}
</Select>
</FormControl>
</Grid>
</Grid>
</div>
<br />
{props.earlyStoppingSettings.map((setting, i) => {
return (
<div key={i} className={classes.parameter}>
<Grid container alignItems={'center'}>
<Grid item xs={3} />
<Grid item xs={4}>
<TextField
label={'Name'}
className={classes.textField}
value={setting.name}
onChange={onChangeEarlyStoppingSetting('name', i)}
/>
</Grid>
<Grid item xs={4}>
<TextField
label={'Value'}
className={classes.textField}
value={setting.value}
onChange={onChangeEarlyStoppingSetting('value', i)}
/>
</Grid>
<Grid item xs={1}>
<IconButton
key="close"
aria-label="Close"
color={'primary'}
className={classes.icon}
onClick={onDeleteEarlyStoppingSetting(i)}
>
<DeleteIcon />
</IconButton>
</Grid>
</Grid>
</div>
);
})}
</div>
);
};

const mapStateToProps = state => {
return {
earlyStoppingAlgorithm: state[GENERAL_MODULE].earlyStoppingAlgorithm,
allEarlyStoppingAlgorithms: state[GENERAL_MODULE].allEarlyStoppingAlgorithms,
earlyStoppingSettings: state[GENERAL_MODULE].earlyStoppingSettings,
};
};

export default connect(mapStateToProps, {
changeEarlyStoppingAlgorithm,
addEarlyStoppingSetting,
changeEarlyStoppingSetting,
deleteEarlyStoppingSetting,
})(EarlyStopping);
38 changes: 38 additions & 0 deletions pkg/ui/v1beta1/frontend/src/components/HP/Create/HPParameters.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import Objective from './Params/Objective';
import TrialTemplate from '../../Common/Create/Params/Trial/TrialTemplate';
import Parameters from './Params/Parameters';
import Algorithm from './Params/Algorithm';
import EarlyStopping from '../../Common/Create/Params/EarlyStopping';
import MetricsCollectorSpec from '../../Common/Create/Params/MetricsCollector';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';

import { submitHPJob } from '../../../actions/hpCreateActions';

Expand Down Expand Up @@ -110,6 +113,14 @@ const HPParameters = props => {
data.spec.algorithm.algorithmSettings = [];
addAlgorithmSettings(props.algorithmSettings, data.spec.algorithm.algorithmSettings);

// Add early stopping if selected.
if (checkedSetEarlyStopping) {
data.spec.earlyStopping = {};
data.spec.earlyStopping.algorithmName = props.earlyStoppingAlgorithm;
data.spec.earlyStopping.algorithmSettings = [];
addAlgorithmSettings(props.earlyStoppingSettings, data.spec.earlyStopping.algorithmSettings);
}

data.spec.parameters = [];
addParameter(props.parameters, data.spec.parameters);

Expand Down Expand Up @@ -238,6 +249,12 @@ const HPParameters = props => {

const { classes } = props;

const [checkedSetEarlyStopping, setCheckedSetEarlyStopping] = React.useState(false);

const onCheckBoxChange = event => {
setCheckedSetEarlyStopping(event.target.checked);
};

return (
<div className={classes.root}>
{/* Common Metadata */}
Expand All @@ -251,6 +268,25 @@ const HPParameters = props => {
{SectionInTypography('Algorithm')}
<Algorithm />

<Grid container spacing={3}>
<Grid item>
<Typography variant="h6">Early Stopping (Optional)</Typography>
</Grid>
<Grid item>
<FormControlLabel
control={
<Checkbox
checked={checkedSetEarlyStopping}
onChange={onCheckBoxChange}
color="primary"
/>
}
label="Set"
/>
</Grid>
</Grid>
{checkedSetEarlyStopping && <EarlyStopping />}

{SectionInTypography('Parameters')}
<Parameters />
{SectionInTypography('Metrics Collector Spec')}
Expand Down Expand Up @@ -290,6 +326,8 @@ const mapStateToProps = state => {
additionalMetricNames: state[constants.HP_CREATE_MODULE].additionalMetricNames,
metricStrategies: state[constants.HP_CREATE_MODULE].metricStrategies,
algorithmName: state[constants.HP_CREATE_MODULE].algorithmName,
earlyStoppingAlgorithm: state[constants.GENERAL_MODULE].earlyStoppingAlgorithm,
earlyStoppingSettings: state[constants.GENERAL_MODULE].earlyStoppingSettings,
algorithmSettings: state[constants.HP_CREATE_MODULE].algorithmSettings,
parameters: state[constants.HP_CREATE_MODULE].parameters,
primaryPodLabels: state[constants.GENERAL_MODULE].primaryPodLabels,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class HPJobTable extends React.Component {

return (
<Paper className={classes.root}>
{this.props.data.length > 1 && (
{this.props.data.length >= 1 && (
<div>
<Table className={classes.table}>
<TableHead>
Expand Down
32 changes: 32 additions & 0 deletions pkg/ui/v1beta1/frontend/src/reducers/general.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const initialState = {
suggestion: {},
dialogSuggestionOpen: false,

earlyStoppingAlgorithm: 'medianstop',
allEarlyStoppingAlgorithms: ['medianstop'],
earlyStoppingSettings: [],

trialTemplateSourceList: [TEMPLATE_SOURCE_CONFIG_MAP, TEMPLATE_SOURCE_YAML],
trialTemplateSource: 'ConfigMap',
primaryPodLabels: [],
Expand Down Expand Up @@ -237,6 +241,34 @@ const generalReducer = (state = initialState, action) => {
dialogExperimentOpen: false,
dialogSuggestionOpen: false,
};
// Experiment early stopping actions.
case actions.CHANGE_EARLY_STOPPING_ALGORITHM:
return {
...state,
earlyStoppingAlgorithm: action.algorithmName,
};
case actions.ADD_EARLY_STOPPING_SETTING:
var earlyStoppingSettings = state.earlyStoppingSettings.slice();
let setting = { name: '', value: '' };
earlyStoppingSettings.push(setting);
return {
...state,
earlyStoppingSettings: earlyStoppingSettings,
};
case actions.CHANGE_EARLY_STOPPING_SETTING:
earlyStoppingSettings = state.earlyStoppingSettings.slice();
earlyStoppingSettings[action.index][action.field] = action.value;
return {
...state,
earlyStoppingSettings: earlyStoppingSettings,
};
case actions.DELETE_EARLY_STOPPING_SETTING:
earlyStoppingSettings = state.earlyStoppingSettings.slice();
earlyStoppingSettings.splice(action.index, 1);
return {
...state,
earlyStoppingSettings: earlyStoppingSettings,
};
// Experiment Trial Template actions.
case templateActions.FETCH_TRIAL_TEMPLATES_SUCCESS:
var trialTemplatesData = action.trialTemplatesData;
Expand Down

0 comments on commit 052ca25

Please sign in to comment.