miniCRAN で Azure Machine Learning 用のリポジトリーを作る


本記事は R Advent Calendar 2016 に参加しています。

Azure Machine Learning(Azure ML)を使うと、分析処理を容易に WebAPI 化することができて便利です。分析モジュールは細分化することができ、 R や Python で処理を記述することができます。 R Advent Calendar なのでもちろん R の話です。

R で処理を行う際に、自作他作問わず様々なパッケージを導入する必要がありますが、 Azure ML だとパッケージの導入は少し手間がかかります。というのは Azure ML の分析モジュールではインターネットアクセスを行うことができず、 `install.packages` 関数や `devtools` パッケージの install 系関数では単純にパッケージをインストールすることができないからです。

ではどうするかというと、パッケージを CRAN と同じディレクトリー構造で Windows バイナリーパッケージを配置し(後述)、それを zip ファイルにまとめて DATASETS にアップロードします。アップロードした zip ファイルは、下図のようにして expreriment のモジュールとして R モジュールに渡します。

zip ファイルは C ドライブの src フォルダーに展開されますので、 R スクリプトから参照することができ、以下のようなコードでパッケージをインストールできます。

repos_uri <- "file:///C:/src/myrepos"
install.packages("mypackage", repos = repos_uri)

azureml

さて、 CRAN と同じディレクトリー構造でパッケージを配置するにはどうするか、というところで登場するのが、題名にもある miniCRAN パッケージです。名前の通り、小さな CRAN みたいなもの(ローカルリポジトリー)を作ることができ、今回の目的である CRAN と同じディレクトリー構造でパッケージを配置することを容易にします。

使い方は簡単で、以下のようにパッケージ名のベクトルを `makeRepo` 関数に与えるだけです。

library(miniCRAN)
pkg_list <- c("dplyr", "tidyr")
makeRepo(
   pkg_list, path = "myrepos", download = TRUE,
   type = "win.binary", Rversion = "3.1.0"
)

ここで重要なのは、 `type = "win.binary"` と `Rversion = "3.1.0"` です。 Azure ML は Windows 上の R 3.1.0 で動作するため、 OS と R のバージョンを明示的に指定する必要があります。ちなみに R のバージョンは CRAN の R 3.1.0 の他に、 Microsoft R Open 3.2.2 も選ぶことができ、どちらを選ぶかによって `makeRepo` 関数に指定する `Rversion` のバージョンも変更します。ローカルリポジトリー内はディレクトリー構造でバージョンを分けているので、両バージョンが混在したローカルリポジトリーを作成することもできます。

miniCRAN パッケージには、パッケージの依存関係を解決するための関数も用意されており、自作関数を使った分析モジュールを作る場合には、必要最低限のパッケージを選択してローカルリポジトリーを作ることも簡単にできます。

私は Azure ML にアップロードする独自パッケージを作成する際に、以下のような感じのスクリプトを利用して、 Windows 上で Azure ML にアップロードするローカルリポジトリーの zip ファイルを作成しています。 zip コマンドは Rtools に付属しているものにパスを通して利用しています。

library(magrittr)

# 3.1.0: CRAN R
# 3.2.2: Microsoft R Open
AZUREML_R_VERSION <- "3.1.0"
PACKAGE_NAME <- "mypackage"
# 最初からインストールされているパッケージ
DEFAULT_PACKAGES <- c("base", "methods", "utils", "grDevices", "graphics", "stats", "datasets")

## 依存関係とバージョンを取得するためにインストール
binary_package <- devtools::build(binary = TRUE)
install.packages(binary_package, repos = NULL, type = "binary")
PACKAGE_VERSION <- installed.packages()[PACKAGE_NAME, "Version"]

REPO_PATH <- "myrepos"
PACKAGE_ZIP <- sprintf("%s.zip", REPO_PATH)

## 依存パッケージ
pkgs <- miniCRAN::pkgDep(PACKAGE_NAME, installed.packages(), recursive = TRUE) %>%
   unlist() %>%
   unique() %>%
   setdiff(DEFAULT_PACKAGES)
pdb <- miniCRAN::pkgAvail(Rversion = AZUREML_R_VERSION)
deps <- miniCRAN::pkgDep(pkgs, availPkgs = pdb)

## CRAN リポジトリ作成
if (dir.exists(REPO_PATH)) {
   unlink(REPO_PATH, recursive = TRUE, force = TRUE)
}
dir.create(REPO_PATH, recursive = TRUE)
miniCRAN::makeRepo(deps, path = REPO_PATH, download = TRUE, type = "win.binary", Rversion = AZUREML_R_VERSION)

## 独自パッケージを追加
minor_version <- sub("^(\\d+\\.\\d+)\\D*.*$", "\\1", AZUREML_R_VERSION)
dest <- file.path(REPO_PATH, "bin", "windows", "contrib", minor_version, basename(binary_package))
file.rename(binary_package, dest)

## CRAN のアップデート
miniCRAN::updateRepoIndex(REPO_PATH, type = "win.binary", Rversion = AZUREML_R_VERSION)

## zip 作成
zip(PACKAGE_ZIP, REPO_PATH)

まとめ

Azure ML でパッケージを利用するには、ローカルリポジトリーを作成する必要があります。ローカルリポジトリーの作成には miniCRAN パッケージが便利です。

参考文献