我正在开发一个代码,它接受数据集并在其上运行一些算法。
用户上传数据集,然后选择将在此数据集上运行的算法,并创建如下工作流程:
workflow =
{0: {'dataset': 'some dataset'},
1: {'algorithm1': "parameters"},
2: {'algorithm2': "parameters"},
3: {'algorithm3': "parameters"}
}
这意味着我将workflow[0]
作为我的数据集,我将在其上运行algorithm1
。然后,我将获取其结果,我将在此结果上运行algorithm2
作为我的新数据集。我将采用新结果并在其上运行algorithm3
。直到最后一个项目为止,这个工作流程没有长度限制。
我用Python写这个。您能否提出一些有关处理此工作流程的策略?
答案 0 :(得分:10)
您想在某些数据集上运行管道。这听起来像是一种减少操作(在某些语言中折叠)。不需要任何复杂的事情:
result = reduce(lambda data, (aname, p): algo_by_name(aname)(p, data), workflow)
这假设工作流程看起来像(面向文本,因此您可以使用YAML / JSON加载它):
workflow = ['data', ('algo0', {}), ('algo1', {'param': value}), … ]
你的算法看起来像:
def algo0(p, data):
…
return output_data.filename
algo_by_name采用名称并为您提供算法功能;例如:
def algo_by_name(name):
return {'algo0': algo0, 'algo1': algo1, }[name]
(旧编辑:如果你想要一个用于编写管道的框架,你可以使用Ruffus。它就像一个make工具,但有进度支持和漂亮的流程图。)
答案 1 :(得分:4)
如果每个algorithm
都适用于dataset
上的每个元素,那么map()
将是一个优雅的选择:
dataset=workflow[0]
for algorithm in workflow[1:]:
dataset=map(algorithm, dataset)
e.g。对于奇数的平方根,请使用
>>> algo1=lambda x:0 if x%2==0 else x
>>> algo2=lambda x:x*x
>>> dataset=range(10)
>>> workflow=(dataset, algo1, algo2)
>>> for algo in workflow[1:]:
dataset=map(algo, dataset)
>>> dataset
[0, 1, 0, 9, 0, 25, 0, 49, 0, 81]
答案 2 :(得分:2)
你想要这样做的方式对我来说似乎很合理,或者你需要发布更多关于你想要完成的事情的信息。
建议:我会将工作流结构放在带有元组而不是字典的列表中
workflow = [ ('dataset', 'some dataset'),
('algorithm1', "parameters"),
('algorithm2', "parameters"),
('algorithm3', "parameters")]
答案 3 :(得分:1)
定义一个跟踪...数据的Dataset
类。定义此类中的方法。像这样:
class Dataset:
# Some member fields here that define your data, and a constructor
def algorithm1(self, param1, param2, param3):
# Update member fields based on algorithm
def algorithm2(self, param1, param2):
# More updating/processing
现在,迭代你的“工作流程”字典。对于第一个条目,只需实例化您的Dataset
类。
myDataset = Dataset() # Whatever actual construction you need to do
对于每个后续条目......
dict
在这里不方便)假设您现在拥有当前迭代的字符串algorithm
和元组params
...
getattr(myDataset,algorithm)(* params)
这将调用myDataset
上的函数,其名称由“algorithm”指定,参数列表包含在“params”中。
答案 4 :(得分:1)
以下是我将如何执行此操作(所有代码未经测试):
步骤1:您需要创建算法。数据集可能如下所示:
class Dataset(object):
def __init__(self, dataset):
self.dataset = dataset
def __iter__(self):
for x in self.dataset:
yield x
请注意,您从中创建了一个迭代器,因此您一次迭代一个项目。这是有原因的,你稍后会看到:
另一种算法可能如下所示:
class Multiplier(object):
def __init__(self, previous, multiplier):
self.previous = previous
self.multiplier = multiplier
def __iter__(self):
for x in previous:
yield x * self.multiplier
第2步
然后,您的用户需要以某种方式制作链。现在如果他可以直接访问Python,你可以这样做:
dataset = Dataset(range(100))
multiplier = Multiplier(dataset, 5)
然后通过以下方式获得结果:
for x in multiplier:
print x
它会一次询问一个数据的乘数,乘数又将作为数据集。如果你有一个链,那么这意味着一次处理一个数据。这意味着您可以在不占用大量内存的情况下处理大量数据。
第3步
您可能希望以其他方式指定步骤。例如,文本文件或字符串(这样的声音可能是基于网络的?)。然后你需要一个注册表的算法。最简单的方法是创建一个名为“registry.py”的模块,如下所示:
algorithms = {}
容易,嗯?你会注册一个新的算法,如下:
from registry import algorithms
algorithms['dataset'] = Dataset
algorithms['multiplier'] = Multiplier
您还需要一种方法,可以根据文本文件中的规范创建链。我会把它留给你。 ;)
(我可能会使用Zope组件架构并制作算法组件并在组件注册表中注册它们。但这严格来说就是矫枉过正了。)