From 6a97e1b872ae607507c9b883de27413cb8766575 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Tue, 17 Mar 2020 09:56:42 +0100 Subject: [PATCH 1/2] [ML] add maximize_minimum_recall to classification analysis --- .../components/analytics_list/action_clone.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx index 7199453a15d7f9..4da2b85b3a3acf 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx @@ -97,6 +97,10 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo num_top_feature_importance_values: { optional: true, }, + class_assignment_objective: { + optional: true, + defaultValue: 'maximize_minimum_recall', + }, }, } : {}), From 36485efb0b89957e28305bc9b85c2ef03814c5a6 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Tue, 17 Mar 2020 11:22:36 +0100 Subject: [PATCH 2/2] [ML] fix mutation of the original job during the cloning --- x-pack/plugins/ml/common/types/common.ts | 12 ++++++ .../analytics_list/action_clone.tsx | 40 +++++++++++-------- .../components/analytics_list/actions.tsx | 3 +- .../use_create_analytics_form/actions.ts | 5 ++- .../hooks/use_create_analytics_form/state.ts | 6 +-- .../use_create_analytics_form.ts | 3 +- 6 files changed, 45 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/ml/common/types/common.ts b/x-pack/plugins/ml/common/types/common.ts index 3f3493863e0f55..691b3e9eb11636 100644 --- a/x-pack/plugins/ml/common/types/common.ts +++ b/x-pack/plugins/ml/common/types/common.ts @@ -19,3 +19,15 @@ export function dictionaryToArray(dict: Dictionary): TValue[] { export type DeepPartial = { [P in keyof T]?: DeepPartial; }; + +export type DeepReadonly = T extends Array + ? ReadonlyArray> + : T extends Function + ? T + : T extends object + ? DeepReadonlyObject + : T; + +type DeepReadonlyObject = { + readonly [P in keyof T]: DeepReadonly; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx index 4da2b85b3a3acf..3a0f98fc5acaac 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx @@ -6,8 +6,9 @@ import { EuiButtonEmpty } from '@elastic/eui'; import React, { FC } from 'react'; -import { isEqual } from 'lodash'; +import { isEqual, cloneDeep } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { DeepReadonly } from '../../../../../../../common/types/common'; import { DataFrameAnalyticsConfig, isOutlierAnalysis } from '../../../../common'; import { isClassificationAnalysis, isRegressionAnalysis } from '../../../../common/analytics'; import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; @@ -261,20 +262,25 @@ export type CloneDataFrameAnalyticsConfig = Omit< 'id' | 'version' | 'create_time' >; -export function extractCloningConfig( - originalConfig: DataFrameAnalyticsConfig -): CloneDataFrameAnalyticsConfig { - const { - // Omit non-relevant props from the configuration - id, - version, - create_time, - ...cloneConfig - } = originalConfig; - - // Reset the destination index - cloneConfig.dest.index = ''; - return cloneConfig; +/** + * Gets complete original configuration as an input + * and returns the config for cloning omitting + * non-relevant parameters and resetting the destination index. + */ +export function extractCloningConfig({ + id, + version, + create_time, + ...configToClone +}: DeepReadonly): CloneDataFrameAnalyticsConfig { + return (cloneDeep({ + ...configToClone, + dest: { + ...configToClone.dest, + // Reset the destination index + index: '', + }, + }) as unknown) as CloneDataFrameAnalyticsConfig; } export function getCloneAction(createAnalyticsForm: CreateAnalyticsFormProps) { @@ -284,7 +290,7 @@ export function getCloneAction(createAnalyticsForm: CreateAnalyticsFormProps) { const { actions } = createAnalyticsForm; - const onClick = async (item: DataFrameAnalyticsListRow) => { + const onClick = async (item: DeepReadonly) => { await actions.setJobClone(item.config); }; @@ -298,7 +304,7 @@ export function getCloneAction(createAnalyticsForm: CreateAnalyticsFormProps) { } interface CloneActionProps { - item: DataFrameAnalyticsListRow; + item: DeepReadonly; createAnalyticsForm: CreateAnalyticsFormProps; } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx index 0436bcfc368470..425e3bc903d047 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; +import { DeepReadonly } from '../../../../../../../common/types/common'; import { checkPermission, @@ -107,7 +108,7 @@ export const getActions = (createAnalyticsForm: CreateAnalyticsFormProps) => { }, }, { - render: (item: DataFrameAnalyticsListRow) => { + render: (item: DeepReadonly) => { return ; }, }, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts index 8cedc38b1b59b2..66e4103f5bb41d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { DeepReadonly } from '../../../../../../../common/types/common'; import { DataFrameAnalyticsConfig } from '../../../../common'; import { FormMessage, State, SourceIndexMap } from './state'; @@ -64,7 +65,7 @@ export type Action = | { type: ACTION.SET_JOB_CONFIG; payload: State['jobConfig'] } | { type: ACTION.SET_JOB_IDS; jobIds: State['jobIds'] } | { type: ACTION.SET_ESTIMATED_MODEL_MEMORY_LIMIT; value: State['estimatedModelMemoryLimit'] } - | { type: ACTION.SET_JOB_CLONE; cloneJob: DataFrameAnalyticsConfig }; + | { type: ACTION.SET_JOB_CLONE; cloneJob: DeepReadonly }; // Actions wrapping the dispatcher exposed by the custom hook export interface ActionDispatchers { @@ -79,5 +80,5 @@ export interface ActionDispatchers { startAnalyticsJob: () => void; switchToAdvancedEditor: () => void; setEstimatedModelMemoryLimit: (value: State['estimatedModelMemoryLimit']) => void; - setJobClone: (cloneJob: DataFrameAnalyticsConfig) => Promise; + setJobClone: (cloneJob: DeepReadonly) => Promise; } 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 515e0e42bd873a..719bb6c5b07c77 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 @@ -5,7 +5,7 @@ */ import { EuiComboBoxOptionOption } from '@elastic/eui'; -import { DeepPartial } from '../../../../../../../common/types/common'; +import { DeepPartial, DeepReadonly } from '../../../../../../../common/types/common'; import { checkPermission } from '../../../../../privilege/check_privilege'; import { mlNodesAvailable } from '../../../../../ml_nodes_check'; @@ -91,7 +91,7 @@ export interface State { jobIds: DataFrameAnalyticsId[]; requestMessages: FormMessage[]; estimatedModelMemoryLimit: string; - cloneJob?: DataFrameAnalyticsConfig; + cloneJob?: DeepReadonly; } export const getInitialState = (): State => ({ @@ -195,7 +195,7 @@ export const getJobConfigFromFormState = ( * For cloning we keep job id and destination index empty. */ export function getCloneFormStateFromJobConfig( - analyticsJobConfig: CloneDataFrameAnalyticsConfig + analyticsJobConfig: Readonly ): Partial { const jobType = Object.keys(analyticsJobConfig.analysis)[0] as ANALYSIS_CONFIG_TYPE; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts index 74161d7c48c246..283df659d3a6f9 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts @@ -9,6 +9,7 @@ import { useReducer } from 'react'; import { i18n } from '@kbn/i18n'; import { SimpleSavedObject } from 'kibana/public'; +import { DeepReadonly } from '../../../../../../../common/types/common'; import { ml } from '../../../../../services/ml_api_service'; import { useMlContext } from '../../../../../contexts/ml'; @@ -308,7 +309,7 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { dispatch({ type: ACTION.SET_ESTIMATED_MODEL_MEMORY_LIMIT, value }); }; - const setJobClone = async (cloneJob: DataFrameAnalyticsConfig) => { + const setJobClone = async (cloneJob: DeepReadonly) => { resetForm(); await prepareFormValidation();