RユーザのためのSpark入門 2015年6月20日 第48回Tokyo.R @sfchaos 1
RユーザのためのSpark入門
2015年6月20日第48回Tokyo.R
@sfchaos
1
自己紹介■ twitterID: @sfchaos
■ 仕事:データマイニング
2
アジェンダ1. Sparkとは
2. SparkRを使ってみる
3. MLlibを使ってみる
4. まとめ
3
1. Sparkとは
4
Apache Sparkの概要■ OSSのインメモリ処理の分散並列基盤.
■ RDDという分散コレクションに対して,map, filter, reduceなどのデータ処理を繰り返して目的のデータを得る処理モデル.※ RDD: Resilient Distributed Dataset■ 2009年,UC Berkeley(当時)のMatei Zaharia氏が関数プログラミング言語Scalaを用いて開発.
5
Apache Sparkの概要■ Sparkのコアとなる分散処理エンジン
(Apache Spark Core)■Spark SQL: SparkのアプリでSQL
■Spark Streaming: ストリーム処理
■MLlib: 機械学習
■GraphX: グラフの処理
6
RユーザがSparkを使用する意義■ インタラクティブな分析が可能.■ 並列分散方法などを意識せずに,大規模データ
(~TB級)の処理が可能.
■ 機械学習のアルゴリズムで頻出する反復処理を高速化.
7
RユーザがSparkを使用する価値■k平均法などの反復計算で高速化が期待できる.
8
猿田浩輔,「Spark MLlibではじめるスケーラブルな機械学習」,
JJUG ナイトセミナー, 2014年.
http://www.slideshare.net/hadoopxnttdata/spark-m-llib-nttdata
産業界で進むSparkへの投資■ IBMが3,500人を投入するなど,今後の一層の成長が有望視される.
9
TechCrunch記事(2015年6月16日)
http://jp.techcrunch.com/2015/06/16/20150615ibm-pours-researchers-and-resources-into-apache-spark-project/
SparkRのサポートの開始■ 従来は,Scala, Java, Pythonで記述,実行できた.
■ 先日リリースされたSpark 1.4.0からはSparkRのサポートを公式に開始した.
■ 今回は,SparkRやMLlibの入門的な発表を行う.
10
Sparkのインストール■Mac/Linuxユーザは,以下のページから落として解凍するだけ.http://spark.apache.org/downloads.html
■Windowsユーザは,qtwiさんのQiitaの記事を参照.http://qiita.com/qtwi/items/7abcfc53ba9568f20004
11
2. SparkRを使ってみる
12
SparkRとは■ RからSparkを使うためのバインディング
■ Spark 1.4.0から公式にサポートされることになった.
13
SparkRの情報■ qtwiさんのQiitaの記事が非常にまとまっている.
■ 本資料でも大いに参考にさせていただいた. http://qiita.com/qtwi/items/7abcfc53ba9568f20004■ というか,この記事を読んだ方がはるかに良い.
14
SparkRの情報■@hoxo_mさんの記事
http://qiita.com/hoxo_m/items/22d31ad589970246562d
15
SparkRの起動■Sparkのディレクトリ配下のbin/sparkRを実行■必要に応じてパスを通しておくと良い
16
$ bin/sparkR
R version 3.1.2 (2014-10-31) -- "Pumpkin Helmet" Copyright (C) 2014 The R Foundation for Statistical Computing Platform: x86_64-apple-darwin13.4.0 (64-bit)
(中略)
Welcome to SparkR! Spark context is available as sc, SQL context is available as sqlContext
データの入出力・変換■ createDataFrame: SparkのDataFrameに変換 ※ DataFrameは,SparkSQL用のデータ形式
17
データの入出力・変換■ jsonファイル
■ read.df関数で読み込みHiveSQL上のテーブルに変換■ SQLによりデータ抽出可能
18
> people <- read.df(sqlContext, “./examples/src/main/resources/ > people.json", "json") > head(people) ## age name ##1 NA Michael ##2 30 Andy ##3 19 Justin
> printSchema(people) # root # |-- age: integer (nullable = true) # |-- name: string (nullable = true)
データの入出力・変換■ Hiveとの連携
■ HDFSに蓄積されたデータの抽出
19
> hiveContext <- sparkRHive.init(sc) > sql(hiveContext, "CREATE TABLE IF NOT EXISTS src (key INT, value STRING)") > sql(hiveContext, "LOAD DATA LOCAL INPATH ‘examples/src/main/ resources/kv1.txt' INTO TABLE src")
> # クエリはHiveQLで表現可能 > results <- hiveContext.sql("FROM src SELECT key, value")
> # 返り値はRのデータフレームで返される > head(results) ## key value ## 1 238 val_238 ## 2 86 val_86 ## 3 311 val_311
DataFrameオブジェクトの作成■ createDataFrame関数によりRのデータフレームから作成
20
> iris.df <- createDataFrame(sqlContext, iris) > iris.df DataFrame[Sepal_Length:double, Sepal_Width:double, Petal_Length:double, Petal_Width:double, Species:string] > class(iris.df) [1] "DataFrame" attr(,"package") [1] “SparkR" > head(iris.df, 3) Sepal_Length Sepal_Width Petal_Length Petal_Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa
DataFrameオブジェクトの操作■ 行の抽出(filter関数)
21
> library(magrittr) > head(filter(iris.df, iris.df$Sepal_Length >= 5.0), 3) Sepal_Length Sepal_Width Petal_Length Petal_Width Species 1 5.1 3.5 1.4 0.2 setosa 2 5.0 3.6 1.4 0.2 setosa 3 5.4 3.9 1.7 0.4 setosa > # パイプ処理も可能 > iris.df %>% filter(iris.df$Sepal_Length >= 5.0) %>% head(3) > # NSE(Non Standard Evaluation)は使えない > iris.df %>% filter(Sepal_Length >= 5.0) %>% head(3) 以下にエラー filter(., Sepal_Length >= 5) : 引数 'condition' の評価中にエラーが起きました (関数 'filter' に対するメソッドの選択時): エラー: オブジェクト 'Sepal_Length' がありません
magrittrパッケージを使用
(dplyrを読み込むと名前の衝突が起きて,
面倒なことに・・・)
データフレームの操作■ 列の抽出
22
> head(select(iris.df, iris.df$Species), 3) Species 1 setosa 2 setosa 3 setosa > # パイプ処理も可能 > iris.df %>% select(iris.df$Species) %>% head(3) > # NSE(Non Standard Evaluation)は使えない > iris.df %>% select(Species) %>% head(3) 以下にエラー select(., Species) : 引数 'col' の評価中にエラーが起きました (関数 'select' に対するメソッドの選択時): エラー: オブジェクト 'Species' がありません
グループ化・集約■ グループ化処理はgroupBy関数で実行.
■ 集約処理はsummarize関数で実行.
23
> # 列Speciesの種別ごとに件数を集計する > iris.df %>% groupBy(iris.df$Species) %>% summarize(count=n(iris.df$Species)) %>% collect Species count 1 versicolor 50 2 setosa 50 3 virginica 50
その他の話題■ ローカルモードだけでなく,マスター・スレーブを用いた実行例■ RStudioからの利用
■ SparkRからのRDDの利用 等々 qtwiさんのqiita記事を参照.
24
3. MLlibを使ってみる
25
MLlibとは■ Sparkで機械学習を実行するライブラリ
■ 残念ながら,Spark 1.4.0のSparkRではMLlibへのインタフェースは提供されていない.
26
MLlibで利用できるアルゴリズム■線形モデル■クラス分類(線形カーネルSVM, ロジスティック回帰)
■回帰(最小二乗法,LASSO,リッジ回帰)
■決定木■集団学習(ランダムフォレスト,勾配ブースティング)
■ナイーブベイズ分類器■ isotonic回帰(等調回帰?)
27
MLlibの参考資料■ MLlibについては,以下の資料が大変参考になる.
■ MapReduceを用いる問題点の指摘からSparkやMLlibの処理の概要まで,非常に分かりやすい.
28
猿田浩輔,「Spark MLlibではじめるスケーラブルな機械学習」,
JJUG ナイトセミナー, 2014年.
http://www.slideshare.net/hadoopxnttdata/spark-m-llib-nttdata
予測モデルの構築・検証(ホールドアウト検定)
■訓練データと検証データに分割
29
データ
訓練データ
検証データ
モデル構築
予測モデル
モデル検証
検証結果
モデルを評価するフェーズ
モデルを構築するフェーズ
SparkRからのランダムフォレストの実行■ launchBackend関数でScalaやJavaでビルドした関数を実行するのが良さそう.※ qtwiさんのqiita記事を参照.
30
> SparkR:::launchBackend( sparkSubmitOpts=“--class org.apache.spark.examples.mllib.DecisionTreeRunner lib/spark-examples-1.4.0-hadoop2.6.0.jar”, jars=“", args="-input data/mllib/sample_libsvm_data.txt -numTrees 500 -fracTest 0.3”, sparkHome=Sys.getenv("SPARK_HOME"))
ランダムフォレストの実行例
Scalaのファイルを覗いてみる${SPARK_HOME}/examples/src/main/scala/org/apache/spark/examples/mllib/DecisionTreeRunner.scala
31
object DecisionTreeRunner {
object ImpurityType extends Enumeration { type ImpurityType = Value val Gini, Entropy, Variance = Value }
import ImpurityType._
Scalaのファイルを覗いてみる${SPARK_HOME}/examples/src/main/scala/org/apache/spark/examples/mllib/DecisionTreeRunner.scala
32
case class Params( input: String = null, testInput: String = "", dataFormat: String = "libsvm", algo: Algo = Classification, maxDepth: Int = 5, impurity: ImpurityType = Gini, maxBins: Int = 32, minInstancesPerNode: Int = 1, minInfoGain: Double = 0.0, numTrees: Int = 1, featureSubsetStrategy: String = "auto", fracTest: Double = 0.2, useNodeIdCache: Boolean = false, checkpointDir: Option[String] = None, checkpointInterval: Int = 10) extends AbstractParams[Params]
def main(args: Array[String]) {
ランダムフォレストを用いたホールドアウト検定
■ 現状は,あえてSparkRを使う理由はない気がする
33
scala> import org.apache.spark.SparkContext scala> import org.apache.spark.mllib.tree.RandomForest scala> import org.apache.spark.mllib.util.MLUtils scala> import org.apache.spark.mllib.evaluation.BinaryClassificationMetrics scala> import org.apache.spark.mllib.evaluation.MulticlassMetrics scala> // データのロード scala> val sc = new SparkContext("local", "RandomForest") scala> val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt") scala> // 訓練データとテストデータへの分割 scala> val splits = data.randomSplit(Array(0.7, 0.3)) scala> val (trainingData, testData) = (splits(0), splits(1))
ランダムフォレストを用いたホールドアウト検定
■ 現状は,あえてSparkRを使う理由はないかも
34
scala> // ランダムフォレストを用いた予測モデルの構築 scala> val numClasses = 2 // クラス数 scala> val categoricalFeaturesInfo = Map[Int, Int]() // カテゴリ変数の情報 scala> val numTrees = 500 // 構築する決定木の個数 scala> val featureSubsetStrategy = "auto" // 特徴量選択のアルゴリズム scala> val impurity = "gini" // 不純度に用いる指標 scala> val maxDepth = 5 // 木の最大の深さ scala> val maxBins = 32 scala> val model = RandomForest.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo, numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins)
ランダムフォレストを用いたホールドアウト検定
■ 現状は,あえてSparkRを使う必要はないかも.
35
scala> // テストデータに対する予測モデルの評価 val labelAndPreds = testData.map { point => val prediction = model.predict(point.features) (point.label, prediction) } scala> // 混合行列 scala> val metrics = new MulticlassMetrics(labelAndPreds) scala> metrics.confusionMatrix res20: org.apache.spark.mllib.linalg.Matrix = 13.0 1.0 0.0 17.0
scala> metrics.precision res21: Double = 0.9285714
正例と予測
実績が正例
適合率
(precision)
クロスバリデーション■訓練データと検証データを複数セット作成
36
データ
訓練データ
検証データ
モデル構築予測モデル
モデル検証
検証結果
訓練データ
検証データ
モデル構築予測モデル
モデル検証
検証結果
・・・
検証結果の統合
謝罪■ ごめんなさい,調査中です・・・
37
https://spark.apache.org/docs/latest/ml-guide.html
4. まとめ
38
まとめ■ Sparkはインメモリの並列処理フレームワーク.
■ Spark1.4.0より,SparkRが公式的にサポートされることになった.■ まだデータの集計・加工処理が中心の印象だが,今後の発展が期待される.
39