-Introduction à l'apprentissage automatique avec ** Java ** et ** Apache Spark **
C'est finalement la phase d'apprentissage automatique. Cette fois, nous allons créer un "moteur d'estimation de prix" qui fonctionne réellement.
Dernière fois a exécuté le processus de remplacement de la variable catégorielle représentée par la chaîne de caractères par une valeur numérique dans le pipeline.
Et comme le nom de la variable de catégorie numérisée a été traité de sorte que ** Index ** a été ajouté à la fin (suffixe), L'ensemble de données contient ** materialIndex, shapeIndex, brandIndex, shopIndex, weight, price ** comme variables de type numérique.
Dans cet exemple, nous voulons estimer (prédire) le prix de l'accessoire, mais les données à prévoir (** prix ** ici) sont appelées la ** variable objective **.
Lorsque vous souhaitez estimer (prédire) le prix d'un accessoire, qu'est-ce qui détermine le prix de l'accessoire?
Si l'accessoire est fait de diamant, il sera cher, et plus le bijou ou le métal précieux est lourd, plus il aura de valeur. De plus, si le produit est fabriqué par une marque célèbre, il est susceptible d'avoir une prime.
Comme vous pouvez le voir, il y a quelques raisons, c'est-à-dire ** causes **, au-dessus et en dessous du prix des accessoires.
Les données qui en sont la cause sont appelées la ** variable explicative **.
Cause: variable explicative Résultat ... Variable objective
Alors Les variables de l'ensemble de données sont divisées en variables explicatives et en variables objectives comme suit.
Variables explicatives ... ** materialIndex, shapeIndex, brandIndex, shopIndex, weight ** Objectif variable ・ ・ ・ ** prix **
Désormais, nous utiliserons ces données pour l'apprentissage.
L'apprentissage est une grande variété de méthodes permettant de découvrir et d'exprimer (bien que pas toujours compréhensibles par l'homme) les relations et les règles entre variables explicatives et variables objectives à l'aide de formules mathématiques et ** d'algorithmes d'apprentissage **. A été proposé.
La relation entre les variables explicatives et les variables objectives acquises par l'apprentissage est appelée le ** modèle d'apprentissage ** (ou modèle d'apprentissage automatique, ou simplement le modèle).
Bien sûr, pour démêler et approximer des relations inconnues, il doit y avoir une quantité considérable de données, donc l'apprentissage automatique est égal ou supérieur à l'algorithme ** la quantité et la qualité des données sont importantes **. C'est dit.
Cette fois-ci, nous préparerons ** l'arbre d'amplification du gradient ** en tant qu'algorithme d'apprentissage et ** 500 données sur le prix des accessoires (aucune valeur manquante) ** en tant que données.
Lorsque la variable objectif (= prix) que vous souhaitez prédire par apprentissage automatique est une valeur continue comme cette fois, une telle prédiction est appelée ** régression ** (régression).
Et le modèle d'apprentissage de la régression s'appelle ** Regressor **.
En revanche, lorsque la variable objectif est binaire ou lorsque plusieurs classes (catégories) sont requises, on parle de ** classification ** (classification). Le modèle d'apprentissage pour la classification est appelé ** Classificateur **.
Il traite plusieurs variables (colonnes) en une seule pour une utilisation dans l'apprentissage.
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;
}
}
** (1) ** ・ ・ ・ *** StringIndexer *** Les noms de colonne de sortie (outputCol) sont regroupés dans un tableau. Ce sera un tableau de noms de colonnes de variables catégorielles quantifiées comme indiqué ci-dessous.
[materialIndex,shapeIndex,brandIndex,shopIndex]
** (2) ** ・ ・ ・ Un tableau de noms de colonnes qui prennent une variable numérique. Cette fois seulement ** poids **
** (3) ** ・ ・ ・ Vectoriser plusieurs variables de type numérique.
Pour *** VectorAssembler # setInputCols *, spécifiez le nom de la colonne que vous souhaitez vectoriser. Ici, tous les noms de colonne ( materialIndex, shapeIndex, brandIndex, shopIndex, weight **) qui sont candidats pour les variables explicatives sont spécifiés [^ 1].
[^ 1]: Selon l'algorithme d'apprentissage automatique, il peut ne pas être possible de bien apprendre à moins d'avoir une bonne compréhension des variables explicatives et de sélectionner les variables explicatives (Sélection des fonctionnalités). Par exemple, une forte corrélation entre les variables explicatives peut poser le problème de la colinéarité multiple (multico). Cette fois, l'algorithme est un système d'arbre de décision (modèle non linéaire) et c'est une partie introductive, j'ai donc inclus toutes les variables explicatives candidates. *** fonction de tableau *** est une fonction pour joindre des tableaux. Le résultat vectorisé est ajouté à l'ensemble de données en tant que nom de colonne spécifié par *** setOutputCol ***.
VectorAssembler assembler = new VectorAssembler()// (3)
.setInputCols(array(indexedCategoricalColNames, numericColNames))
.setOutputCol("features");
** (5) - (7) ** ・ ・ ・ Set ** StringIndexer ** et ** VectorAssembler ** dans ** Pipeline **.
PipelineStage[] indexerStages = stringIndexers.toArray(new PipelineStage[0]);// (5)
PipelineStage[] pipelineStages = array(indexerStages, assembler);// (6)
Pipeline pipeline = new Pipeline().setStages(pipelineStages);// (7)
** (8) ** ・ ・ ・ Exécuter ce traitement de pipeline
Le résultat de l'exécution est le suivant.
Vous pouvez voir qu'une colonne vectorielle appelée ** features ** a été ajoutée.
En d'autres termes, *** VectorAssembler *** fait de plusieurs variables ** weight, materialIndex, shapeIndex, brandIndex, shopIndex ** un seul vecteur avec le nom "** features **".
Ces ** données similaires aux caractéristiques ** sont appelées un ** vecteur de caractéristiques **.
Eh bien, je suis enfin prêt Enfin ** construisez un modèle d'apprentissage ** et prévoyez réellement ** le prix des accessoires ** (retour).
Immédiatement, le code d'apprentissage et de prédiction ressemble à ceci:
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;
}
}
** (1) ** ・ ・ ・ Créez un estimateur pour ** l'arbre d'amplification de gradient ** pour un apprentissage supervisé. Pour *** setLabelCol *, spécifiez le nom de la colonne ( prix **) que vous souhaitez prédire. Pour *** setFeaturesCol *, spécifiez le nom de colonne ( features ) du vecteur de caractéristiques. *** setPredictionCol *** spécifie un nouveau nom de colonne ( prediction **) pour stocker les résultats de la prédiction.
GBTRegressor gbtr = new GBTRegressor()// (1)
.setLabelCol("price")
.setFeaturesCol("features")
.setPredictionCol("prediction");
** (2) ** ・ ・ ・ Ajout d'un apprenant (** gbt **) à Pipeline. Désormais, en plus de l'indexation des variables catégorielles et du traitement de vectorisation, l'apprenant est également ajouté lors de la formation.
PipelineStage[] pipelineStages = array(indexerStages, assembler, gbtr);// (2)
Pipeline pipeline = new Pipeline().setStages(pipelineStages);
** (3) ** ・ ・ ・ *** dataset.randomSplit *** divise l'ensemble de données d'origine de manière aléatoire dans un rapport de 70%: 30%
** (4) ** ・ ・ ・ Sur l'ensemble de données divisé, 70% sont utilisés comme données d'entraînement.
** (5) ** ・ ・ ・ Sur l'ensemble de données divisé, 30% sont utilisés comme données de test.
** (6) ** ・ ・ ・ *** Pipeline.fit *** pour mettre les données d'entraînement dans le formateur et l'entraîner. Après la formation, *** pipelineModel *** peut être obtenu en tant que ** modèle d'apprentissage ** entraîné (modèle d'apprentissage automatique). Vous pourrez effectuer une régression (prédiction du ** prix **) à l'aide de ce ** modèle d'apprentissage **.
PipelineModel pipelineModel = pipeline.fit(trainingData);// (6)
** (7) ** ・ ・ ・ *** Exécuter ** prédiction ** (retour) en utilisant le modèle entraîné avec pipelineModel.transform (testData) ***! Prédisez le prix de l'accessoire dans les données de test spécifiées ici. Un ensemble de données contenant les résultats de la prédiction (spécifiquement, la colonne ** prediction **) est renvoyé.
Dataset<Row> predictions = pipelineModel.transform(testData);// (7)
** (8) ** ・ ・ ・ Afficher le résultat de l'exécution. Dans *** show ***, le nom de la colonne que vous souhaitez afficher est spécifié et affiché.
Oui, le résultat d'exécution prévu est le suivant
La ** prédiction ** à l'extrême droite du tableau et le ** prix ** à la seconde à partir de la droite sont les résultats de prédiction de l'apprentissage automatique et les réponses contenues dans les données d'origine, respectivement.
La différence entre ** prédiction ** et ** prix ** est la différence entre la prédiction et la réponse, mais je pense que vous pouvez prédire une valeur proche de cela.
Je ne l'ai pas réglé en particulier, mais j'ai fait un simple "moteur d'estimation du prix des accessoires" ^ _ ^
** Continuer à la prochaine fois **
La prochaine fois, j'aimerais traiter des ** indicateurs d'évaluation des résultats d'apprentissage, du réglage des hyper paramètres et de la recherche de grille **.
Recommended Posts