所以我一直致力于使用不同的参数组合来分配和并行化不同ML算法的执行。我正在集群环境中进行实验,我想尽可能多地利用所有可用资源。 有关详细信息:How are tasks distributed within a Spark cluster?
我的输入包含JSON格式的算法和参数列表。基于这种情况,我有两种方法:
对于我拥有的每个ML算法,我创建了一个SparkGridSearch对象(来自official integration)并将其放入列表中。然后,我在不同的线程上触发这些网格搜索对象的执行,如下所示:
...
for experiment in experiments:
# experiment contains the algorithm and its list of parameters
gridSearchCV = SparkGridSearchCV(spark_context, experiment[0], experiment[1], scoring=experiment[2], cv=experiment[3])
experiment_thread = Thread(target=run_experiment, args=(bcast_dataframe, gridSearchCV))
experiment_thread.start()
输入:
experiments_dict = {
'Decision Tree': {'num_folds': 2, 'evaluation': 'accuracy', 'parameters': {'criterion': ['entropy'], 'class_weight': ['balanced']}},
'Naive Bayes': {'num_folds': 2, 'evaluation': 'accuracy', 'parameters': {}},
'Random Forests': {'num_folds': 2, 'evaluation': 'accuracy', 'parameters': {'n_estimators': [5, 7]}},
'Random Forests_2': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'bootstrap': [True, False], 'criterion': ['entropy'], 'class_weight': ['balanced']}},
'Decision Tree_2': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'splitter': ['random'], 'max_leaf_nodes': [2, 3, None], 'max_depth': [None], 'class_weight': ['balanced', None]}},
...
}
我还创建了一个列表,其中每个元素都是一个具有一个参数组合的算法。因此,该列表的大小比前一种方法大得多,因为每个组合是列表的一个元素。在这种情况下,我只需在此列表中使用spark.parallelize
并将其映射到我运行每个ML算法的函数中:
def run_experiment(dataframe, experiment):
...
model = estimator.fit(train_data, train_target)
predicted = model.predict(test_data)
score = accuracy_score(predicted, expected)
return [model, score]
def main():
...
bcast_dataset = spark_context.broadcast(df)
experimentsRDD = spark_context.parallelize(experiments_dict)
print experimentsRDD.map(lambda experiment: run_experiment(bcast_dataset, experiment)).collect()
bcast_dataset.unpersist()
输入:
experiments_dict = {
'Decision Tree': {'num_folds': 2, 'evaluation': 'accuracy', 'parameters': {'criterion': ['entropy'], 'class_weight': ['balanced']}},
'Naive Bayes': {'num_folds': 2, 'evaluation': 'accuracy', 'parameters': {}},
'Random Forests': {'num_folds': 2, 'evaluation': 'accuracy', 'parameters': {'n_estimators': [5]}},
'Random Forests_1_2': {'num_folds': 2, 'evaluation': 'accuracy', 'parameters': {'n_estimators': [7]}},
'Random Forests_2': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'bootstrap': [True, False], 'criterion': ['entropy'], 'class_weight': ['balanced']}},
'Random Forests_2_1': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'bootstrap': [False], 'criterion': ['entropy'], 'class_weight': ['balanced']}},
'Decision Tree_2': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'splitter': ['random'], 'max_leaf_nodes': [2], 'max_depth': [None], 'class_weight': ['balanced']}},
'Decision Tree_2_1': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'splitter': ['random'], 'max_leaf_nodes': [3], 'max_depth': [None], 'class_weight': ['balanced']}},
'Decision Tree_2_2': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'splitter': ['random'], 'max_leaf_nodes': [None], 'max_depth': [None], 'class_weight': ['balanced']}},
'Decision Tree_2_3': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'splitter': ['random'], 'max_leaf_nodes': [2], 'max_depth': [None], 'class_weight': ['None']}},
'Decision Tree_2_4': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'splitter': ['random'], 'max_leaf_nodes': [3], 'max_depth': [None], 'class_weight': ['None']}},
'Decision Tree_2_5': {'num_folds': 3, 'evaluation': 'accuracy', 'parameters': {'splitter': ['random'], 'max_leaf_nodes': [None], 'max_depth': [None], 'class_weight': ['None']}},
...
}
我已经进行了一些实验,并用第二种方法获得了更好的结果。但是,当更改分区数(等于实验数,或可用内核数的2或3倍)时,执行时间不会发生变化。 在多线程方法中使用Spark广播数据集时我也遇到了一些问题,但显然这是一个已知的issue。
我的问题:这些结果有意义吗?为什么分区数不会影响执行时间?我错过了什么或者有什么我可以改进的吗?
谢谢!