7

R経由でH2Oを使用して、1つの大規模なデータセット(〜10GB)のサブセットを使用して複数のモデルを構築しようとしています. データは 1 年分のデータであり、私は 51 個のモデル (つまり、1 週目にトレーニング、2 週目に予測など) を構築しようとしています。各週は、8 つの変数を持つ約 150 万から 250 万行です。

私はこれをループ内で実行しましたが、これは R で常に最善の方法であるとは限りません。私が見つけたもう 1 つの問題は、H2O エンティティが以前のオブジェクトを蓄積することでした。そのため、メイン データを除くすべてのオブジェクトを削除する関数を作成しました。設定。

h2o.clean <- function(clust = localH2O, verbose = TRUE, vte = c()){
  # Find all objects on server
  keysToKill <- h2o.ls(clust)$Key
  # Remove items to be excluded, if any
  keysToKill <- setdiff(keysToKill, vte)
  # Loop thru and remove items to be removed
  for(i in keysToKill){
    h2o.rm(object = clust, keys = i)

    if(verbose == TRUE){
      print(i);flush.console()

    }    
  }
  # Print remaining objects in cluster.
  h2o.ls(clust)
}

スクリプトはしばらくの間正常に実行された後、クラッシュします。多くの場合、メモリ不足やディスクへのスワップに関する問題が発生します。

プロセスを説明するための擬似コードを次に示します

# load h2o library
library(h2o)
# create h2o entity
localH2O = h2o.init(nthreads = 4, max_mem_size = "6g")
# load data
dat1.hex = h2o.importFile(localH2O, inFile, key = "dat1.hex")

# Start loop
for(i in 1:51){
# create test/train hex objects
train1.hex <- dat1.hex[dat1.hex$week_num == i,]
test1.hex <- dat1.hex[dat1.hex$week_num == i + 1,]
# train gbm
dat1.gbm <- h2o.gbm(y = 'click_target2', x = xVars, data = train1.hex
                      , nfolds = 3
                      , importance = T
                      , distribution = 'bernoulli' 
                      , n.trees = 100
                      , interaction.depth = 10,
                      , shrinkage = 0.01
  )
# calculate out of sample performance
test2.hex <- cbind.H2OParsedData(test1.hex,h2o.predict(dat1.gbm, test1.hex))
colnames(test2.hex) <- names(head(test2.hex))
gbmAuc <- h2o.performance(test2.hex$X1, test2.hex$click_target2)@model$auc

# clean h2o entity
h2o.clean(clust = localH2O, verbose = F, vte = c('dat1.hex'))

} # end loop

私の質問は、このタイプのスタンドアロン エンティティ (これは Hadoop またはクラスターで実行されていない - 単なる大規模な EC2 インスタンス (~ 64 GB RAM + 12 CPU)) でデータとメモリを管理する正しい方法がある場合、それは何かということです。プロセスの?各ループの後に H2O エンティティを強制終了して再作成する必要がありますか (これは元のプロセスでしたが、毎回ファイルからデータを読み取ると、反復ごとに約 10 分かかります)。各ループ後にメモリをガベージ コレクションまたは解放する適切な方法はありますか?

任意の提案をいただければ幸いです。

4

4 に答える 4

9

この回答は、元の H2O プロジェクト (リリース 2.xyz) に対するものです。

元の H2O プロジェクトでは、H2O R パッケージは、H2O クラスター DKV (分散キー/値ストア) に「Last.value」プレフィックスを持つ多くの一時的な H2O オブジェクトを作成します。

これらは、Web UI からの Store ビューと、R からの h2o.ls() の呼び出しの両方で表示されます。

私がお勧めすることは次のとおりです。

  • 各ループ反復の最後で、 h2o.assign() を使用して、既知のキー名に保存したいもののディープコピーを実行します
  • h2o.rm() を使用して、保持したくないもの、特に「Last.value」一時を削除します
  • ループのどこかで R で明示的に gc() を呼び出す

Last.value 一時オブジェクトを削除する関数を次に示します。引数として H2O 接続オブジェクトを渡します。

removeLastValues <- function(conn) {
    df <- h2o.ls(conn)
    keys_to_remove <- grep("^Last\\.value\\.", perl=TRUE, x=df$Key, value=TRUE)
    unique_keys_to_remove = unique(keys_to_remove)
    if (length(unique_keys_to_remove) > 0) {
        h2o.rm(conn, unique_keys_to_remove)
    }
}

H2O github リポジトリ内の R テストへのリンクを次に示します。この手法は、この手法を使用し、メモリ不足になることなく無期限に実行できます。

https://github.com/h2oai/h2o/blob/master/R/tests/testdir_misc/runit_looping_slice_quantile.R

于 2015-03-30T02:50:02.433 に答える
4

2015 年 12 月 15 日現在の新しい提案: 最新の安定版 (Tibshirani 3.6.0.8 以降) に更新します。R と H2O が内部の一時変数を処理する方法を完全に作り直し、メモリ管理がよりスムーズになりました。

次へ: H2O temps は、R デッド変数によって "生きている" 状態に保つことができます... そのため、ループの反復ごとに R gc() を実行します。R の GC がデッド変数を削除すると、H2O はそのメモリを再利用します。

その後、クラスターは、ロードされたデータセットやモデルなど、具体的に名前が付けられたもののみを保持する必要があります。これらは、K/V ストアに大量のデータが蓄積されないように、作成とほぼ同じ速さで削除する必要があります。

さらに問題がある場合は、Google グループの h2o ストリームに投稿してお知らせください: https://groups.google.com/forum/#!forum/h2ostream

于 2015-12-16T18:07:17.340 に答える
2

この質問に対する最新の答えはh2o.grid()、ループを記述するのではなく、おそらく関数を使用する必要があるということです。

于 2017-08-01T16:04:35.067 に答える