H2O的性能预测()函数

时间:2017-08-07 13:08:04

标签: python performance python-3.x machine-learning h2o


我在python中使用H2O的Random Forest Regression模型。在评估其速度方面的表现时,我将其与scikit-learn的RandomForestRegressor进行了比较。

数据集由~20,000行和20列数据组成。
我的机器运行带有python 3.6的窗口。

import time
import h2o
import pandas as pd
from h2o.estimators.random_forest import H2ORandomForestEstimator
from sklearn.ensemble import RandomForestRegressor

def timing(f):
    def wrap(*args):
        time1 = time.time()
        ret = f(*args)
        time2 = time.time()
        print('%s function took %0.3f ms' % (f.__name__ , (time2-time1)*1000.0))
        return ret
    return wrap


@timing
def predict_row(model, row):
    return model.predict(row)


# read data
h2o.init(max_mem_size = "8G")
h2o.remove_all() 
h2o_df = h2o.import_file(csv_path)
train, valid, test = h2o_df.split_frame([0.6, 0.2], seed=1234)
X = h2o_df.col_names[:-1]
y = h2o_df.col_names[-1]  


# random forest at H2O
rf_h2o = H2ORandomForestEstimator(model_id="rf_h2o_v1", ntrees=100, stopping_rounds=2, score_each_iteration=True, seed=1000000,
                             col_sample_rate_per_tree=0.3)
rf_h2o.train(X, y, training_frame=train, validation_frame=valid)


# random forest at sklearn
train_df = train[:-1].as_data_frame(use_pandas=True)
y_df = h2o_df[:,-1].as_data_frame(use_pandas=True)
y_df = y_df[y_df.index.isin(train_df.index)]
rf_sklearn = RandomForestRegressor(n_estimators=100, min_samples_leaf=3, oob_score=True, max_features=0.25)
rf_sklearn.fit(train_df, y_df)


# prediction comparison, let's take row #5 from the test set for example
row_h20 = test[5,:-1]
row_array = test[5,:-1].as_data_frame(use_pandas=True).values
rf_sklearn.predict(row_array)

# run 20 times and test performance on all iterations
for i in range(20):
    predict_row(rf_sklearn, row_array)
    predict_row(rf_h2o, row_h20)

当我运行这段代码时,我通过scikit-learn得到了随机森林 X4-5倍比H2O的模型(6-7毫秒与最快迭代的~30毫秒)两种情况)。
我的问题是:

  1. 真的是这样吗?谁能证实我没有做错什么? 我知道H2O是建立在JVM之上的,它不应该闪电般快,但我认为它们至少和scikit-learn一样好。

  2. 我需要在回归算法中实现预测的超快速。有没有人有什么建议?
    scikit-learn / H2O对我来说不是强制性的,但我需要一些可靠的东西。

4 个答案:

答案 0 :(得分:1)

H2O使用数据并行来实现规模和效率,这里的行数非常少,因此执行工作的并行线程数可能很少。

当有更多行(数百万+)时,H2O的速度和比例有利。

您可以使用内置的Water Meter(在Linux上)或“top”或其他性能监视工具来查看有多少线程在工作。如果您打开H2O Flow Web UI,在解析数据后,您可以看到详细的Frame Distribution Summary细分(见下文)。

对于此示例,我摄取的数据集有43,478行和31列。您可以看到每列的块数为1.这意味着我的数据并行级别仅为1,并且只有1个线程可以正常工作。 H2O被设计为在更大的数据集上有效。

enter image description here

答案 1 :(得分:1)

我认为基准测试中有一些问题是错误的:

  • 在H2O中,您有col_sample_rate_per_tree=0.3,而在sklearn中,您有max_features=0.25。您应该在H2O中将col_sample_rate设置为与sklearn中的max_features相同的内容。在sklearn中使用较少的功能将使sklearn更快地训练。
  • 在sklearn中,您有min_samples_leaf=3,但min_rows(相当于H2O)默认为1.这些应设置为相同的值。它们都默认为1,所以你应该把它们都保留为默认值。设置min_samples_leaf=3将迫使sklearn更快地停止构建树(因此训练会更快)。
  • 请勿在H2O中设置stopping_rounds=2
  • 在sklearn vs H2O中有许多其他参数具有不同的默认值。
  • 我建议在每次迭代时使用和不使用评分来运行基准测试,以了解它对性能的影响(参考H2O中的score_each_iteration和sklearn中的oob_score)。
  • 我假设您的数据仅包含数字要素,但如果您使用包含分类要素的数据集,则sklearn将要求您对这些要素进行单热编码,这可能会增加您的训练时间,具体取决于每个分类功能的级别数。

也就是说,在小型数据集中,sklearn仍然可以比H2O更快地训练。 H2O在设计时考虑了可扩展性,因此当您使用更多的训练数据时,您将开始看到H2O的值(超过其他工具)。在benchmark(下面的屏幕截图)中,随着训练大小的增加,H2O随机森林与其他工具的对比情况很好。这仅适用于单个数据集,因此不能推广到所有情况,但它很好地证明了sklearn等工具在训练大小增加时如何开始分解(sklearn RF在此行中的1M行之后耗尽内存基准)。

enter image description here

答案 2 :(得分:1)

6-7毫秒与~30毫秒的差异可能是由于进行REST API调用的开销。

为了在生产环境中进行预测,23ms非常重要,我相信建议使用POJO或MOJO。你正在使用随机森林,所以应该使用MOJO,因为它们根据https://github.com/h2oai/h2o-3/blob/master/h2o-docs/src/product/howto/MOJO_QuickStart.md显着提高了速度

如果您只是为了评估H2O的速度而进行测试,您还应该对非常大的数据集或更复杂的模型进行比较。例如。如果差异是2.006s而不是2.030s你可以不再担心它,并继续做更重要的事情。

答案 3 :(得分:0)

我遇到了类似的问题。我已经对H2O预测进行了编码,可以一次进行一次预测。表现令人失望。这是因为要为H2O进行设置需要大量的开销,包括构建H2O数据帧。

为了使事情变得合理,我批量添加了几行数据以进行预测,现在我获得了不错的性能。

LeDell博士发布的图表清楚地显示了各种平台遇到的各种,有时甚至是巨大的开销。

OP需要建立基准,以反映他们对模型使用的真正期望:开销是否更重要(不太可能),或者每次预测的时间是否更重要。