Skip to content

Commit

Permalink
[ML] DF Analytics: add results field to wizard and show regression st…
Browse files Browse the repository at this point in the history
…ats (#70893) (#71161)

* add results_field input in form. handle in cloning and editor

* update regression evaluate metrics

* add additional reg evaluation stats to expanded row and result panel

* update jest test

* resultsField: check for only spaces string in editor and form

* update getValuesFromResult to be less repetitive

* update types

* fix type name typo
  • Loading branch information
alvarezmelissa87 authored Jul 9, 2020
1 parent 9a75c48 commit df74fdc
Show file tree
Hide file tree
Showing 11 changed files with 353 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,24 @@ export interface DfAnalyticsExplainResponse {
}

export interface Eval {
meanSquaredError: number | string;
mse: number | string;
msle: number | string;
huber: number | string;
rSquared: number | string;
error: null | string;
}

export interface RegressionEvaluateResponse {
regression: {
huber: {
value: number;
};
mse: {
value: number;
};
msle: {
value: number;
};
r_squared: {
value: number;
};
Expand Down Expand Up @@ -414,19 +422,37 @@ export const useRefreshAnalyticsList = (

const DEFAULT_SIG_FIGS = 3;

export function getValuesFromResponse(response: RegressionEvaluateResponse) {
let meanSquaredError = response?.regression?.mse?.value;
interface RegressionEvaluateExtractedResponse {
mse: number | string;
msle: number | string;
huber: number | string;
r_squared: number | string;
}

if (meanSquaredError) {
meanSquaredError = Number(meanSquaredError.toPrecision(DEFAULT_SIG_FIGS));
}
export const EMPTY_STAT = '--';

let rSquared = response?.regression?.r_squared?.value;
if (rSquared) {
rSquared = Number(rSquared.toPrecision(DEFAULT_SIG_FIGS));
export function getValuesFromResponse(response: RegressionEvaluateResponse) {
const results: RegressionEvaluateExtractedResponse = {
mse: EMPTY_STAT,
msle: EMPTY_STAT,
huber: EMPTY_STAT,
r_squared: EMPTY_STAT,
};

if (response?.regression) {
for (const statType in response.regression) {
if (response.regression.hasOwnProperty(statType)) {
let currentStatValue =
response.regression[statType as keyof RegressionEvaluateResponse['regression']]?.value;
if (currentStatValue) {
currentStatValue = Number(currentStatValue.toPrecision(DEFAULT_SIG_FIGS));
}
results[statType as keyof RegressionEvaluateExtractedResponse] = currentStatValue;
}
}
}

return { meanSquaredError, rSquared };
return results;
}
interface ResultsSearchBoolQuery {
bool: Dictionary<any>;
Expand Down Expand Up @@ -490,13 +516,22 @@ export function getEvalQueryBody({
return query;
}

export enum REGRESSION_STATS {
MSE = 'mse',
MSLE = 'msle',
R_SQUARED = 'rSquared',
HUBER = 'huber',
}

interface EvaluateMetrics {
classification: {
multiclass_confusion_matrix: object;
};
regression: {
r_squared: object;
mean_squared_error: object;
mse: object;
msle: object;
huber: object;
};
}

Expand Down Expand Up @@ -541,7 +576,9 @@ export const loadEvalData = async ({
},
regression: {
r_squared: {},
mean_squared_error: {},
mse: {},
msle: {},
huber: {},
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,8 @@ export const ConfigurationStepForm: FC<CreateAnalyticsStepProps> = ({
EuiComboBoxOptionOption[]
>([]);
const [includesTableItems, setIncludesTableItems] = useState<FieldSelectionItem[]>([]);
const [maxDistinctValuesError, setMaxDistinctValuesError] = useState<string | undefined>(
undefined
);
const [unsupportedFieldsError, setUnsupportedFieldsError] = useState<string | undefined>(
undefined
);
const [maxDistinctValuesError, setMaxDistinctValuesError] = useState<string | undefined>();
const [unsupportedFieldsError, setUnsupportedFieldsError] = useState<string | undefined>();

const { setEstimatedModelMemoryLimit, setFormState } = actions;
const { estimatedModelMemoryLimit, form, isJobCreated, requestMessages } = state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const DetailsStepDetails: FC<{ setCurrentStep: any; state: State }> = ({
state,
}) => {
const { form, isJobCreated } = state;
const { description, jobId, destinationIndex } = form;
const { description, jobId, destinationIndex, resultsField } = form;

const detailsFirstCol: ListItems[] = [
{
Expand All @@ -37,6 +37,19 @@ export const DetailsStepDetails: FC<{ setCurrentStep: any; state: State }> = ({
},
];

if (
resultsField !== undefined &&
typeof resultsField === 'string' &&
resultsField.trim() !== ''
) {
detailsFirstCol.push({
title: i18n.translate('xpack.ml.dataframe.analytics.create.configDetails.resultsField', {
defaultMessage: 'Results field',
}),
description: resultsField,
});
}

const detailsSecondCol: ListItems[] = [
{
title: i18n.translate('xpack.ml.dataframe.analytics.create.configDetails.jobDescription', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
jobIdExists,
jobIdInvalidMaxLength,
jobIdValid,
resultsField,
} = form;
const forceInput = useRef<HTMLInputElement | null>(null);

Expand Down Expand Up @@ -195,6 +196,22 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
data-test-subj="mlAnalyticsCreateJobFlyoutDestinationIndexInput"
/>
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ml.dataframe.analytics.create.resultsFieldLabel', {
defaultMessage: 'Results field',
})}
helpText={i18n.translate('xpack.ml.dataframe.analytics.create.resultsFieldHelpText', {
defaultMessage:
'Defines the name of the field in which to store the results of the analysis. Defaults to ml.',
})}
>
<EuiFieldText
disabled={isJobCreated}
value={resultsField}
onChange={(e) => setFormState({ resultsField: e.target.value })}
data-test-subj="mlAnalyticsCreateJobWizardResultsFieldInput"
/>
</EuiFormRow>
<EuiFormRow
fullWidth
isInvalid={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import {
isResultsSearchBoolQuery,
isRegressionEvaluateResponse,
ANALYSIS_CONFIG_TYPE,
REGRESSION_STATS,
EMPTY_STAT,
} from '../../../../common/analytics';

interface Props {
Expand All @@ -42,7 +44,17 @@ interface Props {
searchQuery: SavedSearchQuery;
}

const defaultEval: Eval = { meanSquaredError: '', rSquared: '', error: null };
const EMPTY_STATS = {
mse: EMPTY_STAT,
msle: EMPTY_STAT,
huber: EMPTY_STAT,
rSquared: EMPTY_STAT,
};

const defaultEval: Eval = {
...EMPTY_STATS,
error: null,
};

export const EvaluatePanel: FC<Props> = ({ jobConfig, jobStatus, searchQuery }) => {
const {
Expand Down Expand Up @@ -82,18 +94,19 @@ export const EvaluatePanel: FC<Props> = ({ jobConfig, jobStatus, searchQuery })
genErrorEval.eval &&
isRegressionEvaluateResponse(genErrorEval.eval)
) {
const { meanSquaredError, rSquared } = getValuesFromResponse(genErrorEval.eval);
const { mse, msle, huber, r_squared } = getValuesFromResponse(genErrorEval.eval);
setGeneralizationEval({
meanSquaredError,
rSquared,
mse,
msle,
huber,
rSquared: r_squared,
error: null,
});
setIsLoadingGeneralization(false);
} else {
setIsLoadingGeneralization(false);
setGeneralizationEval({
meanSquaredError: '--',
rSquared: '--',
...EMPTY_STATS,
error: genErrorEval.error,
});
}
Expand All @@ -118,18 +131,19 @@ export const EvaluatePanel: FC<Props> = ({ jobConfig, jobStatus, searchQuery })
trainingErrorEval.eval &&
isRegressionEvaluateResponse(trainingErrorEval.eval)
) {
const { meanSquaredError, rSquared } = getValuesFromResponse(trainingErrorEval.eval);
const { mse, msle, huber, r_squared } = getValuesFromResponse(trainingErrorEval.eval);
setTrainingEval({
meanSquaredError,
rSquared,
mse,
msle,
huber,
rSquared: r_squared,
error: null,
});
setIsLoadingTraining(false);
} else {
setIsLoadingTraining(false);
setTrainingEval({
meanSquaredError: '--',
rSquared: '--',
...EMPTY_STATS,
error: trainingErrorEval.error,
});
}
Expand Down Expand Up @@ -274,22 +288,48 @@ export const EvaluatePanel: FC<Props> = ({ jobConfig, jobStatus, searchQuery })
<EuiSpacer />
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem>
<EuiFlexGroup>
<EuiFlexGroup direction="column" gutterSize="s">
{/* First row stats */}
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionGenMSEstat'}
isLoading={isLoadingGeneralization}
title={generalizationEval.meanSquaredError}
isMSE
/>
<EuiFlexGroup>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionGenMSEstat'}
isLoading={isLoadingGeneralization}
title={generalizationEval.mse}
statType={REGRESSION_STATS.MSE}
/>
</EuiFlexItem>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionGenRSquaredStat'}
isLoading={isLoadingGeneralization}
title={generalizationEval.rSquared}
statType={REGRESSION_STATS.R_SQUARED}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
{/* Second row stats */}
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionGenRSquaredStat'}
isLoading={isLoadingGeneralization}
title={generalizationEval.rSquared}
isMSE={false}
/>
<EuiFlexGroup>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionGenMsleStat'}
isLoading={isLoadingGeneralization}
title={generalizationEval.msle}
statType={REGRESSION_STATS.MSLE}
/>
</EuiFlexItem>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionGenHuberStat'}
isLoading={isLoadingGeneralization}
title={generalizationEval.huber}
statType={REGRESSION_STATS.HUBER}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
Expand Down Expand Up @@ -331,22 +371,48 @@ export const EvaluatePanel: FC<Props> = ({ jobConfig, jobStatus, searchQuery })
<EuiSpacer />
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem>
<EuiFlexGroup>
<EuiFlexGroup direction="column" gutterSize="s">
{/* First row stats */}
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionTrainingMSEstat'}
isLoading={isLoadingTraining}
title={trainingEval.meanSquaredError}
isMSE
/>
<EuiFlexGroup>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionTrainingMSEstat'}
isLoading={isLoadingTraining}
title={trainingEval.mse}
statType={REGRESSION_STATS.MSE}
/>
</EuiFlexItem>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionTrainingRSquaredStat'}
isLoading={isLoadingTraining}
title={trainingEval.rSquared}
statType={REGRESSION_STATS.R_SQUARED}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
{/* Second row stats */}
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionTrainingRSquaredStat'}
isLoading={isLoadingTraining}
title={trainingEval.rSquared}
isMSE={false}
/>
<EuiFlexGroup>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionTrainingMsleStat'}
isLoading={isLoadingTraining}
title={trainingEval.msle}
statType={REGRESSION_STATS.MSLE}
/>
</EuiFlexItem>
<EuiFlexItem>
<EvaluateStat
dataTestSubj={'mlDFAnalyticsRegressionTrainingHuberStat'}
isLoading={isLoadingTraining}
title={trainingEval.huber}
statType={REGRESSION_STATS.HUBER}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
Expand Down
Loading

0 comments on commit df74fdc

Please sign in to comment.