Spark ベストプラクティスと 
Linear Regression with MLlib のチュートリアル 
株式会社リクルートテクノロジーズ 
アドバンスドテクノロジーラボ 
Yu Ishikawa 
1
自己紹介 
• 所属 
– 株式会社リクルートテクノロジーズ 
– アドバンスドテクノロジーラボ 
• 現在の業務 
– Apache Spark の機械学習ライブラリMLlib へのコントリ 
ビュート 
• バックグラウンド 
– 某SNS サービスの大規模データ分析基盤構築,サービス 
のデータマイニング,社内コンサルティングなど 
2
Apache Spark コミュニティと 
協力して取り組んでいること 
• Distributed Divisive Hierarchical Clustering 
• Distance Functions (Breeze) 
• kNN 
• Bootstrapping (Bag of Little Bootstraps) 
• Canopy K-mean 
• Bregman Divergence on K-means 
3
発表のねらい 
• Spark を扱う上での基本的な考え方を学ぶ 
• Logistic Regression をScala で処理する方法を学ぶ 
– アルゴリズムの詳細は解説はしません 
4
Agenda 
• Spark の基礎知識をおさらい 
• Spark ベストプラクティス 
• Logistic Regression with MLlib 
• Spark 1.2 のMLlib の動向 
5
RDD, Partition, Cache 
SPARK の基礎知識をおさらい 
6
RDD:Resilient Distributed Datasets 
• DAG 型実行計画により,in-memory 分散処理の 
フォールトトレラントを実現 
– Resilient: 回復力のある,すぐに立ち直れる 
– DAG: Directed Acyclic Graph,無閉路有向グラフ 
7 
Cited by Matei Zaharia et al. “Resilient distributed datasets: a 
fault-tolerant abstraction for in-memory cluster computing”
Lazy Evaluation 
8 
// load data from Amazon S3 
val data = sc.textFile(“s3n://bucket/data/access-log.txt”) 
// transformations 
val errors = data.filter(line => line.contains(“error”)) 
val splitedData = errors.map(line => line.split(“t”)) 
val elements = splitedData.map(x => x(3)) 
// action 
elements.count 
この段階では処理は 
実行されていない 
この段階になって初 
めて処理が実行 
RDD のAPI はTransformations とActions に分類 
map() , filter() などのTransformations は遅延評価 
count() などのActions が評価されたタイミングで実行計画を立てて処理される
Partitions in RDD 
• RDD の「分割数」≒利用できるCPU コア数 
• 一般的に利用できるCPU コア数x 1 ~ 3 を設定するのがよい 
• Partition を増やしすぎても遅くなるのでバランスが大事 
val rdd1 = sc.textFile(file, 2) 
val rdd2 = rdd1.map(x => x + 10) 
rdd1 
9 
rdd2 
val rdd1 = sc.textFile(file, 4) 
val rdd2 = rdd1.map(x => x + 10) 
rdd1 rdd2 
Max CPU Cores: 2 Max CPU Cores: 4
Cacheとは? 
• クラスタ横断でメモリ上に処理データをキャッシュす 
ることができる 
• 繰り返し「再利用される」データに活用すると効率的 
に処理できる 
• 11000000 レコードのデータのカウント(160 cores) 
– キャッシュなし:7.48 [sec] 
– キャッシュあり:0.40 [sec] 
10 
Spark はCache の活用次第でパフォーマンスが 
大幅に変化するので注意!
Cacheされるタイミング(1) 
11 
内部処理の違いについて考えてみてください 
val rdd1 = sc.textFile(file, 2) 
val rdd2 = rdd1.map(x => x + 10) 
rdd2.count 
rdd1.cache 
val rdd1 = sc.textFile(file, 2) 
rdd1.cache 
val rdd2 = rdd1.map(x => x + 10) 
rdd2.count
Cacheされるタイミング(2) 
12 
Cache はAction の処理をしながら行われる 
val rdd1 = sc.textFile(file, 2) 
val rdd2 = rdd1.map(x => x + 10) 
rdd2.count 
rdd1.cache 
val rdd1 = sc.textFile(file, 2) 
rdd1.cache 
val rdd2 = rdd1.map(x => x + 10) 
rdd2.count 
この時点ではrdd1 は厳密に 
はキャッシュされていない 
rdd2 のcount をしながら, 
rdd1 をキャッシュする
SPARK ベストプラクティス 
13
Cacheの活用ポイント(1) 
14 
cached 
filter 
val rdd1 = sc.textFile(file, 4) 
rdd1.cache 
val rdd2 = rdd1.filetr(x => x % 5 == 0) 
val rdd3 = rdd2.map(x => x + 10) 
rdd3.count 
rdd3.count 
map 
rdd1 rdd2 rdd3 
2回目のrdd3.count でも 
rdd1 -> rdd2 -> rdd3 の処理が行われてしまう
Cacheの活用ポイント(2) 
15 
cached 
rdd4 
rdd1 
rdd2 
rdd3 
• 適宜キャッシュしないとrdd1 からのDAG 処理が 
適応されてしまう 
• 特に機械学習では複雑な繰り返し処理をするよ 
うなアルゴリズムもあるので,キャッシュのタイミ 
ングがパフォーマンスに大きく影響する 
rdd1 
rdd2 
rdd3 
rdd4 
例:データを再帰的に分割しながら処 
理をしていくようなアルゴリズム
Cache の状態の確認 
• WebUI からSpark のRDD のキャッシュ状態などを確 
認できる 
– http://${SPARK_MASTER}:4040/storage/ 
16
利用データの圧縮形式 
• Gzip などで圧縮されたファイルをSpark で読み込む 
と,いくらPartition 数を増やしても1プロセスでしか 
処理することができない 
• Gzip の分割不可能の性質が原因 
– Hadoopをやったことある方にはお馴染み 
17 
• 元データを予め解凍するか 
• Spark で1回なめて,そのデータをキャッシュするなり書 
き出すなりする必要がある
Data Locality 
• Hadoop と同様に処理を行うマシンと,データがあるマシンが 
同じ方が処理効率がよい 
• Cache と同様にWebUI から確認できる 
– PROCESS_LOCAL で処理されているようであればよい 
18
Master (Driver) に負荷を掛けない 
• RDD のcollect メソッドは,RDD をScala のコレクションに変換 
• 巨大なデータを集約しようとするとDriver が動いているマシ 
ンのメモリに乗り切らない 
• データを確認したいときは,take() やtakeSample() 
• 同様の理由で,countByKey(), countByValue(), collectAsMap() 
でも気をつける 
19 
Don't copy all elements of a large RDD to the driver!!
IntelliJ のimport 最適化問題 
• flatMap() などのTransforms メソッドは, 
org.apache.spark.SparkContext 以下に配置されてい 
る 
• IntelliJ のimport 最適化では, 
`org.apache.spark.SparkContest._` を自動追記してく 
れない 
• 手でimport 文を書く必要がある 
20 
import org.apache.spark.SparkContext._ 
rdd.flatMap(x => (1 to 10).map(i => x))
LOGISTIC REGRESSION 
CLASSIFICATION WITH MLLIB 
21
Logistic Regression with Spark 
• Logistic Regression (Classification) 
– 二項分類の予測モデルの一種 
– Regression のアルゴリズムも用意されている 
• Apache Spark 1.1 ではSGD (確率的勾配降下法) に対応したアルゴ 
リズムのみTop-Level API で利用できる 
– L-BFGS 法はTop-Level API として直接は扱えない 
• LogisticRegressionWithSGD のパラメータ(*: 必須パラメータ) 
– * Input: (ラベル,特徴量のベクトル)のRDD 
– * numIterations: Gradient Desent を実行する回数 
– stepSize(default: 1.0): SGD の 
– miniBatchFraction(default: 1.0): SGD の1回のiteration で利用するデータ 
の比率 
– initialWeights(default: ): 初期値の重みベクトル 
22
モデル構築のイメージ図 
23 
Logistic 
Regression 
Model 
予測したい特徴量 
(1.0, 4.1, 3.0, 1.1) 
Label: 1, Features: (1.0, 4.2, 3.2, 1.2) 
Label: 0, Features: (0.1, 2.4, 8.2, 4.6) 
Label: 0, Features: (0.1, 2.3, 8.1, 4.2) 
Label: 1, Features: (1.2, 4.1, 2.8, 0.9) 
Train 
訓練データ 
0 or 1 
Predict
二項分類器の評価方法 
• Spark は二項分類器を評価するためのクラスがある 
– BinaryClassificationMetrics 
• BinaryClassificationMetrics で算出できる値 
– Area Under the ROC curve 
• 最大値:1のときがモデルとして最も良い 
• 最悪値は0.5 のときで,ランダムな判別を行ったときと同じ 
– Area Under the Precision-Recall curve 
24
実験概要 
25 
S3 
CSV 
7.5GB 
Spark Cluster on EC2 
3.2GB 
parse 
duplicate 
X30 
105.2GB 
Test 
73.2GB 
Train 
32GB 
2/3 
1/3 
Evaluation 
Logistic 
Regression 
Model 
K-分割交差検証(K = 3)
Spark Cluster スペック 
• Cluster 
– Total CPU cores: 160 
– Total Memory: 1195.0 GB 
• Master 
– Instance Types: r3.large 
– Compute Units: 6.5 (2 core x 3.25 unit) 
– Memory: 15.25GB 
• Slaves (# Instances: x5) 
– Instance Type: r3.8xlarge 
– Compute Units: 104 (32 core x 3.25 unit) 
– Memory: 244GB 
– Spot Biting: $0.35 / hour 
26
利用したデータ 
• 利用元 
– Baldi, P., P. Sadowski, and D. Whiteson. “Searching for Exotic Particles in High-energy 
Physics with Deep Learning.” Nature Communications 5 (July 2, 2014) 
– http://archive.ics.uci.edu/ml/datasets/HIGGS 
• 二項分類のデータ 
• データサイズ:7.5GB 
• レコード数:11000000 
• Number of Attributes:28 
• Sample Data:(指数表現されている…) 
27
処理手順の概要 
1. S3 上のファイルをSpark で読み込んで扱える形式に変換 
2. デモ用にレコード数を30倍に増やす 
3. (K-分割交差検証で)Logistic Regression のモデルを構築 
4. 訓練したモデルにテストデータを当てはめて正解率とArea 
Under the ROC curve を算出 
28
処理手順:S3 上のファイルをSpark で読み込んで扱える形式に変換 
29 
// Loads a CSV file from Amazon S3 
val origin = sc.textFile(“s3n://your-bucket/HIGGS.csv”, 160) 
// Converts Strings to Doubles 
val data = origin.map(_.split(",")) 
カンマで分割 
.map { array => array.map(java.lang.Double.parseDouble(_))} 
.map { array => 
val label = array(0) 
val features = Vectors.dense((1 to (array.length - 1)).map(array(_)).toArray) 
new LabeledPoint(label, features) 
} 
文字列をDoubleでパース 
Logistic Regression 用のクラスに変換
処理手順:デモ用にレコード数を30倍に増やす 
• flatMap() を利用することでデータ量をコントロール 
できる 
– (Scala) List(0,1,2).flatMap(n => List(n,'A'+n)) 
–  List(0, 65, 1, 66, 2, 67) 
全く同じデータにならないように1% ランダム誤差を加える 
30 
data.flatMap { point => 
(1 to 30).map { i => 
val newFeatures = point.features.toArray.map(x => x + (0.01 * math.random * x)) 
new LabeledPoint(point.label, Vectors.dense(newFeatures)) 
} 
}
処理手順:K-分割交差検証(K = 3)でLogistic Regression のモデルを構築 
(予測ラベル,正解ラベル)のタプルのRDD を作成 
31 
// Attaches index number to each record 
val indexed = data.zipWithIndex().map { case (lp, idx) => (lp, idx % 3)} 
// Extracts the training data 
val fit = indexed.filter { case (lp, idx) => idx % 3== 0}.map { case (lp, idx) => lp} 
// Extracts the test data 
val test= indexed.filter {case (lp, idx) => idx % 3!= 0}.map {case (lp, idx) => lp} 
// Trains a model 
val model = LogisticRegressionWithSGD.train(fit, subIterations = 100) 
// Predicts the test data 
val predicted = test.map { point => 
val predictedLabel = model.predict(point.features) 
(predictedLabel, point.label) 
}
処理手順:訓練したモデルにテストデータを当てはめて正解率とAUC を算出 
32 
// Calculates a accuracy ratio 
val correct = predicted.filter { case (p, l) => p == l}.count / predict.count.toDouble 
println(s"Correct Ratio: ${correct}") 
// Calculates a Area Under the Curve 
val metric = new BinaryClassificationMetrics(predicted) 
println(s"AUC: ${metric.areaUnderROC()}") 
2値分類器を評価するためのクラス
実験に用いた条件と結果 
• 実験に用いたデータ 
– 全体:330,000,000 レコード(105.2GB) 
– 1回の訓練データ:110000000 レコード(32 GB) 
– 1回のテストデータ:220000000 レコード(73.2GB) 
• 実験に利用したパラメータ 
– numIterations: 100 
• 処理時間 
– 平均訓練時間:75.9[sec] 
– 平均テスト時間:10^-4[sec] 
• 評価 
それほど良い結果が得 
– 平均正解率:0.61 
– 平均Area Under the ROC curve: 0.60 
33 
られなかったが… 
処理速い!
SPARK 1.2 のMLLIB の動向 
34
Spark MLlib の課題 
• Kmeans などの距離関数はEuclidean Distance のみ 
サポート 
– OpenNLP のScala 移植のBreeze で距離関数を実装 
• Top-Level API が一貫していない 
• アルゴリズムによって実装品質がバラバラ 
35 
リファクタリングと新規機能追加で 
卵が先か鶏が先かのような状況が起きているので 
コミュニティを主導して交通整理する必要がある
Spark 1.2 MLlib で注目のissue 
• [SPARK-3530] Pipeline and Parameters 
– scikit-learn の`fit`, `predict` のような一貫性API に向けた取り組み 
– 各アルゴリズムの対応は1.3 以降のマイルストーンになると思われる 
– [SPARK-1856] Standardize MLlib interfaces が1.3 のマイルストーン 
• [SPARK-1545] Add Random Forest algorithm to Mllib 
– Decision Tree に,ようやくRandom Forest が追加 
– 通常のDecision Tree はRandom Forest のnumTree = 1 で実装 
• [SPARK-3486] Add PySpark support for Word2Vec 
– 1.1 系のSpark のWord2Vec はスケールしにくいし,機能として不十 
分 
– 1.2 系以降で処理の改善と機能拡充が期待 
36
[SPARK-3530] Pipeline and Parameters 
• 簡単にデータの処理フローを定義できる 
– ノーマライズ 
– 主成分分析による次元圧縮 
– LogisticRegression 
37
今日最低限持って帰っていただきたいもの 
• Spark で処理を効率化するにあたって最低限知って 
おいていただきたいことは,RDD のPartition 数と 
Cache 
• Cache はタイミングが重要 
– Lazy Evaluation によりCache はRDD のActions API が実 
行されているときに行われる 
• MLlib なら数行程度で機械学習が使える 
– 大規模データも高速に処理できる 
38
Useful Resources 
• databricks/learning-spark 
– https://github.com/databricks/learning-spark 
– O’reilly のLearning Spark のサンプルコード 
• databricks/spark-knowledgebase 
– https://github.com/databricks/spark-knowledgebase 
– Spark のパフォーマンスチューニングなどの簡単な紹介がある 
39
リクルートテクノロジーズ 
アドバンスドテクノロジーラボでは 
人材を募集しています! 
興味のある方は懇親会でお声掛け下さい 
40
ご清聴ありがとうございました 
41
Q&A 
42

2014 11-20 Machine Learning with Apache Spark 勉強会資料

  • 1.
    Spark ベストプラクティスと LinearRegression with MLlib のチュートリアル 株式会社リクルートテクノロジーズ アドバンスドテクノロジーラボ Yu Ishikawa 1
  • 2.
    自己紹介 • 所属 – 株式会社リクルートテクノロジーズ – アドバンスドテクノロジーラボ • 現在の業務 – Apache Spark の機械学習ライブラリMLlib へのコントリ ビュート • バックグラウンド – 某SNS サービスの大規模データ分析基盤構築,サービス のデータマイニング,社内コンサルティングなど 2
  • 3.
    Apache Spark コミュニティと 協力して取り組んでいること • Distributed Divisive Hierarchical Clustering • Distance Functions (Breeze) • kNN • Bootstrapping (Bag of Little Bootstraps) • Canopy K-mean • Bregman Divergence on K-means 3
  • 4.
    発表のねらい • Sparkを扱う上での基本的な考え方を学ぶ • Logistic Regression をScala で処理する方法を学ぶ – アルゴリズムの詳細は解説はしません 4
  • 5.
    Agenda • Sparkの基礎知識をおさらい • Spark ベストプラクティス • Logistic Regression with MLlib • Spark 1.2 のMLlib の動向 5
  • 6.
    RDD, Partition, Cache SPARK の基礎知識をおさらい 6
  • 7.
    RDD:Resilient Distributed Datasets • DAG 型実行計画により,in-memory 分散処理の フォールトトレラントを実現 – Resilient: 回復力のある,すぐに立ち直れる – DAG: Directed Acyclic Graph,無閉路有向グラフ 7 Cited by Matei Zaharia et al. “Resilient distributed datasets: a fault-tolerant abstraction for in-memory cluster computing”
  • 8.
    Lazy Evaluation 8 // load data from Amazon S3 val data = sc.textFile(“s3n://bucket/data/access-log.txt”) // transformations val errors = data.filter(line => line.contains(“error”)) val splitedData = errors.map(line => line.split(“t”)) val elements = splitedData.map(x => x(3)) // action elements.count この段階では処理は 実行されていない この段階になって初 めて処理が実行 RDD のAPI はTransformations とActions に分類 map() , filter() などのTransformations は遅延評価 count() などのActions が評価されたタイミングで実行計画を立てて処理される
  • 9.
    Partitions in RDD • RDD の「分割数」≒利用できるCPU コア数 • 一般的に利用できるCPU コア数x 1 ~ 3 を設定するのがよい • Partition を増やしすぎても遅くなるのでバランスが大事 val rdd1 = sc.textFile(file, 2) val rdd2 = rdd1.map(x => x + 10) rdd1 9 rdd2 val rdd1 = sc.textFile(file, 4) val rdd2 = rdd1.map(x => x + 10) rdd1 rdd2 Max CPU Cores: 2 Max CPU Cores: 4
  • 10.
    Cacheとは? • クラスタ横断でメモリ上に処理データをキャッシュす ることができる • 繰り返し「再利用される」データに活用すると効率的 に処理できる • 11000000 レコードのデータのカウント(160 cores) – キャッシュなし:7.48 [sec] – キャッシュあり:0.40 [sec] 10 Spark はCache の活用次第でパフォーマンスが 大幅に変化するので注意!
  • 11.
    Cacheされるタイミング(1) 11 内部処理の違いについて考えてみてください val rdd1 = sc.textFile(file, 2) val rdd2 = rdd1.map(x => x + 10) rdd2.count rdd1.cache val rdd1 = sc.textFile(file, 2) rdd1.cache val rdd2 = rdd1.map(x => x + 10) rdd2.count
  • 12.
    Cacheされるタイミング(2) 12 CacheはAction の処理をしながら行われる val rdd1 = sc.textFile(file, 2) val rdd2 = rdd1.map(x => x + 10) rdd2.count rdd1.cache val rdd1 = sc.textFile(file, 2) rdd1.cache val rdd2 = rdd1.map(x => x + 10) rdd2.count この時点ではrdd1 は厳密に はキャッシュされていない rdd2 のcount をしながら, rdd1 をキャッシュする
  • 13.
  • 14.
    Cacheの活用ポイント(1) 14 cached filter val rdd1 = sc.textFile(file, 4) rdd1.cache val rdd2 = rdd1.filetr(x => x % 5 == 0) val rdd3 = rdd2.map(x => x + 10) rdd3.count rdd3.count map rdd1 rdd2 rdd3 2回目のrdd3.count でも rdd1 -> rdd2 -> rdd3 の処理が行われてしまう
  • 15.
    Cacheの活用ポイント(2) 15 cached rdd4 rdd1 rdd2 rdd3 • 適宜キャッシュしないとrdd1 からのDAG 処理が 適応されてしまう • 特に機械学習では複雑な繰り返し処理をするよ うなアルゴリズムもあるので,キャッシュのタイミ ングがパフォーマンスに大きく影響する rdd1 rdd2 rdd3 rdd4 例:データを再帰的に分割しながら処 理をしていくようなアルゴリズム
  • 16.
    Cache の状態の確認 •WebUI からSpark のRDD のキャッシュ状態などを確 認できる – http://${SPARK_MASTER}:4040/storage/ 16
  • 17.
    利用データの圧縮形式 • Gzipなどで圧縮されたファイルをSpark で読み込む と,いくらPartition 数を増やしても1プロセスでしか 処理することができない • Gzip の分割不可能の性質が原因 – Hadoopをやったことある方にはお馴染み 17 • 元データを予め解凍するか • Spark で1回なめて,そのデータをキャッシュするなり書 き出すなりする必要がある
  • 18.
    Data Locality •Hadoop と同様に処理を行うマシンと,データがあるマシンが 同じ方が処理効率がよい • Cache と同様にWebUI から確認できる – PROCESS_LOCAL で処理されているようであればよい 18
  • 19.
    Master (Driver) に負荷を掛けない • RDD のcollect メソッドは,RDD をScala のコレクションに変換 • 巨大なデータを集約しようとするとDriver が動いているマシ ンのメモリに乗り切らない • データを確認したいときは,take() やtakeSample() • 同様の理由で,countByKey(), countByValue(), collectAsMap() でも気をつける 19 Don't copy all elements of a large RDD to the driver!!
  • 20.
    IntelliJ のimport 最適化問題 • flatMap() などのTransforms メソッドは, org.apache.spark.SparkContext 以下に配置されてい る • IntelliJ のimport 最適化では, `org.apache.spark.SparkContest._` を自動追記してく れない • 手でimport 文を書く必要がある 20 import org.apache.spark.SparkContext._ rdd.flatMap(x => (1 to 10).map(i => x))
  • 21.
  • 22.
    Logistic Regression withSpark • Logistic Regression (Classification) – 二項分類の予測モデルの一種 – Regression のアルゴリズムも用意されている • Apache Spark 1.1 ではSGD (確率的勾配降下法) に対応したアルゴ リズムのみTop-Level API で利用できる – L-BFGS 法はTop-Level API として直接は扱えない • LogisticRegressionWithSGD のパラメータ(*: 必須パラメータ) – * Input: (ラベル,特徴量のベクトル)のRDD – * numIterations: Gradient Desent を実行する回数 – stepSize(default: 1.0): SGD の – miniBatchFraction(default: 1.0): SGD の1回のiteration で利用するデータ の比率 – initialWeights(default: ): 初期値の重みベクトル 22
  • 23.
    モデル構築のイメージ図 23 Logistic Regression Model 予測したい特徴量 (1.0, 4.1, 3.0, 1.1) Label: 1, Features: (1.0, 4.2, 3.2, 1.2) Label: 0, Features: (0.1, 2.4, 8.2, 4.6) Label: 0, Features: (0.1, 2.3, 8.1, 4.2) Label: 1, Features: (1.2, 4.1, 2.8, 0.9) Train 訓練データ 0 or 1 Predict
  • 24.
    二項分類器の評価方法 • Sparkは二項分類器を評価するためのクラスがある – BinaryClassificationMetrics • BinaryClassificationMetrics で算出できる値 – Area Under the ROC curve • 最大値:1のときがモデルとして最も良い • 最悪値は0.5 のときで,ランダムな判別を行ったときと同じ – Area Under the Precision-Recall curve 24
  • 25.
    実験概要 25 S3 CSV 7.5GB Spark Cluster on EC2 3.2GB parse duplicate X30 105.2GB Test 73.2GB Train 32GB 2/3 1/3 Evaluation Logistic Regression Model K-分割交差検証(K = 3)
  • 26.
    Spark Cluster スペック • Cluster – Total CPU cores: 160 – Total Memory: 1195.0 GB • Master – Instance Types: r3.large – Compute Units: 6.5 (2 core x 3.25 unit) – Memory: 15.25GB • Slaves (# Instances: x5) – Instance Type: r3.8xlarge – Compute Units: 104 (32 core x 3.25 unit) – Memory: 244GB – Spot Biting: $0.35 / hour 26
  • 27.
    利用したデータ • 利用元 – Baldi, P., P. Sadowski, and D. Whiteson. “Searching for Exotic Particles in High-energy Physics with Deep Learning.” Nature Communications 5 (July 2, 2014) – http://archive.ics.uci.edu/ml/datasets/HIGGS • 二項分類のデータ • データサイズ:7.5GB • レコード数:11000000 • Number of Attributes:28 • Sample Data:(指数表現されている…) 27
  • 28.
    処理手順の概要 1. S3上のファイルをSpark で読み込んで扱える形式に変換 2. デモ用にレコード数を30倍に増やす 3. (K-分割交差検証で)Logistic Regression のモデルを構築 4. 訓練したモデルにテストデータを当てはめて正解率とArea Under the ROC curve を算出 28
  • 29.
    処理手順:S3 上のファイルをSpark で読み込んで扱える形式に変換 29 // Loads a CSV file from Amazon S3 val origin = sc.textFile(“s3n://your-bucket/HIGGS.csv”, 160) // Converts Strings to Doubles val data = origin.map(_.split(",")) カンマで分割 .map { array => array.map(java.lang.Double.parseDouble(_))} .map { array => val label = array(0) val features = Vectors.dense((1 to (array.length - 1)).map(array(_)).toArray) new LabeledPoint(label, features) } 文字列をDoubleでパース Logistic Regression 用のクラスに変換
  • 30.
    処理手順:デモ用にレコード数を30倍に増やす • flatMap()を利用することでデータ量をコントロール できる – (Scala) List(0,1,2).flatMap(n => List(n,'A'+n)) –  List(0, 65, 1, 66, 2, 67) 全く同じデータにならないように1% ランダム誤差を加える 30 data.flatMap { point => (1 to 30).map { i => val newFeatures = point.features.toArray.map(x => x + (0.01 * math.random * x)) new LabeledPoint(point.label, Vectors.dense(newFeatures)) } }
  • 31.
    処理手順:K-分割交差検証(K = 3)でLogisticRegression のモデルを構築 (予測ラベル,正解ラベル)のタプルのRDD を作成 31 // Attaches index number to each record val indexed = data.zipWithIndex().map { case (lp, idx) => (lp, idx % 3)} // Extracts the training data val fit = indexed.filter { case (lp, idx) => idx % 3== 0}.map { case (lp, idx) => lp} // Extracts the test data val test= indexed.filter {case (lp, idx) => idx % 3!= 0}.map {case (lp, idx) => lp} // Trains a model val model = LogisticRegressionWithSGD.train(fit, subIterations = 100) // Predicts the test data val predicted = test.map { point => val predictedLabel = model.predict(point.features) (predictedLabel, point.label) }
  • 32.
    処理手順:訓練したモデルにテストデータを当てはめて正解率とAUC を算出 32 // Calculates a accuracy ratio val correct = predicted.filter { case (p, l) => p == l}.count / predict.count.toDouble println(s"Correct Ratio: ${correct}") // Calculates a Area Under the Curve val metric = new BinaryClassificationMetrics(predicted) println(s"AUC: ${metric.areaUnderROC()}") 2値分類器を評価するためのクラス
  • 33.
    実験に用いた条件と結果 • 実験に用いたデータ – 全体:330,000,000 レコード(105.2GB) – 1回の訓練データ:110000000 レコード(32 GB) – 1回のテストデータ:220000000 レコード(73.2GB) • 実験に利用したパラメータ – numIterations: 100 • 処理時間 – 平均訓練時間:75.9[sec] – 平均テスト時間:10^-4[sec] • 評価 それほど良い結果が得 – 平均正解率:0.61 – 平均Area Under the ROC curve: 0.60 33 られなかったが… 処理速い!
  • 34.
    SPARK 1.2 のMLLIBの動向 34
  • 35.
    Spark MLlib の課題 • Kmeans などの距離関数はEuclidean Distance のみ サポート – OpenNLP のScala 移植のBreeze で距離関数を実装 • Top-Level API が一貫していない • アルゴリズムによって実装品質がバラバラ 35 リファクタリングと新規機能追加で 卵が先か鶏が先かのような状況が起きているので コミュニティを主導して交通整理する必要がある
  • 36.
    Spark 1.2 MLlibで注目のissue • [SPARK-3530] Pipeline and Parameters – scikit-learn の`fit`, `predict` のような一貫性API に向けた取り組み – 各アルゴリズムの対応は1.3 以降のマイルストーンになると思われる – [SPARK-1856] Standardize MLlib interfaces が1.3 のマイルストーン • [SPARK-1545] Add Random Forest algorithm to Mllib – Decision Tree に,ようやくRandom Forest が追加 – 通常のDecision Tree はRandom Forest のnumTree = 1 で実装 • [SPARK-3486] Add PySpark support for Word2Vec – 1.1 系のSpark のWord2Vec はスケールしにくいし,機能として不十 分 – 1.2 系以降で処理の改善と機能拡充が期待 36
  • 37.
    [SPARK-3530] Pipeline andParameters • 簡単にデータの処理フローを定義できる – ノーマライズ – 主成分分析による次元圧縮 – LogisticRegression 37
  • 38.
    今日最低限持って帰っていただきたいもの • Sparkで処理を効率化するにあたって最低限知って おいていただきたいことは,RDD のPartition 数と Cache • Cache はタイミングが重要 – Lazy Evaluation によりCache はRDD のActions API が実 行されているときに行われる • MLlib なら数行程度で機械学習が使える – 大規模データも高速に処理できる 38
  • 39.
    Useful Resources •databricks/learning-spark – https://github.com/databricks/learning-spark – O’reilly のLearning Spark のサンプルコード • databricks/spark-knowledgebase – https://github.com/databricks/spark-knowledgebase – Spark のパフォーマンスチューニングなどの簡単な紹介がある 39
  • 40.
  • 41.
  • 42.