Skip to content
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 @@ -32,6 +32,7 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
Expand Down Expand Up @@ -70,7 +71,7 @@ public static TrainedModelDefinition.Builder createRandomBuilder(TargetType targ
TargetMeanEncodingTests.createRandom()))
.limit(numberOfProcessors)
.collect(Collectors.toList()))
.setTrainedModel(randomFrom(TreeTests.buildRandomTree(Collections.emptyList(), 6, targetType),
.setTrainedModel(randomFrom(TreeTests.buildRandomTree(Arrays.asList("foo", "bar"), 6, targetType),
EnsembleTests.createRandom(targetType)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ public Builder validate(boolean forCreation) {
break;
}
}
if (input != null && input.getFieldNames().isEmpty()) {
validationException = addValidationError("[input.field_names] must not be empty", validationException);
}
if (forCreation) {
validationException = checkIllegalSetting(version, VERSION.getPreferredName(), validationException);
validationException = checkIllegalSetting(createdBy, CREATED_BY.getPreferredName(), validationException);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ public int hashCode() {

@Override
public void validate() {
if (this.models.isEmpty()) {
throw ExceptionsHelper.badRequestException("[{}] must not be empty", TRAINED_MODELS.getPreferredName());
}

if (outputAggregator.compatibleWith(targetType) == false) {
throw ExceptionsHelper.badRequestException(
"aggregate_output [{}] is not compatible with target_type [{}]",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ public static Builder builder() {

@Override
public void validate() {
if (featureNames.isEmpty()) {
throw ExceptionsHelper.badRequestException("[{}] must not be empty for tree model", FEATURE_NAMES.getPreferredName());
}
checkTargetType();
detectMissingNodes();
detectCycle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -202,6 +203,14 @@ public void testEnsembleWithTargetTypeAndLabelsMismatch() {
assertThat(ex.getMessage(), equalTo(msg));
}

public void testEnsembleWithEmptyModels() {
List<String> featureNames = Arrays.asList("foo", "bar");
ElasticsearchException ex = expectThrows(ElasticsearchException.class, () -> {
Ensemble.builder().setTrainedModels(Collections.emptyList()).setFeatureNames(featureNames).build().validate();
});
assertThat(ex.getMessage(), equalTo("[trained_models] must not be empty"));
}

public void testClassificationProbability() {
List<String> featureNames = Arrays.asList("foo", "bar");
Tree tree1 = Tree.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,21 @@ public void testTreeWithTargetTypeAndLabelsMismatch() {
assertThat(ex.getMessage(), equalTo(msg));
}

public void testTreeWithEmptyFeatureNames() {
String msg = "[feature_names] must not be empty for tree model";
ElasticsearchException ex = expectThrows(ElasticsearchException.class, () -> {
Tree.builder()
.setRoot(TreeNode.builder(0)
.setLeftChild(1)
.setSplitFeature(1)
.setThreshold(randomDouble()))
.setFeatureNames(Collections.emptyList())
.build()
.validate();
});
assertThat(ex.getMessage(), equalTo(msg));
}

public void testOperationsEstimations() {
Tree tree = buildRandomTree(Arrays.asList("foo", "bar", "baz"), 5);
assertThat(tree.estimatedNumOperations(), equalTo(7L));
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugin/ml/qa/ml-with-security/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ integTest.runner {
'ml/inference_crud/Test delete with missing model',
'ml/inference_crud/Test get given missing trained model',
'ml/inference_crud/Test get given expression without matches and allow_no_match is false',
'ml/inference_crud/Test put ensemble with empty models',
'ml/inference_crud/Test put ensemble with tree where tree has empty feature-names',
'ml/inference_crud/Test put model with empty input.field_names',
'ml/inference_stats_crud/Test get stats given missing trained model',
'ml/inference_stats_crud/Test get stats given expression without matches and allow_no_match is false',
'ml/jobs_crud/Test cannot create job with existing categorizer state document',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,97 @@ setup:
allow_no_match: false
- match: { count: 1 }
- match: { trained_model_configs.0.model_id: "lang_ident_model_1" }
---
"Test put ensemble with empty models":
- do:
catch: /\[trained_models\] must not be empty/
ml.put_trained_model:
model_id: "missing_model_ensembles"
body: >
{
"input": {
"field_names": "fieldy_mc_fieldname"
},
"definition": {
"trained_model": {
"ensemble": {
"feature_names": [],
"trained_models": []
}
}
}
}
---
"Test put ensemble with tree where tree has empty feature-names":
- do:
catch: /\[feature_names\] must not be empty/
ml.put_trained_model:
model_id: "ensemble_tree_missing_feature_names"
body: >
{
"input": {
"field_names": "fieldy_mc_fieldname"
},
"definition": {
"trained_model": {
"ensemble": {
"feature_names": [],
"trained_models": [
{
"tree": {
"feature_names": [],
"tree_structure": [
{
"node_index": 0,
"split_feature": 0,
"split_gain": 12.0,
"threshold": 10.0,
"decision_type": "lte",
"default_left": true,
"left_child": 1,
"right_child": 2
}]
}
}
]
}
}
}
}
---
"Test put model with empty input.field_names":
- do:
catch: /\[input\.field_names\] must not be empty/
ml.put_trained_model:
model_id: "missing_model_ensembles"
body: >
{
"input": {
"field_names": []
},
"definition": {
"trained_model": {
"ensemble": {
"feature_names": [],
"trained_models": [
{
"tree": {
"feature_names": [],
"tree_structure": [
{
"node_index": 0,
"split_feature": 0,
"split_gain": 12.0,
"threshold": 10.0,
"decision_type": "lte",
"default_left": true,
"left_child": 1,
"right_child": 2
}]
}
}
]
}
}
}
}