From 5038cf6135f9793d2bf9ec4742e4349624219f2a Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 6 Jul 2020 15:08:42 -0400 Subject: [PATCH 1/8] add results_field input in form. handle in cloning and editor --- .../configuration_step_form.tsx | 8 ++------ .../details_step/details_step_form.tsx | 17 +++++++++++++++++ .../components/action_clone/clone_button.tsx | 1 + .../hooks/use_create_analytics_form/reducer.ts | 16 ++++++++++++++++ .../hooks/use_create_analytics_form/state.ts | 7 +++++++ 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx index b83dd2e4329e0..9dae54b6537b3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx @@ -71,12 +71,8 @@ export const ConfigurationStepForm: FC = ({ EuiComboBoxOptionOption[] >([]); const [includesTableItems, setIncludesTableItems] = useState([]); - const [maxDistinctValuesError, setMaxDistinctValuesError] = useState( - undefined - ); - const [unsupportedFieldsError, setUnsupportedFieldsError] = useState( - undefined - ); + const [maxDistinctValuesError, setMaxDistinctValuesError] = useState(); + const [unsupportedFieldsError, setUnsupportedFieldsError] = useState(); const { setEstimatedModelMemoryLimit, setFormState } = actions; const { estimatedModelMemoryLimit, form, isJobCreated, requestMessages } = state; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx index d846ae95c2c7e..168d5e31f57c3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx @@ -47,6 +47,7 @@ export const DetailsStepForm: FC = ({ jobIdExists, jobIdInvalidMaxLength, jobIdValid, + resultsField, } = form; const forceInput = useRef(null); @@ -195,6 +196,22 @@ export const DetailsStepForm: FC = ({ data-test-subj="mlAnalyticsCreateJobFlyoutDestinationIndexInput" /> + + setFormState({ resultsField: e.target.value })} + data-test-subj="mlAnalyticsCreateJobWizardResultsFieldInput" + /> + { const destinationIndexNameValid = isValidIndexName(destinationIndexName); const destinationIndexPatternTitleExists = state.indexPatternsMap[destinationIndexName] !== undefined; + + const resultsFieldEmptyString = jobConfig?.dest?.results_field === ''; + const mml = jobConfig.model_memory_limit; const modelMemoryLimitEmpty = mml === '' || mml === undefined; if (!modelMemoryLimitEmpty && mml !== undefined) { @@ -292,6 +295,18 @@ export const validateAdvancedEditor = (state: State): State => { }); } + if (resultsFieldEmptyString) { + state.advancedEditorMessages.push({ + error: i18n.translate( + 'xpack.ml.dataframe.analytics.create.advancedEditorMessage.resultsFieldEmptyString', + { + defaultMessage: 'The results field must not be an empty string.', + } + ), + message: '', + }); + } + if (dependentVariableEmpty) { state.advancedEditorMessages.push({ error: i18n.translate( @@ -336,6 +351,7 @@ export const validateAdvancedEditor = (state: State): State => { sourceIndexNameValid && !destinationIndexNameEmpty && destinationIndexNameValid && + !resultsFieldEmptyString && !dependentVariableEmpty && !modelMemoryLimitEmpty && numTopFeatureImportanceValuesValid && diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index cedbe9094cb20..21fca6eac6487 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -82,6 +82,7 @@ export interface State { previousJobType: null | AnalyticsJobType; requiredFieldsError: string | undefined; randomizeSeed: undefined | number; + resultsField: undefined | string; sourceIndex: EsIndexName; sourceIndexNameEmpty: boolean; sourceIndexNameValid: boolean; @@ -147,6 +148,7 @@ export const getInitialState = (): State => ({ previousJobType: null, requiredFieldsError: undefined, randomizeSeed: undefined, + resultsField: undefined, sourceIndex: '', sourceIndexNameEmpty: true, sourceIndexNameValid: false, @@ -198,6 +200,10 @@ export const getJobConfigFromFormState = ( model_memory_limit: formState.modelMemoryLimit, }; + if (jobConfig.dest && (formState.resultsField !== undefined || formState.resultsField !== '')) { + jobConfig.dest.results_field = formState.resultsField; + } + if ( formState.jobType === ANALYSIS_CONFIG_TYPE.REGRESSION || formState.jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION @@ -277,6 +283,7 @@ export function getCloneFormStateFromJobConfig( const resultState: Partial = { jobType, description: analyticsJobConfig.description ?? '', + resultsField: analyticsJobConfig.dest.results_field, sourceIndex: Array.isArray(analyticsJobConfig.source.index) ? analyticsJobConfig.source.index.join(',') : analyticsJobConfig.source.index, From 479af41c8b8c07b67cce3536accd2d9a475fea72 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 6 Jul 2020 15:29:17 -0400 Subject: [PATCH 2/8] update regression evaluate metrics --- .../application/data_frame_analytics/common/analytics.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index aa637f71db1cc..805a443421298 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -496,7 +496,7 @@ interface EvaluateMetrics { }; regression: { r_squared: object; - mean_squared_error: object; + mse: object; }; } @@ -541,7 +541,7 @@ export const loadEvalData = async ({ }, regression: { r_squared: {}, - mean_squared_error: {}, + mse: {}, }, }; From 84a075ec968e515c9e7ed96064c3085809f38a19 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 6 Jul 2020 18:13:52 -0400 Subject: [PATCH 3/8] add additional reg evaluation stats to expanded row and result panel --- .../data_frame_analytics/common/analytics.ts | 40 +++++- .../regression_exploration/evaluate_panel.tsx | 132 +++++++++++++----- .../regression_exploration/evaluate_stat.tsx | 106 +++++++++----- .../analytics_list/expanded_row.tsx | 73 ++++++++-- 4 files changed, 263 insertions(+), 88 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 805a443421298..1342f610ddb8d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -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; }; @@ -415,18 +423,25 @@ export const useRefreshAnalyticsList = ( const DEFAULT_SIG_FIGS = 3; export function getValuesFromResponse(response: RegressionEvaluateResponse) { - let meanSquaredError = response?.regression?.mse?.value; + let mse = response?.regression?.mse?.value; + let rSquared = response?.regression?.r_squared?.value; + let msle = response?.regression?.msle?.value; + let huber = response?.regression?.huber?.value; - if (meanSquaredError) { - meanSquaredError = Number(meanSquaredError.toPrecision(DEFAULT_SIG_FIGS)); + if (mse) { + mse = Number(mse.toPrecision(DEFAULT_SIG_FIGS)); } - - let rSquared = response?.regression?.r_squared?.value; if (rSquared) { rSquared = Number(rSquared.toPrecision(DEFAULT_SIG_FIGS)); } + if (msle) { + msle = Number(msle.toPrecision(DEFAULT_SIG_FIGS)); + } + if (huber) { + huber = Number(huber.toPrecision(DEFAULT_SIG_FIGS)); + } - return { meanSquaredError, rSquared }; + return { mse, rSquared, msle, huber }; } interface ResultsSearchBoolQuery { bool: Dictionary; @@ -490,6 +505,13 @@ 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; @@ -497,6 +519,8 @@ interface EvaluateMetrics { regression: { r_squared: object; mse: object; + msle: object; + huber: object; }; } @@ -542,6 +566,8 @@ export const loadEvalData = async ({ regression: { r_squared: {}, mse: {}, + msle: {}, + huber: {}, }, }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx index d31b7734f9969..2eb3f9e4471af 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx @@ -34,15 +34,17 @@ import { isResultsSearchBoolQuery, isRegressionEvaluateResponse, ANALYSIS_CONFIG_TYPE, + REGRESSION_STATS, } from '../../../../common/analytics'; +const EMPTY_STAT = '--'; interface Props { jobConfig: DataFrameAnalyticsConfig; jobStatus?: DATA_FRAME_TASK_STATE; searchQuery: SavedSearchQuery; } -const defaultEval: Eval = { meanSquaredError: '', rSquared: '', error: null }; +const defaultEval: Eval = { mse: '', msle: '', huber: '', rSquared: '', error: null }; export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) => { const { @@ -82,9 +84,11 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) genErrorEval.eval && isRegressionEvaluateResponse(genErrorEval.eval) ) { - const { meanSquaredError, rSquared } = getValuesFromResponse(genErrorEval.eval); + const { mse, msle, huber, rSquared } = getValuesFromResponse(genErrorEval.eval); setGeneralizationEval({ - meanSquaredError, + mse, + msle, + huber, rSquared, error: null, }); @@ -92,8 +96,10 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) } else { setIsLoadingGeneralization(false); setGeneralizationEval({ - meanSquaredError: '--', - rSquared: '--', + mse: EMPTY_STAT, + msle: EMPTY_STAT, + huber: EMPTY_STAT, + rSquared: EMPTY_STAT, error: genErrorEval.error, }); } @@ -118,9 +124,11 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) trainingErrorEval.eval && isRegressionEvaluateResponse(trainingErrorEval.eval) ) { - const { meanSquaredError, rSquared } = getValuesFromResponse(trainingErrorEval.eval); + const { mse, msle, huber, rSquared } = getValuesFromResponse(trainingErrorEval.eval); setTrainingEval({ - meanSquaredError, + mse, + msle, + huber, rSquared, error: null, }); @@ -128,8 +136,10 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) } else { setIsLoadingTraining(false); setTrainingEval({ - meanSquaredError: '--', - rSquared: '--', + mse: EMPTY_STAT, + msle: EMPTY_STAT, + rSquared: EMPTY_STAT, + huber: EMPTY_STAT, error: trainingErrorEval.error, }); } @@ -274,22 +284,48 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) - + + {/* First row stats */} - + + + + + + + + + {/* Second row stats */} - + + + + + + + + @@ -331,22 +367,48 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) - + + {/* First row stats */} - + + + + + + + + + {/* Second row stats */} - + + + + + + + + diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx index 1b4461b2bb075..bec0748c3e496 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx @@ -6,58 +6,96 @@ import React, { FC } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiStat, EuiIconTip, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiStat, EuiIconTip, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; +import { REGRESSION_STATS } from '../../../../common/analytics'; interface Props { isLoading: boolean; title: number | string; - isMSE: boolean; + statType: REGRESSION_STATS; dataTestSubj: string; } -const meanSquaredErrorText = i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.meanSquaredErrorText', - { - defaultMessage: 'Mean squared error', - } -); -const rSquaredText = i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.rSquaredText', - { - defaultMessage: 'R squared', - } -); -const meanSquaredErrorTooltipContent = i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.meanSquaredErrorTooltipContent', - { - defaultMessage: - 'Measures how well the regression analysis model is performing. Mean squared sum of the difference between true and predicted values.', - } -); -const rSquaredTooltipContent = i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.rSquaredTooltipContent', - { - defaultMessage: - 'Represents the goodness of fit. Measures how well the observed outcomes are replicated by the model.', - } -); +const statDescriptions = { + [REGRESSION_STATS.MSE]: i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.meanSquaredErrorText', + { + defaultMessage: 'Mean squared error', + } + ), + [REGRESSION_STATS.MSLE]: i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.msleText', + { + defaultMessage: 'Mean squared logarithmic error', + } + ), + [REGRESSION_STATS.R_SQUARED]: i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.rSquaredText', + { + defaultMessage: 'R squared', + } + ), + [REGRESSION_STATS.HUBER]: ( + + Pseudo Huber loss function + + ), + }} + /> + ), +}; + +const tooltipContent = { + [REGRESSION_STATS.MSE]: i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.meanSquaredErrorTooltipContent', + { + defaultMessage: + 'Measures how well the regression analysis model is performing. Mean squared sum of the difference between true and predicted values.', + } + ), + [REGRESSION_STATS.MSLE]: i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.msleTooltipContent', + { + defaultMessage: + 'Average squared difference between the logarithm of the predicted values and the logarithm of the actual (ground truth) value', + } + ), + [REGRESSION_STATS.R_SQUARED]: i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.rSquaredTooltipContent', + { + defaultMessage: + 'Represents the goodness of fit. Measures how well the observed outcomes are replicated by the model.', + } + ), +}; -export const EvaluateStat: FC = ({ isLoading, isMSE, title, dataTestSubj }) => ( +export const EvaluateStat: FC = ({ isLoading, statType, title, dataTestSubj }) => ( - + {statType !== REGRESSION_STATS.HUBER && ( + + )} ); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx index 4d029ff1d9546..32bb310b2f125 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx @@ -29,6 +29,7 @@ import { getDataFrameAnalyticsProgressPhase, isCompletedAnalyticsJob } from './c import { isRegressionAnalysis, ANALYSIS_CONFIG_TYPE, + REGRESSION_STATS, isRegressionEvaluateResponse, } from '../../../../common/analytics'; import { ExpandedRowMessagesPane } from './expanded_row_messages_pane'; @@ -44,7 +45,7 @@ function getItemDescription(value: any) { interface LoadedStatProps { isLoading: boolean; evalData: Eval; - resultProperty: 'meanSquaredError' | 'rSquared'; + resultProperty: REGRESSION_STATS; } const LoadedStat: FC = ({ isLoading, evalData, resultProperty }) => { @@ -61,7 +62,7 @@ interface Props { item: DataFrameAnalyticsListRow; } -const defaultEval: Eval = { meanSquaredError: '', rSquared: '', error: null }; +const defaultEval: Eval = { mse: '', msle: '', huber: '', rSquared: '', error: null }; export const ExpandedRow: FC = ({ item }) => { const [trainingEval, setTrainingEval] = useState(defaultEval); @@ -94,9 +95,11 @@ export const ExpandedRow: FC = ({ item }) => { genErrorEval.eval && isRegressionEvaluateResponse(genErrorEval.eval) ) { - const { meanSquaredError, rSquared } = getValuesFromResponse(genErrorEval.eval); + const { mse, msle, huber, rSquared } = getValuesFromResponse(genErrorEval.eval); setGeneralizationEval({ - meanSquaredError, + mse, + msle, + huber, rSquared, error: null, }); @@ -104,7 +107,9 @@ export const ExpandedRow: FC = ({ item }) => { } else { setIsLoadingGeneralization(false); setGeneralizationEval({ - meanSquaredError: '', + mse: '', + msle: '', + huber: '', rSquared: '', error: genErrorEval.error, }); @@ -124,9 +129,11 @@ export const ExpandedRow: FC = ({ item }) => { trainingErrorEval.eval && isRegressionEvaluateResponse(trainingErrorEval.eval) ) { - const { meanSquaredError, rSquared } = getValuesFromResponse(trainingErrorEval.eval); + const { mse, msle, huber, rSquared } = getValuesFromResponse(trainingErrorEval.eval); setTrainingEval({ - meanSquaredError, + mse, + msle, + huber, rSquared, error: null, }); @@ -134,7 +141,9 @@ export const ExpandedRow: FC = ({ item }) => { } else { setIsLoadingTraining(false); setTrainingEval({ - meanSquaredError: '', + mse: '', + msle: '', + huber: '', rSquared: '', error: genErrorEval.error, }); @@ -221,7 +230,17 @@ export const ExpandedRow: FC = ({ item }) => { + ), + }, + { + title: 'generalization mean squared logarithmic error', + description: ( + ), }, @@ -231,7 +250,17 @@ export const ExpandedRow: FC = ({ item }) => { + ), + }, + { + title: 'generalization pseudo huber loss function', + description: ( + ), }, @@ -241,7 +270,17 @@ export const ExpandedRow: FC = ({ item }) => { + ), + }, + { + title: 'training mean squared logarithmic error', + description: ( + ), }, @@ -251,7 +290,17 @@ export const ExpandedRow: FC = ({ item }) => { + ), + }, + { + title: 'training pseudo huber loss function', + description: ( + ), } From 0439807d0796dd0020d248fb1e9d9ec6303b71c5 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 6 Jul 2020 18:18:06 -0400 Subject: [PATCH 4/8] update jest test --- .../components/action_clone/clone_button.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.test.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.test.ts index 006cccf3b4610..9db32e298691e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.test.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.test.ts @@ -131,7 +131,7 @@ describe('Analytics job clone action', () => { }, analyzed_fields: { includes: [], - excludes: [], + excludes: ['excluded_field'], }, model_memory_limit: '350mb', allow_lazy_start: false, From 0bc8210629b1d0fdd996956264c5e3872e3a4b3f Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 7 Jul 2020 15:12:06 -0400 Subject: [PATCH 5/8] resultsField: check for only spaces string in editor and form --- .../details_step/details_step_details.tsx | 17 ++++++++++++++++- .../regression_exploration/evaluate_stat.tsx | 5 ++++- .../hooks/use_create_analytics_form/reducer.ts | 4 +++- .../hooks/use_create_analytics_form/state.ts | 5 ++++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx index a4d86b48006e8..77078d0590cd4 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx @@ -16,6 +16,8 @@ import { import { State } from '../../../analytics_management/hooks/use_create_analytics_form/state'; import { ANALYTICS_STEPS } from '../../page'; +const DEFAULT_RESULTS_FIELD = 'ml'; + export interface ListItems { title: string; description: string | JSX.Element; @@ -26,7 +28,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[] = [ { @@ -37,6 +39,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', { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx index bec0748c3e496..114ec75efb2e7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx @@ -45,8 +45,11 @@ const statDescriptions = { - Pseudo Huber loss function + {i18n.translate('xpack.ml.dataframe.analytics.regressionExploration.huberLinkText', { + defaultMessage: 'Pseudo Huber loss function', + })} ), }} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts index f60786328875f..b344e44c97d59 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts @@ -145,7 +145,9 @@ export const validateAdvancedEditor = (state: State): State => { const destinationIndexPatternTitleExists = state.indexPatternsMap[destinationIndexName] !== undefined; - const resultsFieldEmptyString = jobConfig?.dest?.results_field === ''; + const resultsFieldEmptyString = + typeof jobConfig?.dest?.results_field === 'string' && + jobConfig?.dest?.results_field.trim() === ''; const mml = jobConfig.model_memory_limit; const modelMemoryLimitEmpty = mml === '' || mml === undefined; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index 21fca6eac6487..0d425c8ead4a2 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -200,7 +200,10 @@ export const getJobConfigFromFormState = ( model_memory_limit: formState.modelMemoryLimit, }; - if (jobConfig.dest && (formState.resultsField !== undefined || formState.resultsField !== '')) { + const resultsFieldEmpty = + typeof formState?.resultsField === 'string' && formState?.resultsField.trim() === ''; + + if (jobConfig.dest && !resultsFieldEmpty) { jobConfig.dest.results_field = formState.resultsField; } From 744a5ddf8a3f8b713ddd0706d81912d71fbbcbce Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 7 Jul 2020 15:53:35 -0400 Subject: [PATCH 6/8] update getValuesFromResult to be less repetitive --- .../data_frame_analytics/common/analytics.ts | 30 ++++++++----------- .../details_step/details_step_details.tsx | 2 -- .../regression_exploration/evaluate_panel.tsx | 8 ++--- .../analytics_list/expanded_row.tsx | 8 ++--- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 1342f610ddb8d..1817611a66dd2 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -423,25 +423,21 @@ export const useRefreshAnalyticsList = ( const DEFAULT_SIG_FIGS = 3; export function getValuesFromResponse(response: RegressionEvaluateResponse) { - let mse = response?.regression?.mse?.value; - let rSquared = response?.regression?.r_squared?.value; - let msle = response?.regression?.msle?.value; - let huber = response?.regression?.huber?.value; - - if (mse) { - mse = Number(mse.toPrecision(DEFAULT_SIG_FIGS)); - } - if (rSquared) { - rSquared = Number(rSquared.toPrecision(DEFAULT_SIG_FIGS)); - } - if (msle) { - msle = Number(msle.toPrecision(DEFAULT_SIG_FIGS)); - } - if (huber) { - huber = Number(huber.toPrecision(DEFAULT_SIG_FIGS)); + const results = {}; + + if (response?.regression) { + for (const statType in response.regression) { + if (response.regression.hasOwnProperty(statType)) { + let currentStatValue = response.regression[statType]?.value; + if (currentStatValue) { + currentStatValue = Number(currentStatValue.toPrecision(DEFAULT_SIG_FIGS)); + } + results[statType] = currentStatValue; + } + } } - return { mse, rSquared, msle, huber }; + return results; } interface ResultsSearchBoolQuery { bool: Dictionary; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx index 77078d0590cd4..8a41eb4b8a865 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_details.tsx @@ -16,8 +16,6 @@ import { import { State } from '../../../analytics_management/hooks/use_create_analytics_form/state'; import { ANALYTICS_STEPS } from '../../page'; -const DEFAULT_RESULTS_FIELD = 'ml'; - export interface ListItems { title: string; description: string | JSX.Element; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx index 2eb3f9e4471af..976cf063e8d32 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx @@ -84,12 +84,12 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) genErrorEval.eval && isRegressionEvaluateResponse(genErrorEval.eval) ) { - const { mse, msle, huber, rSquared } = getValuesFromResponse(genErrorEval.eval); + const { mse, msle, huber, r_squared } = getValuesFromResponse(genErrorEval.eval); setGeneralizationEval({ mse, msle, huber, - rSquared, + rSquared: r_squared, error: null, }); setIsLoadingGeneralization(false); @@ -124,12 +124,12 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) trainingErrorEval.eval && isRegressionEvaluateResponse(trainingErrorEval.eval) ) { - const { mse, msle, huber, rSquared } = getValuesFromResponse(trainingErrorEval.eval); + const { mse, msle, huber, r_squared } = getValuesFromResponse(trainingErrorEval.eval); setTrainingEval({ mse, msle, huber, - rSquared, + rSquared: r_squared, error: null, }); setIsLoadingTraining(false); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx index 32bb310b2f125..5276fedff0fde 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx @@ -95,12 +95,12 @@ export const ExpandedRow: FC = ({ item }) => { genErrorEval.eval && isRegressionEvaluateResponse(genErrorEval.eval) ) { - const { mse, msle, huber, rSquared } = getValuesFromResponse(genErrorEval.eval); + const { mse, msle, huber, r_squared } = getValuesFromResponse(genErrorEval.eval); setGeneralizationEval({ mse, msle, huber, - rSquared, + rSquared: r_squared, error: null, }); setIsLoadingGeneralization(false); @@ -129,12 +129,12 @@ export const ExpandedRow: FC = ({ item }) => { trainingErrorEval.eval && isRegressionEvaluateResponse(trainingErrorEval.eval) ) { - const { mse, msle, huber, rSquared } = getValuesFromResponse(trainingErrorEval.eval); + const { mse, msle, huber, r_squared } = getValuesFromResponse(trainingErrorEval.eval); setTrainingEval({ mse, msle, huber, - rSquared, + rSquared: r_squared, error: null, }); setIsLoadingTraining(false); From 8559b4bb3110892b5d5b2948d665da5987c0388a Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 7 Jul 2020 16:40:45 -0400 Subject: [PATCH 7/8] update types --- .../data_frame_analytics/common/analytics.ts | 21 +++++++++++++--- .../regression_exploration/evaluate_panel.tsx | 24 +++++++++++-------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 1817611a66dd2..c23ed0e6b3665 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -422,17 +422,32 @@ export const useRefreshAnalyticsList = ( const DEFAULT_SIG_FIGS = 3; +interface RegressionEvaluteExtractedResponse { + mse: number | string; + msle: number | string; + huber: number | string; + r_squared: number | string; +} + +export const EMPTY_STAT = '--'; + export function getValuesFromResponse(response: RegressionEvaluateResponse) { - const results = {}; + const results: RegressionEvaluteExtractedResponse = { + 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]?.value; + let currentStatValue = + response.regression[statType as keyof RegressionEvaluateResponse['regression']]?.value; if (currentStatValue) { currentStatValue = Number(currentStatValue.toPrecision(DEFAULT_SIG_FIGS)); } - results[statType] = currentStatValue; + results[statType as keyof RegressionEvaluteExtractedResponse] = currentStatValue; } } } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx index 976cf063e8d32..75c41c097192e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx @@ -35,16 +35,26 @@ import { isRegressionEvaluateResponse, ANALYSIS_CONFIG_TYPE, REGRESSION_STATS, + EMPTY_STAT, } from '../../../../common/analytics'; -const EMPTY_STAT = '--'; interface Props { jobConfig: DataFrameAnalyticsConfig; jobStatus?: DATA_FRAME_TASK_STATE; searchQuery: SavedSearchQuery; } -const defaultEval: Eval = { mse: '', msle: '', huber: '', 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 = ({ jobConfig, jobStatus, searchQuery }) => { const { @@ -96,10 +106,7 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) } else { setIsLoadingGeneralization(false); setGeneralizationEval({ - mse: EMPTY_STAT, - msle: EMPTY_STAT, - huber: EMPTY_STAT, - rSquared: EMPTY_STAT, + ...EMPTY_STATS, error: genErrorEval.error, }); } @@ -136,10 +143,7 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) } else { setIsLoadingTraining(false); setTrainingEval({ - mse: EMPTY_STAT, - msle: EMPTY_STAT, - rSquared: EMPTY_STAT, - huber: EMPTY_STAT, + ...EMPTY_STATS, error: trainingErrorEval.error, }); } From 4daf088d1231e5f5df292d4cc0a7788254ad2c97 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Wed, 8 Jul 2020 13:53:52 -0400 Subject: [PATCH 8/8] fix type name typo --- .../application/data_frame_analytics/common/analytics.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index c23ed0e6b3665..618ea5184007d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -422,7 +422,7 @@ export const useRefreshAnalyticsList = ( const DEFAULT_SIG_FIGS = 3; -interface RegressionEvaluteExtractedResponse { +interface RegressionEvaluateExtractedResponse { mse: number | string; msle: number | string; huber: number | string; @@ -432,7 +432,7 @@ interface RegressionEvaluteExtractedResponse { export const EMPTY_STAT = '--'; export function getValuesFromResponse(response: RegressionEvaluateResponse) { - const results: RegressionEvaluteExtractedResponse = { + const results: RegressionEvaluateExtractedResponse = { mse: EMPTY_STAT, msle: EMPTY_STAT, huber: EMPTY_STAT, @@ -447,7 +447,7 @@ export function getValuesFromResponse(response: RegressionEvaluateResponse) { if (currentStatValue) { currentStatValue = Number(currentStatValue.toPrecision(DEFAULT_SIG_FIGS)); } - results[statType as keyof RegressionEvaluteExtractedResponse] = currentStatValue; + results[statType as keyof RegressionEvaluateExtractedResponse] = currentStatValue; } } }