** Funktionsbedeutungen ** können von ** Apache Spark ** mithilfe des folgenden baumbasierten Lernmodells berechnet werden.
GBTRegressionModel < / td> | Gradientenverstärkendes Baumregressionsmodell td> tr> |
GBTClassificationModel < / td> | Gradientenverstärkendes Baumklassifizierungsmodell td> tr> |
RandomForestRegressionModel < / td> | Zufälliges Waldregressionsmodell td> tr> |
RandomForestClassificationModel < / td> | Zufälliges Waldklassifizierungsmodell td> tr> |
DecisionTreeRegressionModel < / td> | Regressionsmodell des Entscheidungsbaums td> tr> |
DecisionTreeClassificationModel < / td> | Bestimmen des Baumklassifizierungsmodells td> tr> |
Der praktische Teil des Baumsystemalgorithmus besteht darin, dass [berechnet] werden kann (https: :), welche Variable beim Erstellen des Modells als Ergebnis des Trainings als "Wichtigkeit der Variablen (** Feature Importance **)" wichtig war. //web.stanford.edu/~hastie/ElemStatLearn/printings/ESLII_print12.pdf) (S.593).
Da jedoch zufällige Wälder und Bäume mit Gradientenverstärkung Methoden sind, die mehrere Modelle kombinieren, die als ** Ensemble-Lernen ** bezeichnet werden, entspricht die Bedeutung von Variablen (** Merkmalsbedeutung **) dem Regressionskoeffizienten. Es ist zu beachten, dass es sich nicht um einen Index für die Suche nach einer direkten Interpretation handelt.
Das Trainingsmodell, das durch Training von ** RandomForest ** in ** spark.ml ** erhalten wurde, z. B. ** RandomForestRegressionModel ** -Klasse, verfügt über die ** RandomForestRegressionModel # featureImportances ** -Methode, wenn Random Forest als Algorithmus verwendet wird. Gibt es.
Durch Aufrufen dieser Methode kann die Wichtigkeit der Variablen (** Feature Importance **) berechnet werden.
Übrigens ist der Rückgabewert der ** RandomForestRegressionModel # featureImportances ** -Methode vom Typ ** SparseVector **, und da der Vektor nur die numerische Komponente enthält, die die Wichtigkeit angibt, sind der numerische Wert und welche Variablen spezifisch. Es ist schwer zu verstehen, ob es unterstützt wird. Es ist schwer zu sagen, ob es da ist.
In diesem Dokument werden daher ** Funktionsbedeutungen ** mit Variablennamen verknüpft.
Bereiten Sie die Variablen, die an die Argumente übergeben werden sollen, in drei Schritten vor, um sie zuzuordnen.
Es wird davon ausgegangen, dass das Modellobjekt mit dem Namen randomForestRegressionModel unter der Voraussetzung erworben wurde, dass das Lernen abgeschlossen wurde.
** SCHRITT 1 ** Holen Sie sich zuerst ** Feature Importances ** wie folgt.
Vector importances=randomForestRegressionModel.featureImportances();
** SCHRITT 2 ** Als nächstes erhalten Sie den Variablennamen, der als Feature-Menge verwendet wird. (Da es sich um einen Variablennamen handelt, für den Sie sich ursprünglich entschieden haben, können Sie ihn hart codieren.)
String featuresCol = this.randomForestRegressionModel.getFeaturesCol()
** SCHRITT 3 ** Holen Sie sich endlich das Schema
StructType schema = predictions.schema();
Übergeben Sie die drei, die Sie gerade vorbereitet haben, an die folgende Methode. Diese Methode wird zum Verknüpfen (plus Sortieren) verwendet.
List<Importance> zipImportances(Vector featureImportances, String featuresCol, StructType schema) {
final int indexOfFeaturesCol = (Integer) schema.getFieldIndex(featuresCol).get();
final StructField featuresField = schema.fields()[indexOfFeaturesCol];
final Metadata metadata = featuresField
.metadata();
final Metadata featuresFieldAttrs = metadata
.getMetadata("ml_attr")
.getMetadata("attrs");
final Map<Integer, String> idNameMap = new HashMap<>();
final String[] fieldKeys = { "nominal", "numeric", "binary" };
final Collector<Metadata, ?, HashMap<Integer, String>> metaDataMapperFunc = Collectors
.toMap(
metaData -> (int) metaData.getLong("idx"), // key of map
metaData -> metaData.getString("name"), // value of map
(oldVal, newVal) -> newVal,
HashMap::new);
for (String fieldKey : fieldKeys) {
if (featuresFieldAttrs.contains(fieldKey)) {
idNameMap.putAll(Arrays
.stream(featuresFieldAttrs.getMetadataArray(fieldKey))
.collect(metaDataMapperFunc));
}
}
final double[] importanceScores = featureImportances.toArray();
final List<Importance> rawImportanceList = IntStream
.range(0, importanceScores.length)
.mapToObj(idx -> new Importance(idx, idNameMap.get(idx), importanceScores[idx], 0))
.collect(Collectors.toList());
final List<Importance> descSortedImportanceList = rawImportanceList
.stream()
.sorted(Comparator.comparingDouble((Importance ifeature) -> ifeature.score).reversed())
.collect(Collectors.toList());
for (int i = 0; i < descSortedImportanceList.size(); i++) {
descSortedImportanceList.get(i).rank = i;
}
final List<Importance> finalImportanceList;
switch (this.sort) {
case ASCENDING:
final List<Importance> ascSortedImportantFeatureList = descSortedImportanceList
.stream()
.sorted(Comparator.comparingDouble((Importance ifeature) -> ifeature.score))
.collect(Collectors.toList());
finalImportanceList = ascSortedImportantFeatureList;
break;
case DESCENDING:
finalImportanceList = descSortedImportanceList;
break;
case UNSORTED:
default:
finalImportanceList = rawImportanceList;
break;
}
return finalImportanceList;
}
Der Schlüssel zu dieser Methode lautet wie folgt.
final StructField featuresField = schema.fields()[indexOfFeaturesCol];
final Metadata metadata = featuresField
.metadata();
final Metadata featuresFieldAttrs = metadata
.getMetadata("ml_attr")
.getMetadata("attrs");
** Schema ** speichert die Struktur des Datensatzes, es gibt jedoch eine Variable als Merkmalsgröße zum Lernen, und die Metadaten (Entwurfsinformationen) davon werden extrahiert und die Position (Index) der Daten wird extrahiert. Und erhalten Sie die Zuordnungsinformationen der entsprechenden Variablen.
Was mit den tatsächlichen Metadaten passiert, kann im folgenden JSON-Format extrahiert werden. (Da sich das Format abhängig von dem in der Pipeline-Verarbeitung enthaltenen Transformer ändert, ist das folgende Beispiel)
MetaData-Beispiel(Beispiel bei der Vorhersage des Preises von Schmuckzubehör)
{
"ml_attr":{
"attrs":{
"numeric":[
{
"idx":0,
"name":"weight"
}
],
"nominal":[
{
"vals":[
"Platin",
"Gold",
"Silber",
"Dia"
],
"idx":1,
"name":"materialIndex"
},
{
"vals":[
"Brosche",
"Halskette",
"Ohrringe",
"Ring",
"Armband"
],
"idx":2,
"name":"shapeIndex"
},
{
"vals":[
"Inländische berühmte Marke",
"Übersee super berühmte Marke",
"Keine Marke",
"Berühmte Marken aus Übersee"
],
"idx":3,
"name":"brandIndex"
},
{
"vals":[
"Kaufhaus",
"Direkt verwalteter Laden",
"Billiger Laden"
],
"idx":4,
"name":"shopIndex"
}
]
},
"num_attrs":5
}
}
Wie Sie in diesen Daten sehen können, können Sie das Paar von ** idx ** und ** name ** erhalten. Wenn Sie es also mit ** Vector ** abbilden, das Sie mit der ** FeatureImportances ** -Methode erhalten haben, sieht es wie folgt aus. Aufgrund eines bestimmten Lernens ist es möglich zu wissen, wie wichtig der Variablenname (** Name ) ist ( Punktzahl **).
Erläuterung der Rangfolge der variablen Wichtigkeit
FeatureInfo [rank=0, score=0.3015643580333446, name=weight]
FeatureInfo [rank=1, score=0.2707593044437997, name=materialIndex]
FeatureInfo [rank=2, score=0.20696065038166056, name=brandIndex]
FeatureInfo [rank=3, score=0.11316392134864546, name=shapeIndex]
FeatureInfo [rank=4, score=0.10755176579254973, name=shopIndex]
Der Quellcode ist unten https://github.com/riversun/spark-ml-feature-importance-helper
Maven Auch im Maven-Repository erhältlich
<dependency>
<groupId>org.riversun</groupId>
<artifactId>spark-ml-feature-importance-helper</artifactId>
<version>1.0.0</version>
</dependency>
Recommended Posts