Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.x] [ML] DF Analytics: add results field to wizard and show regression stats (#70893) #71161

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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