[JAVA] Einführung in das maschinelle Lernen mit Spark "Preisschätzung" # 3 Lernen wir mit Trainingsdaten und erstellen eine [Preisschätzungs-Engine]

Überblick

-Einführung in das maschinelle Lernen mit ** Java ** und ** Apache Spark ** --Hand-on von der Verwendung von ** Apache Spark ** bis zum tatsächlichen maschinellen Lernen (Lernen, Regression) mit einer auf "Preisschätzung" basierenden Step-up-Methode --Verwenden Sie den ** Gradientenverstärkungsbaum ** des ** überwachten Lernens ** für den Algorithmus für maschinelles Lernen --Posten Sie die Step-up-Methode mehrmals

Umgebung

Erstellen Sie ein Modell für maschinelles Lernen

Es ist endlich die maschinelle Lernphase. Dieses Mal werden wir eine "Preisschätzungs-Engine" erstellen, die tatsächlich funktioniert.

Letztes Mal hat einen Prozess in der Pipeline ausgeführt, um die durch Zeichenfolgen dargestellten kategorialen Variablen durch Zahlen zu ersetzen.

Und da der Name der digitalisierten Kategorievariablen so verarbeitet wurde, dass am Ende ** Index ** hinzugefügt wurde (Suffix), Der Datensatz enthält ** materialIndex, shapeIndex, brandIndex, shopIndex, weight, price ** als numerische Typvariablen.

Erklärende und objektive Variablen

In diesem Beispiel möchten wir den Preis des Zubehörs schätzen (vorhersagen), aber die vorherzusagenden Daten (** Preis ** hier) werden als ** Zielvariable ** bezeichnet.

Was bestimmt den Preis des Zubehörs, wenn Sie den Preis eines Zubehörs schätzen (vorhersagen) möchten?

Wenn das Accessoire aus Diamant besteht, ist es teuer, und je schwerer der Schmuck oder das Edelmetall ist, desto wertvoller ist es. Wenn das Produkt von einer bekannten Marke hergestellt wird, hat es wahrscheinlich eine Prämie.

Wie Sie sehen können, gibt es einige Gründe, dh ** Ursachen **, die über und unter dem Preis für Zubehör liegen.

Die Daten, die dies verursachen, werden als ** erklärende Variable ** bezeichnet.

Ursache: Erklärende Variable Ergebnis ... Zielvariable

Damit Die Variablen im Datensatz werden wie folgt in die erklärenden Variablen und die objektiven Variablen unterteilt.

Erklärende Variablen ... ** materialIndex, shapeIndex, brandIndex, shopIndex, weight ** Zielvariable ・ ・ ・ ** Preis **

image.png

Von nun an werden wir diese Daten zum Lernen verwenden.

Lernen ist eine Vielzahl von Methoden, indem es ermöglicht wird, die Beziehungen und Regeln zwischen erklärenden Variablen und objektiven Variablen mithilfe mathematischer Formeln und ** Lernalgorithmen ** zu entdecken und auszudrücken (obwohl dies nicht immer für den Menschen verständlich ist). Wurde vorgeschlagen.

Die Beziehung zwischen den erklärenden Variablen und den durch das Lernen erfassten objektiven Variablen wird als ** Lernmodell ** (oder maschinelles Lernmodell oder einfach als Modell) bezeichnet.

Natürlich muss eine beträchtliche Datenmenge vorhanden sein, um unbekannte Beziehungen zu entschlüsseln und zu approximieren. Daher ist maschinelles Lernen gleich oder größer als der Algorithmus ** Quantität und Qualität der Daten sind wichtig **. Es wird gesagt.

Dieses Mal werden wir ** Gradientenverstärkungsbaum ** als Lernalgorithmus und ** 500 zusätzliche Preisdaten (keine fehlenden Werte) ** als Daten vorbereiten.

Rückkehr

Wenn die Zielvariable (= Preis), die Sie durch maschinelles Lernen vorhersagen möchten, ein kontinuierlicher Wert wie dieser ist, wird diese Vorhersage als ** Regression ** (Regression) bezeichnet.

Und das Lernmodell für die Regression heißt ** Regressor **.

Wenn die Zielvariable dagegen zwei Werte hat oder mehrere Klassen (Kategorien) erforderlich sind, wird sie als ** Klassifizierung ** (Klassifizierung) bezeichnet. Das Lernmodell für die Klassifizierung heißt ** Classifier **.

Erstellen Sie einen Feature-Vektor

Es verarbeitet mehrere Variablen (Spalten) zu einer, um sie beim Lernen zu verwenden.


import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.spark.ml.Pipeline;
import org.apache.spark.ml.PipelineStage;
import org.apache.spark.ml.feature.StringIndexer;
import org.apache.spark.ml.feature.VectorAssembler;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;

public class GBTRegressionStep03_part01 {

  public static void main(String[] args) {

    System.setProperty("hadoop.home.dir", "c:\\Temp\\winutil\\");// for windows

    org.apache.log4j.Logger.getLogger("org").setLevel(org.apache.log4j.Level.ERROR);
    org.apache.log4j.Logger.getLogger("akka").setLevel(org.apache.log4j.Level.ERROR);

    SparkSession spark = SparkSession
        .builder()
        .appName("GradientBoostingTreeGegression")
        .master("local[*]")
        .getOrCreate();

    Dataset<Row> dataset = spark
        .read()
        .format("csv")
        .option("header", "true")
        .option("inferSchema", "true")
        .load("dataset/gem_price_ja.csv");

    List<String> categoricalColNames = Arrays.asList("material", "shape", "brand", "shop");

    List<StringIndexer> stringIndexers = categoricalColNames.stream()
        .map(col -> new StringIndexer()
            .setStringOrderType("frequencyDesc")
            .setInputCol(col)
            .setOutputCol(col + "Index"))
        .collect(Collectors.toList());

    String[] indexedCategoricalColNames = stringIndexers// (1)
        .stream()
        .map(StringIndexer::getOutputCol)
        .toArray(String[]::new);

    String[] numericColNames = new String[] { "weight" };// (2)

    VectorAssembler assembler = new VectorAssembler()// (3)
        .setInputCols(array(indexedCategoricalColNames, numericColNames))
        .setOutputCol("features");

    PipelineStage[] indexerStages = stringIndexers.toArray(new PipelineStage[0]);// (5)

    PipelineStage[] pipelineStages = array(indexerStages, assembler);// (6)

    Pipeline pipeline = new Pipeline().setStages(pipelineStages);// (7)

    pipeline.fit(dataset).transform(dataset).show(10);// (8)

  }

  @SuppressWarnings("unchecked")
  public static <T> T[] array(final T[] array1, final T... array2) {
    final Class<?> type1 = array1.getClass().getComponentType();
    final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
    System.arraycopy(array1, 0, joinedArray, 0, array1.length);
    System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
    return joinedArray;
  }
}

Codekommentar

** (1) ** In ・ ・ *** StringIndexer *** Die Spaltennamen der Ausgabe (outputCol) werden zu einem Array zusammengefasst. Es wird ein Array von Spaltennamen von kategorialen Variablen sein, die wie unten gezeigt quantifiziert werden.

[materialIndex,shapeIndex,brandIndex,shopIndex]

** (2) ** ・ ・ ・ Ein Array von Spaltennamen, die eine numerische Variable annehmen. Diesmal nur ** Gewicht **

** (3) ** ector ・ ・ Vektorisieren Sie mehrere numerische Variablen.

Geben Sie für *** VectorAssembler # setInputCols *** den Spaltennamen an, den Sie vektorisieren möchten. Hier werden alle Spaltennamen (** materialIndex, shapeIndex, brandIndex, shopIndex, weight **) angegeben, die Kandidaten für erklärende Variablen sind [^ 1].

[^ 1]: Abhängig vom Algorithmus für maschinelles Lernen ist es möglicherweise nicht möglich, gut zu lernen, es sei denn, Sie haben ein gutes Verständnis der erklärenden Variablen und wählen die erklärenden Variablen aus (Funktionsauswahl). Beispielsweise kann eine hohe Korrelation zwischen erklärenden Variablen das Problem der multiplen Co-Linearität (Multico) verursachen. Diesmal ist der Algorithmus ein Entscheidungsbaumsystem (nichtlineares Modell) und ein einleitender Teil, daher habe ich alle erklärenden Variablenkandidaten aufgenommen. *** Array-Funktion *** ist eine Funktion zum Verbinden von Arrays. Das vektorisierte Ergebnis wird dem Datensatz als der durch *** setOutputCol *** angegebene Spaltenname hinzugefügt.

VectorAssembler assembler = new VectorAssembler()// (3)
    .setInputCols(array(indexedCategoricalColNames, numericColNames))
    .setOutputCol("features");

** (5) - (7) ** ・ ・ ・ Setze ** StringIndexer ** und ** VectorAssembler ** in ** Pipeline **.

PipelineStage[] indexerStages = stringIndexers.toArray(new PipelineStage[0]);// (5)
PipelineStage[] pipelineStages = array(indexerStages, assembler);// (6)
Pipeline pipeline = new Pipeline().setStages(pipelineStages);// (7)

** (8) ** ・ ・ ・ Führen Sie diese Pipeline-Verarbeitung aus

Das Ausführungsergebnis ist wie folgt.

image.png

Sie können sehen, dass eine Vektorspalte mit dem Namen ** Features ** hinzugefügt wurde.

Mit anderen Worten, *** VectorAssembler *** macht mehrere Variablen ** weight, materialIndex, shapeIndex, brandIndex, shopIndex ** zu einem einzelnen Vektor mit dem Namen "** features **".

image.png

Diese ** Merkmale ** - ähnlichen Daten werden als ** Merkmalsvektor ** bezeichnet.

Erstellen Sie ein Lernmodell und prognostizieren Sie Preise

Nun, ich bin endlich bereit Schließlich ** ein Lernmodell erstellen ** und tatsächlich ** den Preis für Zubehör ** vorhersagen ** (Rendite).

Der Lern- und Vorhersagecode sieht sofort so aus:


import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.spark.ml.Pipeline;
import org.apache.spark.ml.PipelineModel;
import org.apache.spark.ml.PipelineStage;
import org.apache.spark.ml.feature.StringIndexer;
import org.apache.spark.ml.feature.VectorAssembler;
import org.apache.spark.ml.regression.GBTRegressor;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;

public class GBTRegressionStep03_part02 {

  public static void main(String[] args) {

    SparkSession spark = SparkSession
        .builder()
        .appName("GradientBoostingTreeGegression")
        .master("local[*]")
        .getOrCreate();

    Dataset<Row> dataset = spark
        .read()
        .format("csv")
        .option("header", "true")
        .option("inferSchema", "true")
        .load("dataset/gem_price_ja.csv");

    List<String> categoricalColNames = Arrays.asList("material", "shape", "brand", "shop");

    List<StringIndexer> stringIndexers = categoricalColNames.stream()
        .map(col -> new StringIndexer()
            .setStringOrderType("frequencyDesc")
            .setInputCol(col)
            .setOutputCol(col + "Index"))
        .collect(Collectors.toList());

    String[] indexedCategoricalColNames = stringIndexers
        .stream()
        .map(StringIndexer::getOutputCol)
        .toArray(String[]::new);

    String[] numericColNames = new String[] { "weight" };

    VectorAssembler assembler = new VectorAssembler()
        .setInputCols(array(indexedCategoricalColNames, numericColNames))
        .setOutputCol("features");

    GBTRegressor gbtr = new GBTRegressor()// (1)
        .setLabelCol("price")
        .setFeaturesCol("features")
        .setPredictionCol("prediction");

    PipelineStage[] indexerStages = stringIndexers.toArray(new PipelineStage[0]);

    PipelineStage[] pipelineStages = array(indexerStages, assembler, gbtr);// (2)

    Pipeline pipeline = new Pipeline().setStages(pipelineStages);

    long seed = 0;

    Dataset<Row>[] splits = dataset.randomSplit(new double[] { 0.7, 0.3 }, seed);// (3)

    Dataset<Row> trainingData = splits[0];// (4)
    Dataset<Row> testData = splits[1];// (5)

    PipelineModel pipelineModel = pipeline.fit(trainingData);// (6)

    Dataset<Row> predictions = pipelineModel.transform(testData);// (7)

    predictions.select("id", "material", "shape", "weight", "brand", "shop", "price", "prediction").show(10);// (8)

  }

  @SuppressWarnings("unchecked")
  public static <T> T[] array(final T[] array1, final T... array2) {
    final Class<?> type1 = array1.getClass().getComponentType();
    final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
    System.arraycopy(array1, 0, joinedArray, 0, array1.length);
    System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
    return joinedArray;
  }
}

Codekommentar

** (1) ** ・ ・ ・ Erstellen Sie einen Schätzer für den ** Gradientenverstärkungsbaum ** für überwachtes Lernen. Geben Sie für *** setLabelCol *** den Spaltennamen (** Preis ) an, den Sie vorhersagen möchten. Geben Sie für *** setFeaturesCol *** den Spaltennamen ( Features ) des Feature-Vektors an. *** setPredictionCol *** gibt einen neuen Spaltennamen ( Vorhersage **) zum Speichern der Vorhersageergebnisse an.

 GBTRegressor gbtr = new GBTRegressor()// (1)
        .setLabelCol("price")
        .setFeaturesCol("features")
        .setPredictionCol("prediction");

** (2) ** ・ ・ ・ Pipeline wurde ein Lernender (** gbt **) hinzugefügt. Zusätzlich zur kategorialen Variablenindizierung und Vektorisierungsverarbeitung wird der Lernende jetzt auch während des Trainings hinzugefügt.

PipelineStage[] pipelineStages = array(indexerStages, assembler, gbtr);// (2)
Pipeline pipeline = new Pipeline().setStages(pipelineStages);

** (3) ** datas ・ ・ *** dataset.randomSplit *** teilt den ursprünglichen Datensatz zufällig in einem Verhältnis von 70%: 30%

** (4) ** ・ ・ ・ 70% des geteilten Datensatzes werden als Trainingsdaten verwendet.

** (5) ** ・ ・ ・ Vom geteilten Datensatz werden 30% als Testdaten verwendet.

** (6) ** Pipeline ・ ・ *** Pipeline.fit ***, um die Trainingsdaten in den Trainer zu übertragen und zu trainieren. Nach dem Training kann *** PipelineModel *** als trainiertes ** Lernmodell ** (maschinelles Lernmodell) erhalten werden. Mit diesem ** Lernmodell ** können Sie eine Regression (Vorhersage des ** Preises **) durchführen.

PipelineModel pipelineModel = pipeline.fit(trainingData);// (6)

** (7) ** ・ ・ ・ *** Führe ** Vorhersage ** (Rückkehr) mit dem trainierten Modell mit PipelineModel.transform (testData) *** aus! Sagen Sie den Preis des Zubehörs in den hier angegebenen Testdaten voraus. Ein Datensatz, der die Vorhersageergebnisse enthält (insbesondere die Spalte ** Vorhersage **), wird zurückgegeben.

Dataset<Row> predictions = pipelineModel.transform(testData);// (7)

** (8) ** ・ ・ ・ Zeigt das Ausführungsergebnis an. In *** show *** wird der Spaltenname, den Sie anzeigen möchten, angegeben und angezeigt.

Ja, das vorhergesagte Ausführungsergebnis lautet wie folgt

image.png

Die ** Vorhersage ** ganz rechts in der Tabelle und der ** Preis ** ganz rechts in der Tabelle sind die Vorhersageergebnisse aus maschinellem Lernen und die in den Originaldaten enthaltenen Antworten.

image.png

Der Unterschied zwischen ** Vorhersage ** und ** Preis ** ist der Unterschied zwischen der Vorhersage und der Antwort, aber ich denke, Sie können einen Wert vorhersagen, der nahe daran liegt.

Ich habe es nicht speziell eingestellt, aber ich habe eine einfache "Zubehör-Preisschätzungs-Engine" erstellt ^ _ ^

** Weiter zum nächsten Mal **

Das nächste Mal möchte ich mich mit ** Bewertungsindikatoren für Lernergebnisse, Hyperparameter-Tuning und Rastersuche ** befassen.

Recommended Posts

Einführung in das maschinelle Lernen mit Spark "Preisschätzung" # 3 Lernen wir mit Trainingsdaten und erstellen eine [Preisschätzungs-Engine]
Einführung in das maschinelle Lernen mit Spark "Price Estimation" # 2 Datenvorverarbeitung (Umgang mit Kategorievariablen)
Erste Schritte mit maschinellem Lernen mit Spark "Preisschätzung" # 1 Laden von Datensätzen mit Apache Spark (Java)
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 3 ~ Übung ~ erstellt
Ruby mit AtCoder lernen 13 So erstellen Sie ein zweidimensionales Array
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 2 ~ Grundlegende Schreibweise für Dash ~ erstellt
Ich habe versucht, eine Anwendung für maschinelles Lernen mit Dash (+ Docker) Teil 1 ~ Umgebungskonstruktion und Funktionsprüfung ~ zu erstellen
[Einführung in Docker] Erstellen Sie ein Docker-Image für maschinelles Lernen und verwenden Sie das Jupyter-Notizbuch
[Maschinelles Lernen mit Apache Spark] Sparse Vector (spärlicher Vektor) und Dense Vector (dichter Vektor)
[Einführung in die Android App-Entwicklung] Machen wir einen Zähler