-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ML] adds multi-class feature importance support (#53803)
Adds multi-class feature importance calculation. Feature importance objects are now mapped as follows (logistic) Regression: ``` { "feature_name": "feature_0", "importance": -1.3 } ``` Multi-class [class names are `foo`, `bar`, `baz`] ``` { “feature_name”: “feature_0”, “importance”: 2.0, // sum(abs()) of class importances “foo”: 1.0, “bar”: 0.5, “baz”: -0.5 }, ``` For users to get the full benefit of aggregating and searching for feature importance, they should update their index mapping as follows (before turning this option on in their pipelines) ``` "ml.inference.feature_importance": { "type": "nested", "dynamic": true, "properties": { "feature_name": { "type": "keyword" }, "importance": { "type": "double" } } } ``` The mapping field name is as follows `ml.<inference.target_field>.<inference.tag>.feature_importance` if `inference.tag` is not provided in the processor definition, it is not part of the field path. `inference.target_field` is defaulted to `ml.inference`. //cc @lcawl ^ Where should we document this? If this makes it in for 7.7, there shouldn't be any feature_importance at inference BWC worries as 7.7 is the first version to have it.
- Loading branch information
Showing
18 changed files
with
410 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
...re/src/main/java/org/elasticsearch/xpack/core/ml/inference/results/FeatureImportance.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.core.ml.inference.results; | ||
|
||
import org.elasticsearch.common.io.stream.StreamInput; | ||
import org.elasticsearch.common.io.stream.StreamOutput; | ||
import org.elasticsearch.common.io.stream.Writeable; | ||
|
||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
public class FeatureImportance implements Writeable { | ||
|
||
private final Map<String, Double> classImportance; | ||
private final double importance; | ||
private final String featureName; | ||
private static final String IMPORTANCE = "importance"; | ||
private static final String FEATURE_NAME = "feature_name"; | ||
|
||
public static FeatureImportance forRegression(String featureName, double importance) { | ||
return new FeatureImportance(featureName, importance, null); | ||
} | ||
|
||
public static FeatureImportance forClassification(String featureName, Map<String, Double> classImportance) { | ||
return new FeatureImportance(featureName, classImportance.values().stream().mapToDouble(Math::abs).sum(), classImportance); | ||
} | ||
|
||
private FeatureImportance(String featureName, double importance, Map<String, Double> classImportance) { | ||
this.featureName = Objects.requireNonNull(featureName); | ||
this.importance = importance; | ||
this.classImportance = classImportance == null ? null : Collections.unmodifiableMap(classImportance); | ||
} | ||
|
||
public FeatureImportance(StreamInput in) throws IOException { | ||
this.featureName = in.readString(); | ||
this.importance = in.readDouble(); | ||
if (in.readBoolean()) { | ||
this.classImportance = in.readMap(StreamInput::readString, StreamInput::readDouble); | ||
} else { | ||
this.classImportance = null; | ||
} | ||
} | ||
|
||
public Map<String, Double> getClassImportance() { | ||
return classImportance; | ||
} | ||
|
||
public double getImportance() { | ||
return importance; | ||
} | ||
|
||
public String getFeatureName() { | ||
return featureName; | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
out.writeString(this.featureName); | ||
out.writeDouble(this.importance); | ||
out.writeBoolean(this.classImportance != null); | ||
if (this.classImportance != null) { | ||
out.writeMap(this.classImportance, StreamOutput::writeString, StreamOutput::writeDouble); | ||
} | ||
} | ||
|
||
public Map<String, Object> toMap() { | ||
Map<String, Object> map = new LinkedHashMap<>(); | ||
map.put(FEATURE_NAME, featureName); | ||
map.put(IMPORTANCE, importance); | ||
if (classImportance != null) { | ||
classImportance.forEach(map::put); | ||
} | ||
return map; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object object) { | ||
if (object == this) { return true; } | ||
if (object == null || getClass() != object.getClass()) { return false; } | ||
FeatureImportance that = (FeatureImportance) object; | ||
return Objects.equals(featureName, that.featureName) | ||
&& Objects.equals(importance, that.importance) | ||
&& Objects.equals(classImportance, that.classImportance); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(featureName, importance, classImportance); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.