我在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毫秒)两种情况)。
我的问题是:
真的是这样吗?谁能证实我没有做错什么? 我知道H2O是建立在JVM之上的,它不应该闪电般快,但我认为它们至少和scikit-learn一样好。
我需要在回归算法中实现预测的超快速。有没有人有什么建议?
scikit-learn / H2O对我来说不是强制性的,但我需要一些可靠的东西。
答案 0 :(得分:1)
H2O使用数据并行来实现规模和效率,这里的行数非常少,因此执行工作的并行线程数可能很少。
当有更多行(数百万+)时,H2O的速度和比例有利。
您可以使用内置的Water Meter(在Linux上)或“top”或其他性能监视工具来查看有多少线程在工作。如果您打开H2O Flow Web UI,在解析数据后,您可以看到详细的Frame Distribution Summary细分(见下文)。
对于此示例,我摄取的数据集有43,478行和31列。您可以看到每列的块数为1.这意味着我的数据并行级别仅为1,并且只有1个线程可以正常工作。 H2O被设计为在更大的数据集上有效。
答案 1 :(得分:1)
我认为基准测试中有一些问题是错误的:
col_sample_rate_per_tree=0.3
,而在sklearn中,您有max_features=0.25
。您应该在H2O中将col_sample_rate
设置为与sklearn中的max_features
相同的内容。在sklearn中使用较少的功能将使sklearn更快地训练。min_samples_leaf=3
,但min_rows
(相当于H2O)默认为1.这些应设置为相同的值。它们都默认为1,所以你应该把它们都保留为默认值。设置min_samples_leaf=3
将迫使sklearn更快地停止构建树(因此训练会更快)。stopping_rounds=2
。score_each_iteration
和sklearn中的oob_score
)。也就是说,在小型数据集中,sklearn仍然可以比H2O更快地训练。 H2O在设计时考虑了可扩展性,因此当您使用更多的训练数据时,您将开始看到H2O的值(超过其他工具)。在benchmark(下面的屏幕截图)中,随着训练大小的增加,H2O随机森林与其他工具的对比情况很好。这仅适用于单个数据集,因此不能推广到所有情况,但它很好地证明了sklearn等工具在训练大小增加时如何开始分解(sklearn RF在此行中的1M行之后耗尽内存基准)。
答案 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需要建立基准,以反映他们对模型使用的真正期望:开销是否更重要(不太可能),或者每次预测的时间是否更重要。