More Related Content Similar to Rにおける大規模データ解析(第10回TokyoWebMining) Similar to Rにおける大規模データ解析(第10回TokyoWebMining)(20) More from Shintaro Fukushima More from Shintaro Fukushima(20) Rにおける大規模データ解析(第10回TokyoWebMining)2. 本発表の趣旨
� Rは便利な統計解析ツールとして注目を浴びていますが,
大規模なデータを扱うことが得意ではありません.
� そこで,本発表では,大規模データを扱うパッケージの
一つであるbigmemoryとその兄弟パッケージについて紹
介します.
� HadoopやMahoutなどを使うほどではなく,かといってR
の標準機能だけでは扱いに困るほどの規模のデータを扱
う方のお役に立てれば幸いです.
2
5. 自己紹介
� TwitterID: @sfchaos
� 出身地: 埼玉県
� 職業:コンサルタント
� 数年間,金融工学のモデル構築・データ解析
� 最近,大規模データ解析に着手(Hadoop/Mahout)
� 学生時代の専攻は物理・応用数学(非線形力学系・カオ
ス)
※博士ではありません
5
8. 2.2 Rの長所(の一例)
� ベクトルや行列等のオブジェクトの扱いやすさ
> x <- 1:10
> x
[1] 1 2 3 4 5 6 7 8 9 10
> x[x%%2==0] # 偶数番目の要素の取り出し
[1] 2 4 6 8 10
> y <- matrix(1:10, nrow=2)
> y
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
> apply(y, 1, mean) # 各行の平均
[1] 5 6
8
9. � きれいなグラフィクス
Average Yearly Sunspots
1750 1800 1850 1900 1950
150
spots
100
50
0
150
spots
100
50
0
1750 1800 1850 1900 1950
Year
9
15. 2.3 Rの短所
� マルチCPU(コア)の環境でも基本的に1CPU(コア)
� 基本的にオンメモリでデータを保持,計算を実行
� ベクトル,行列,配列などの要素数の上限が231-1
� 基本的にオブジェクトの参照渡しができず値渡しを行う
ため,コピーがあちこちで発生しメモリを消費する
15
16. 2.3 Rの短所
� マルチCPU(コア)の環境でも基本的に1CPU(コア)
� 基本的にオンメモリでデータを保持,計算を実行
� ベクトル,行列,配列などの要素数の上限が231-1
� 基本的にオブジェクトの参照渡しができず値渡しを行う
ため,コピーがあちこちで発生しメモリを消費する
大規模なデータを扱ったり
計算速度を上げるためには工夫が必要
→高性能計算(High Performance Computing)
16
18. 3.1 RにおけるHPC
明示的な並列化
内部的な並列化
グリッドコンピューティング
乱数
並列計算
リソース管理・バッチスケジューリ
ング
応用
GPU
大規模データ管理
コンパイルコードへの簡便なインタフェース
プロファイリングツール
CRAN Task View: High-Performance and Parallel Computing with R
http://cran.r-project.org/index.html
18
19. 3.1 RにおけるHPC
明示的な並列化(マルチコア/CPU計算等)
内部的な並列化
グリッドコンピューティング
乱数
並列計算
リソース管理・バッチスケジューリ
ング
応用
GPU
大規模データ管理(RAMを超えるデータ管理)
コンパイルコードへの簡便なインタフェース
プロファイリングツール
CRAN Task View: High-Performance and Parallel Computing with R
http://cran.r-project.org/index.html
19
21. 3.2 大規模データ管理パッケージ
� ff
� データをディスクに置き,必要に応じてメモリにロードする.
� 行列,データフレーム,因子など多数のデータ型を用意してい
る.
� bigmemory
� 大規模データをディスク等に置き,必要に応じて物理メモリに
キャッシュする.
� 扱えるデータ型は行列のみである.
� 1台の計算機上で複数のRのプロセスでオブジェクトを共有する
ことが可能である.
21
22. 3.2 大規模データ管理パッケージ
� ff
� データをディスクに置き,必要に応じてメモリにロードする.
� 行列,データフレーム,因子など多数のデータ型を用意してい
る.
どちらが優位かについては
一概に言えない
� bigmemory
� 大規模データをディスク等に置き,必要に応じて物理メモリに
キャッシュする.
� 扱えるデータ型は行列のみである.
� 1台の計算機上で複数のRのプロセスでオブジェクトを共有する
ことが可能である.
22
23. 3.2 大規模データ管理パッケージ
� ff
� データをディスクに置き,必要に応じてメモリにロードする.
� 行列,データフレーム,因子など多数のデータ型を用意してい
る.
どちらが優位かについては
一概に言えない
� bigmemory
� 大規模データをディスク等に置き,必要に応じて物理メモリに
キャッシュする.
� 扱えるデータ型は行列のみである.
� 1台の計算機上で複数のRのプロセスでオブジェクトを共有する
ことが可能である.
23
24. 3.2 大規模データ管理パッケージ
� ff
� データをディスクに置き,必要に応じてメモリにロードする.
� 行列,データフレーム,因子など多数のデータ型を用意してい
る.
どちらが優位かについては
一概に言えない
� bigmemory
� 大規模データをディスク等に置き,必要に応じて物理メモリに
キャッシュする.
� 扱えるデータ型は行列のみである.
� 1台の計算機上で複数のRのプロセスでオブジェクトを共有する
ことが可能である.
並列計算・並行計算が可能に
24
25. 3.3 bigmemoryを用いて解決するRの欠点
欠点 bigmemoryの使用による解決度合い
マルチCPU(コア)の環境でも基 ○
本的に1CPU(コア) 並列計算,並行計算が可能に
○
基本的にオンメモリでデータ
を保持,計算を実行 RAMをはるかに超えるデータの扱いが
可能に
ベクトル,行列,配列などの ○
要素数の上限が231-1 要素数の上限は252まで拡張
基本的にオブジェクトの参照
渡しができず値渡しを行うた ◎
め,コピーがあちこちで発生 参照渡しでオブジェクトを渡せる
しメモリを消費する
25
26. 3.4 The bigmemory project
� 大規模行列の管理/解析/集計を行うパッケージ群
� 2010年度の米国の統計学会の
統計計算分野で、2010年の
"John M. Chambers Statistical
Software Award"を受賞
� 次の5つのパッケージで構成される
パッケージ名 機能
bigmemory 大規模行列の管理
biganalytics 大規模行列の解析
bigtabulate 大規模行列の集計
bigalgebra 大規模行列の演算
synchronicity 大規模行列の処理の同期・排他制御
26
28. � データの読み込み
> library(bigmemory)
> airline <- read.big.matrix("AirlineAllData.csv", header=TRUE,
sep=",", backingifle="AirlineAllData.bin",
descriptorfile="AirlineAllData.desc")
� 行列サイズの確認
> dim(airline)
[1] 123534969 29
� 行列要素へのアクセス・値の格納
> airline[1:5, 1:5]
> airline[1:5, ]
> airline[1:5, 1] <- 1986
通常のRの関数を使った場合とほとんど同じように操作できる
28
33. 4.2 bigmemoryを用いた並列計算
� 旅客機の製造後の経過年数を推定する問題
(Vignette "The Bigmemory Project"に掲載されている例)
> # 1つの旅客機のフライト日から製造された月を推定する関数
> birthmonth <- function(y) {
+ minYear <- min(y[,'Year'], na.rm=TRUE)
+ these <- which(y[,'Year']==minYear)
+ minMonth <- min(y[these,'Month'], na.rm=TRUE)
+ return(12*minYear + minMonth - 1)
33
34. � 普通にやろうとすると・・・
> # 旅客機コード
> allplanes <- unique(x[,'TailNum'])
> planeStart <- rep(0, length(allplanes))
> # 各旅客機に対してfor文で製造月を推定
> for (i in allplanes) {
+ planeStart[i] <- birthmonth( x[mwhich(x, 'TailNum', i, 'eq'),
+ c('Year', 'Month'), drop=FALSE] )}
34
35. � 普通にやろうとすると・・・
> # 旅客機コード
> allplanes <- unique(x[,'TailNum'])
> planeStart <- rep(0, length(allplanes))
> # 各旅客機に対してfor文で製造月を推定
> for (i in allplanes) {
+ planeStart[i] <- birthmonth( x[mwhich(x, 'TailNum', i, 'eq'),
+ c('Year', 'Month'), drop=FALSE] )}
約9時間もかかる!!
35
36. � そこで,異なるアプローチで計算を行う
> library(bigtabulate)
> # 旅客機コードごとのレコード番号
> planeindices <- bigsplit(x, 'TailNum')
> library(doMC)
> registerDoMC(cores=2)
> # 製造月の推定
> planeStart <-
+ foreach(i=planeindices, .combine=c) %dopar% {
+ return(birthmonth(x[i, c('Year','Month'),
+ drop=FALSE]))
+ }
36
37. � そこで,異なるアプローチで計算を行う
> library(bigtabulate)
> # 旅客機コードごとのレコード番号
> planeindices <- bigsplit(x, 'TailNum')
> library(doMC)
> registerDoMC(cores=2)
> # 製造月の推定
> planeStart <-
+ foreach(i=planeindices, .combine=c) %dopar% {
+ return(birthmonth(x[i, c('Year','Month'),
+ drop=FALSE]))
+ }
14秒!!
37
38. � そこで,異なるアプローチで計算を行う
> library(bigtabulate)
> # 旅客機コードごとのレコード番号
> planeindices <- bigsplit(x, 'TailNum')
> library(doMC) 2コアを使って
> registerDoMC(cores=2) 並列計算
> # 製造月の推定
> planeStart <-
+ foreach(i=planeindices, .combine=c) %dopar% {
+ return(birthmonth(x[i, c('Year','Month'),
+ drop=FALSE]))
+ }
14秒!!
38
39. � そこで,異なるアプローチで計算を行う
> library(bigtabulate)
> # 旅客機コードごとのレコード番号
> planeindices <- bigsplit(x, 'TailNum')
> library(doMC) 2コアを使って
> registerDoMC(cores=2) 並列計算
> # 製造月の推定 旅客機ごとに
> planeStart <- ジョブを分割
+ foreach(i=planeindices, .combine=c) %dopar% {
+ return(birthmonth(x[i, c('Year','Month'),
+ drop=FALSE]))
+ }
14秒!!
39
40. � そこで,異なるアプローチで計算を行う
> library(bigtabulate)
> # 旅客機コードごとのレコード番号
> planeindices <- bigsplit(x, 'TailNum')
> library(doMC) 2コアを使って
> registerDoMC(cores=2) 並列計算
> # 製造月の推定 旅客機ごとに
> planeStart <- ジョブを分割
+ foreach(i=planeindices, .combine=c) %dopar% {
+ return(birthmonth(x[i, c('Year','Month'),
+ drop=FALSE]))
+ } 旅客機ごとの製造月の推定
14秒!!
40
41. � そこで,異なるアプローチで計算を行う
> library(bigtabulate)
> # 旅客機コードごとのレコード番号
> planeindices <- bigsplit(x, 'TailNum')
> library(doMC) 2コアを使って
> registerDoMC(cores=2) 並列計算
> # 製造月の推定 旅客機ごとに
結果の集約
> planeStart <- ジョブを分割
+ foreach(i=planeindices, .combine=c) %dopar% {
+ return(birthmonth(x[i, c('Year','Month'),
+ drop=FALSE]))
+ } 旅客機ごとの製造月の推定
14秒!!
41
43. CPU
CPU
CPU
CPU
2コアを使って
並列計算
43
44. CPU
CPU
CPU
CPU
旅客機ごとに 2コアを使って
ジョブを分割 並列計算
44
45. CPU
CPU
CPU
CPU
旅客機ごとに 2コアを使って 旅客機ごとの
ジョブを分割 並列計算 製造月の推定
45
46. CPU
CPU
CPU
CPU
旅客機ごとに 2コアを使って 旅客機ごとの 結果の集約
ジョブに分割 並列計算 製造月の推定
46
47. split
CPU
CPU
CPU
CPU
旅客機ごとに 2コアを使って 旅客機ごとの 結果の集約
ジョブに分割 並列計算 製造月の推定
47
48. split apply
CPU
CPU
CPU
CPU
旅客機ごとに 2コアを使って 旅客機ごとの 結果の集約
ジョブを分割 並列計算 製造月の推定
48
52. 4.4.2 設計方針
bigkmeans <- function (x, centers, iter.max = 10, nstart = 1){
(中略)
ans <- foreach(cen = centers, .combine = "choosebest") %dopar% {
require(biganalytics)
(中略)
if (is.null(xdesc)) {
if (mattype == 4) {
res <- .Call("kmeansRIntMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
} else {
res <- .Call("kmeansRNumericMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
}
}
(以降略)
}
52
53. bigkmeans <- function (x, centers, iter.max = 10, nstart = 1){
(中略) 並列計算
ans <- foreach(cen = centers, .combine = "choosebest") %dopar% {
require(biganalytics)
(中略)
if (is.null(xdesc)) {
if (mattype == 4) {
res <- .Call("kmeansRIntMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
} else {
res <- .Call("kmeansRNumericMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
}
}
(以降略)
}
53
54. bigkmeans <- function (x, centers, iter.max = 10, nstart = 1){
(中略) 並列計算 クラスター中心(split)
ans <- foreach(cen = centers, .combine = "choosebest") %dopar% {
require(biganalytics)
(中略)
if (is.null(xdesc)) {
if (mattype == 4) {
res <- .Call("kmeansRIntMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
} else {
res <- .Call("kmeansRNumericMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
}
}
(以降略)
}
54
55. bigkmeans <- function (x, centers, iter.max = 10, nstart = 1){
(中略) 並列計算 クラスター中心(split)
ans <- foreach(cen = centers, .combine = "choosebest") %dopar% {
require(biganalytics)
(中略)
if (is.null(xdesc)) {
if (mattype == 4) {
res <- .Call("kmeansRIntMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
} else {
res <- .Call("kmeansRNumericMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
}
}
1回のk平均法の
実行(apply)
(以降略)
}
55
56. bigkmeans <- function (x, centers, iter.max = 10, nstart = 1){
(中略) 並列計算 クラスター中心(split)
ans <- foreach(cen = centers, .combine = "choosebest") %dopar% {
require(biganalytics) 結果の集約(combine)
(中略)
if (is.null(xdesc)) {
if (mattype == 4) {
res <- .Call("kmeansRIntMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
} else {
res <- .Call("kmeansRNumericMatrix", x, center@address,
clust@address, clustsizes@address, wss@address,
as.integer(iter.max))
}
}
1回のk平均法の
実行(apply)
(以降略)
}
56
57. 4.4.3 bigkmeans関数を用いて計算が速くなる例
� UCI Machine Learning Repository
Gisette Data Set
http://archive.ics.uci.edu/ml/datasets/Gisette
� 手書きの数字の「4」と「9」の5000個の特徴に関するデータ
セット
� 13,500レコード,5000フィールド
� 3つのケースについて計算速度を比較する
� クラスター数は2個
� 収束までの最大反復回数は50回
� クラスタリングの試行回数は10回
k平均法
kmeans関数 bigkmeans関数
データの read.table関数 ① ②
読み込み read.big.matrix関数 ③ ー
57
58. ① read.table関数 + kmeans関数
> z.rt <- read.table("gisette.data", sep="", header=FALSE)
> system.time(z.rt.km <- kmeans(z.rt, centers=2, iter.max=50,
+ nstart=10, algorithm="MacQueen"))
ユーザ システム 経過
413.31 3.18 416.79
② read.table関数 + bigkmeans関数
> z.mat <- as.matrix(z.rt)
> system.time(z.rt.bkm <- bigkmeans(z.mat, centers=2, iter.max=50,
+ nstart=10))
ユーザ システム 経過
316.07 0.06 316.46
③ read.big.matrix関数 + bigkmeans関数
> z.bm <- read.big.matrix("gisette.data", sep="", header=FALSE,
+ type="integer")
> system.time(z.bm.bkm <- bigkmeans(z.bm, centers=2, iter.max=50,
+ nstart=10))
ユーザ システム 経過
131.82 1.01 132.90
58
64. bignaiveBayes <- function(x, ...)
UseMethod("bignaiveBayes")
bignaiveBayes.default <-function(x, ccols, summary.cols, laplace = 0,
datatype, ...) {
call <- match.call()
if (length(summary.cols) != length(datatype))
stop("length(summary.cols) must equal length(datatype)n")
# estimation-function
apriori <- bigtable(x, ccols)
Yname <- names(apriori)
tables <- lapply(summary.cols,
function(i) if (datatype[i] == "char") {
tab <- bigtable(x, c(ccols, i))
(tab + laplace) /
(rowSums(tab) + laplace * ncol(tab))
} else {
z <- bigtsummary(x, ccols=ccols, cols=i)
z <- sapply(z, function(zz) zz[, c("mean", "sd")])
as.table(t(z))
}
)
# fix dimname names
names(tables) <- colnames(x)[summary.cols]
structure(list(apriori = apriori, tables = tables, levels = Yname, call =
call), class = "bignaiveBayes")
}
64
65. predict.bignaiveBayes <- function(object, newdata, type = c("class", "raw"), threshold =
0.001, datatype, ...) {
type <- match.arg(type)
attribs <- which(names(object$tables) %in% colnames(newdata))
isnumeric <- datatype!="char"
L <- sapply(1:nrow(newdata), function(i) {
ndata <- newdata[i,]
L <- log(object$apriori) + apply(log(sapply(attribs, function(v) {
nd <- ndata[v]
if(is.na(nd)) rep(1, length(object$apriori))
else {
prob <- if (isnumeric[v]) {
msd <- object$tables[[v]]
msd[,2][msd[,2]==0] <- threshold
dnorm(nd, msd[,1], msd[,2])
} else
object$tables[[v]][,nd]
prob[prob == 0] <- threshold
prob
}
})), 1, sum)
if (type == "class") L
else {
L <- exp(L)
L / sum(L)
}
})
if (type == "class")
factor(object$levels[apply(L, 2, which.max)], levels = object$levels)
else t(L)
}
65
67. � 統計解析ツールとして有望なRは大規模なデータを扱う
ことが得意ではない.
� そのため,Rで大規模なデータを管理,分析しようとす
ると工夫が必要.
� bigmemoryパッケージを用いるとディスクを用いてRAMを
はるかに超える量のデータを管理でき,また同一計算機
上の複数プロセスでオブジェクトを共有できる.
� bigmemoryとその兄弟パッケージを用いると大規模デー
タの管理や集計が可能だが,biganalyticsパッケージに
入っている分析用の関数はまだまだ少ない.
� そこで,機械学習のアルゴリズムを実装しようと試みた
(to be coninued).
67
68. 参考文献
� Bigmemory Project
� Michael J. Kane and John W. Emerso(2010):
The Bigmemory project,
http://cran.rproject.org/web/packages/bigmemory/vignettes/Overv
iew.pdf.
� Michael J. Kane and John W. Emerso(2010):
Scalable strategies for computing with massive data: The
Bigmemory project,
http://www.slideshare.net/joshpaulson/big-memory?from=ss_embed.
� 「Rを使ったハイパフォーマンスコンピューティング入門」,
統計数理研究所公開講座,2011年1月24日.
68