Spark MLlibによる機械学習

1. 概要

このチュートリアルでは、https://spark.apache.org/mllib/ [Apache Spark MLlib]を活用して機械学習製品を開発する方法を理解します。 Spark MLlibを使用して簡単な機械学習製品を開発し、コアコンセプトを示します。

2. 機械学習の簡単な入門書

機械学習は、*人工知能*として知られるより広範な傘の一部です。 機械学習とは、パターンと推論で特定の問題を解決するための*統計モデルの研究を指します。 これらのモデルは、問題空間から抽出されたトレーニングデータによって特定の問題に対して「トレーニング」されます。
この定義を正確に理解するために、例を取り上げます。

2.1. 機械学習のカテゴリ

アプローチに基づいて、機械学習を教師ありと教師なし*のカテゴリーに広く分類できます。 他のカテゴリもありますが、次の2つに専念します。
  • 教師あり学習*両方を含むデータのセットで動作します
    入力と必要な出力* —たとえば、プロパティのさまざまな特性と予想される賃貸収入を含むデータセット。 教師あり学習は、分類と回帰と呼ばれる2つの広範なサブカテゴリにさらに分けられます。

  • 分類アルゴリズムは、次のようなカテゴリ出力に関連しています
    プロパティが占有されているかどうか

  • 回帰アルゴリズムは、次のような連続出力範囲に関連しています
    プロパティの値

  • 一方、教師なし学習は、一連のデータで動作します
    入力値のみがあります
    。 入力データの固有の構造を識別しようとすることで機能します。 たとえば、消費行動のデータセットからさまざまなタイプの消費者を見つけます。

2.2. 機械学習のワークフロー

機械学習はまさに学際的な研究分野です。 ビジネスドメイン、統計、確率、線形代数、プログラミングの知識が必要です。 これは明らかに圧倒的になる可能性があるため、*通常は機械学習ワークフローと呼ばれる、規則正しい方法でこれにアプローチするのが最善です:
link:/uploads/Machine-Learning-Workflow-1-100x36.jpg%20100w []
ご覧のとおり、すべての機械学習プロジェクトは、明確に定義された問題ステートメントから開始する必要があります。 これに続いて、問題に潜在的に答えることができるデータに関連する一連のステップを実行する必要があります。
次に、通常、問題の性質を考慮したモデルを選択します。 これに続いて、一連のモデルのトレーニングと検証が行われます。これは、モデルの微調整として知られています。 最後に、以前に見えなかったデータでモデルをテストし、満足のいくものであれば本番に展開します。

3. Spark MLlibとは何ですか?

Spark MLlibは、*機械学習のプリミティブ*をAPIとして提供する* Spark Core上のモジュールです。 機械学習は通常、モデルトレーニングのために大量のデータを処理します。
Sparkのベースコンピューティングフレームワークは大きなメリットです。 さらに、MLlibは一般的な機械学習と統計アルゴリズムのほとんどを提供します。 これにより、大規模な機械学習プロジェクトでの作業が大幅に簡素化されます。

4. MLlibによる機械学習

これで、機械学習とMLlibがこの取り組みにどのように役立つかについての十分なコンテキストが得られました。 Spark MLlibで機械学習プロジェクトを実装する基本的な例から始めましょう。
機械学習のワークフローに関する議論から思い出すと、問題のステートメントから始めて、次にデータに移るべきです。 幸いなことに、機械学習の「hello world」、https://archive.ics.uci.edu/ml/datasets/Iris [Iris Dataset]を選択します。 これは多変量ラベル付きデータセットで、アイリスの異なる種のがく片と花びらの長さと幅で構成されています。
これにより、問題の目的がわかります。*がく片と花びらの長さと幅からアヤメの種を予測できますか?

4.1. 依存関係の設定

まず、次のhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.apache.spark%22%20AND%20a%3A%22spark-mllib_2.11を定義する必要があります%22 [Mavenの依存関係]を使用して、関連するライブラリをプルします。
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-mllib_2.11</artifactId>
    <version>2.4.3</version>
    <scope>provided</scope>
</dependency>
また、Spark APIを使用するには、SparkContextを初期化する必要があります。
SparkConf conf = new SparkConf()
  .setAppName("Main")
  .setMaster("local[2]");
JavaSparkContext sc = new JavaSparkContext(conf);

4.2. データの読み込み

まず最初に、CSV形式のテキストファイルとして利用可能なデータをダウンロードする必要があります。 次に、このデータをSparkにロードする必要があります。
String dataFile = "data\\iris.data";
JavaRDD<String> data = sc.textFile(dataFile);
Spark MLlibは、入力データと対応するラベルを表すために、ローカルと分散の両方のいくつかのデータ型を提供します。 最も単純なデータ型は_Vector_です。
JavaRDD<Vector> inputData = data
  .map(line -> {
      String[] parts = line.split(",");
      double[] v = new double[parts.length - 1];
      for (int i = 0; i < parts.length - 1; i++) {
          v[i] = Double.parseDouble(parts[i]);
      }
      return Vectors.dense(v);
});
ここでは、主に統計分析を実行するために、入力フィーチャのみを含めていることに注意してください。
トレーニング例は通常、クラス_LabeledPoint_で表される複数の入力フィーチャとラベルで構成されます。
Map<String, Integer> map = new HashMap<>();
map.put("Iris-setosa", 0);
map.put("Iris-versicolor", 1);
map.put("Iris-virginica", 2);

JavaRDD<LabeledPoint> labeledData = data
  .map(line -> {
      String[] parts = line.split(",");
      double[] v = new double[parts.length - 1];
      for (int i = 0; i < parts.length - 1; i++) {
          v[i] = Double.parseDouble(parts[i]);
      }
      return new LabeledPoint(map.get(parts[parts.length - 1]), Vectors.dense(v));
});
データセットの出力ラベルはテキストであり、アイリスの種を示しています。 これを機械学習モデルにフィードするには、これを数値に変換する必要があります。

4.3. 探索的データ分析

探索的データ分析には、利用可能なデータの分析が含まれます。 現在、*機械学習アルゴリズムはデータ品質に敏感です*。したがって、高品質のデータほど望ましい結果を提供する可能性が高くなります。
典型的な分析目的には、異常の除去とパターンの検出が含まれます。 これは、利用可能なデータから有用な機能に到達するための機能エンジニアリングの重要なステップにさえつながります。
この例のデータセットは小さく、整形式です。 したがって、多くのデータ分析にinする必要はありません。 ただし、Spark MLlibにはAPIが装備されており、非常に洞察を提供します。
簡単な統計分析から始めましょう。
MultivariateStatisticalSummary summary = Statistics.colStats(inputData.rdd());
System.out.println("Summary Mean:");
System.out.println(summary.mean());
System.out.println("Summary Variance:");
System.out.println(summary.variance());
System.out.println("Summary Non-zero:");
System.out.println(summary.numNonzeros());
ここでは、特徴の平均と分散を観察しています。 これは、機能の正規化を実行する必要があるかどうかを判断するのに役立ちます。 *同様の規模ですべての機能を使用すると便利です*。 また、モデルのパフォーマンスに悪影響を与える可能性のあるゼロ以外の値にも注意しています。
入力データの出力は次のとおりです。
Summary Mean:
[5.843333333333332,3.0540000000000003,3.7586666666666666,1.1986666666666668]
Summary Variance:
[0.6856935123042509,0.18800402684563744,3.113179418344516,0.5824143176733783]
Summary Non-zero:
[150.0,150.0,150.0,150.0]
分析するもう1つの重要な指標は、入力データの特徴間の相関です。
Matrix correlMatrix = Statistics.corr(inputData.rdd(), "pearson");
System.out.println("Correlation Matrix:");
System.out.println(correlMatrix.toString());
任意の2つの機能間の高い相関関係は、増分値を追加していないことを示しており、そのうちの1つを削除できます。 機能の相関関係は次のとおりです。
Correlation Matrix:
1.0                   -0.10936924995064387  0.8717541573048727   0.8179536333691672
-0.10936924995064387  1.0                   -0.4205160964011671  -0.3565440896138163
0.8717541573048727    -0.4205160964011671   1.0                  0.9627570970509661
0.8179536333691672    -0.3565440896138163   0.9627570970509661   1.0

4.4. データを分割する

機械学習のワークフローの説明を思い出すと、モデルのトレーニングと検証のいくつかの反復に続いて最終テストが行​​われます。
そのためには、*トレーニングデータをトレーニング、検証、テストセットに分割する必要があります*。 物事を単純にするために、検証部分はスキップします。 それでは、データをトレーニングセットとテストセットに分けましょう。
JavaRDD<LabeledPoint>[] splits = parsedData.randomSplit(new double[] { 0.8, 0.2 }, 11L);
JavaRDD<LabeledPoint> trainingData = splits[0];
JavaRDD<LabeledPoint> testData = splits[1];

4.5. モデルトレーニング

それで、データセットを分析して準備する段階に達しました。 あとは、これをモデルにフィードして、マジックを開始するだけです! まあ、言うより簡単だ。 問題に適したアルゴリズムを選択する必要があります。先ほど述べた機械学習のさまざまなカテゴリを思い出してください。
*私たちの問題が監視対象カテゴリ内の分類に適合することを理解することは難しくありません*。 現在、このカテゴリで使用できるアルゴリズムはかなりあります。
それらの中で最も単純なものはロジスティック回帰です(回帰という言葉は私たちを混乱させないようにしましょう。結局のところ、分類アルゴリズムです)。
LogisticRegressionModel model = new LogisticRegressionWithLBFGS()
  .setNumClasses(3)
  .run(trainingData.rdd());
ここでは、3クラスの限定メモリBFGSベースの分類子を使用しています。 このアルゴリズムの詳細はこのチュートリアルの範囲外ですが、これは最も広く使用されているものの1つです。

4.6. モデル評価

モデルのトレーニングには複数の反復が含まれることを忘れないでください。ただし、簡単にするために、ここでは単一のパスを使用しました。 モデルのトレーニングが完了したので、テストデータセットでこれをテストします。
JavaPairRDD<Object, Object> predictionAndLabels = testData
  .mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));
MulticlassMetrics metrics = new MulticlassMetrics(predictionAndLabels.rdd());
double accuracy = metrics.accuracy();
System.out.println("Model Accuracy on Test Data: " + accuracy);
さて、モデルの有効性をどのように測定しますか? *使用できるいくつかのメトリックがありますが、最も単純なものの1つは精度*です。 簡単に言えば、精度は予測の正しい数と予測の総数の比率です。 モデルの1回の実行で達成できることは次のとおりです。
Model Accuracy on Test Data: 0.9310344827586207
アルゴリズムの確率的性質のため、これは実行ごとにわずかに異なることに注意してください。
ただし、一部の問題領域では、精度はあまり効果的なメトリックではありません。 他の*より洗練されたメトリックは、Precision and Recall(F1 Score)、ROC Curve、およびConfusion Matrix *です。

4.7. モデルの保存と読み込み

最後に、訓練されたモデルをファイルシステムに保存し、実稼働データの予測のためにロードする必要があります。 これはSparkでは簡単です:
model.save(sc, "model\\logistic-regression");
LogisticRegressionModel sameModel = LogisticRegressionModel
  .load(sc, "model\\logistic-regression");
Vector newData = Vectors.dense(new double[]{1,1,1,1});
double prediction = sameModel.predict(newData);
System.out.println("Model Prediction on New Data = " + prediction);
そのため、モデルをファイルシステムに保存し、ロードし直しています。 ロード後、モデルをすぐに使用して、新しいデータの出力を予測できます。 ランダムな新しいデータのサンプル予測は次のとおりです。
Model Prediction on New Data = 2.0

5. 原始的な例を超えて

実施した例では、機械学習プロジェクトのワークフローを幅広く取り上げていますが、多くの微妙で重要なポイントが残っています。 ここで詳細に議論することはできませんが、重要なもののいくつかを確実に検証することができます。
APIを介したSpark MLlibは、これらすべての分野で広範なサポートを提供しています。

5.1. モデル選択

モデルの選択は、多くの場合、複雑で重要なタスクの1つです。 モデルのトレーニングは複雑なプロセスであり、望ましい結果が得られると確信しているモデルで行う方がはるかに優れています。
問題の性質は、選択する機械学習アルゴリズムのカテゴリを特定するのに役立ちますが、完全な仕事ではありません。 前に見たように、分類などのカテゴリ内では、*多くの場合、選択可能な多くの異なるアルゴリズムとそのバリエーションがあります*。
多くの場合、*最善のアクションは、より小さなデータセットでの迅速なプロトタイピングです*。 Spark MLlibのようなライブラリを使用すると、クイックプロトタイピングの作業がはるかに簡単になります。

5.2. モデルのハイパーパラメーター調整

典型的なモデルは、機能、パラメーター、およびハイパーパラメーターで構成されています。 機能は、入力データとしてモデルに入力するものです。 モデルパラメーターは、トレーニングプロセス中にモデルが学習する変数です。 モデルに応じて、*経験に基づいて設定し、反復的に調整する必要がある特定の追加パラメーターがあります*。 これらは、モデルハイパーパラメーターと呼ばれます。
たとえば、学習率は、勾配下降ベースのアルゴリズムの典型的なハイパーパラメーターです。 学習率は、トレーニングサイクル中にパラメーターを調整する速度を制御します。 モデルが適切なペースで効果的に学習するには、これを適切に設定する必要があります。
経験に基づいたこのようなハイパーパラメーターの初期値から始めることができますが、モデル検証を実行し、手動で繰り返し調整する必要があります。

5.3. モデル性能

統計モデルは、訓練されている間は*過剰適合と不足適合の傾向があり、どちらもモデルのパフォーマンスが低下します*。 アンダーフィッティングとは、モデルがデータから一般的な詳細を十分に選択しない場合を指します。 一方、モデルがデータからノイズを拾い始めると、過剰適合が発生します。
アンダーフィットとオーバーフィットの問題を回避するためのいくつかの方法があり、それらはしばしば組み合わせて使用​​されます。 たとえば、*過剰適合に対抗するために、最も採用されている手法には相互検証と正則化*が含まれます。 同様に、アンダーフィットを改善するために、モデルの複雑さを増し、トレーニング時間を増やすことができます。
Spark MLlibは、正則化や相互検証などのこれらの手法のほとんどをサポートしています。 実際、ほとんどのアルゴリズムはデフォルトでサポートされています。

6. 比較のSpark MLlib

Spark MLlibは機械学習プロジェクトのための非常に強力なライブラリですが、仕事のための唯一のライブラリではありません。 さまざまなサポートを備えたさまざまなプログラミング言語で利用可能な非常に多くのライブラリがあります。 ここでは人気のあるものをいくつか見ていきます。

6.1. テンソルフロー/ケラス

https://www.tensorflow.org/[Tensorflow]は、オープンソースの*データフローと微分可能プログラミングのためのライブラリであり、機械学習アプリケーションに広く採用されています*。 高レベルの抽象化であるhttps://keras.io/[Keras]とともに、機械学習に最適なツールです。 これらは主にPythonとCで記述され、主にPythonで使用されます。 Spark MLlibとは異なり、ポリグロットは存在しません。

6.2. テアノ

https://github.com/Theano/Theano[Theano]は、数式を操作および評価するためのもう1つのPythonベースのオープンソース*ライブラリです。たとえば、機械学習アルゴリズムで一般的に使用される行列ベースの式です。 。 Spark MLlibとは異なり、Theanoは主にPythonで使用されます。 ただし、KerasはTheanoバックエンドと一緒に使用できます。

6.3. CNTK

https://docs.microsoft.com/en-us/cognitive-toolkit/[Microsoft Cognitive Toolkit(CNTK)]は、有向グラフを介した計算手順を説明するCで記述された*深層学習フレームワークです。 PythonプログラムとCプログラムの両方で使用でき、主にニューラルネットワークの開発で使用されます。 おなじみの直感的な抽象化を提供する、使用可能なCNTKに基づくKerasバックエンドがあります。

7. 結論

要約すると、このチュートリアルでは、さまざまなカテゴリやワークフローなど、機械学習の基本について説明しました。 Spark MLlibの基礎を、利用可能な機械学習ライブラリとして検証しました。
さらに、利用可能なデータセットに基づいた単純な機械学習アプリケーションを開発しました。 この例では、機械学習のワークフローで最も一般的な手順のいくつかを実装しました。
また、典型的な機械学習プロジェクトの高度な手順のいくつかと、それらでSpark MLlibがどのように役立つかについても説明しました。 最後に、使用可能な代替の機械学習ライブラリのいくつかを見ました。
いつものように、コードはhttps://github.com/eugenp/tutorials/tree/master/apache-spark[GitHubで]にあります。