2010-01-24 12 views
9

Ich arbeite an einem Code, der ein Dataset übernimmt und einige Algorithmen darauf ausführt.Verarbeiten eines einfachen Workflows in Python

Börse einen Datensatz, und wählt dann die Algorithmen auf diesem Datensatz ausgeführt werden und erstellt einen Workflow wie folgt aus:

workflow = 
{0: {'dataset': 'some dataset'}, 
1: {'algorithm1': "parameters"}, 
2: {'algorithm2': "parameters"}, 
3: {'algorithm3': "parameters"} 
} 

Was bedeutet, dass ich workflow[0] als mein Dataset nehmen werde, und ich werde algorithm1 laufen darauf. Dann werde ich seine Ergebnisse nehmen und ich werde algorithm2 auf diese Ergebnisse als meine neue Datenmenge ausführen. Und ich werde die neuen Ergebnisse nehmen und algorithm3 darauf laufen lassen. Es geht so bis zum letzten Artikel und es gibt keine Längenbeschränkung für diesen Workflow.

Ich schreibe dies in Python. Können Sie Strategien zur Verarbeitung dieses Workflows vorschlagen?

Antwort

9

Sie möchten eine Pipeline auf einem Dataset ausführen. Das klingt nach einem Reduce-Vorgang (in einigen Sprachen).Keine Notwendigkeit für etwas kompliziert:

result = reduce(lambda data, (aname, p): algo_by_name(aname)(p, data), workflow) 

Dies setzt voraus, Workflow sieht aus wie (textorientiert, so dass Sie es mit YAML/JSON laden kann):

workflow = ['data', ('algo0', {}), ('algo1', {'param': value}), … ] 

Und dass Ihre Algorithmen wie folgt aussehen:

def algo0(p, data): 
    … 
    return output_data.filename 

algo_by_name nimmt einen Namen und gibt Ihnen eine Algo-Funktion; zum Beispiel:

def algo_by_name(name): 
    return {'algo0': algo0, 'algo1': algo1, }[name] 

(alt edit:.., wenn Sie einen Rahmen für das Schreiben von Pipelines wollen, könnten Sie Ruffus verwenden Es ist wie ein Make-Tool, aber mit dem Fortschritt Unterstützung und ziemlich Flussdiagramme)

+0

Ausgezeichnet und elegant. –

+0

Tut mir leid, dass ich der Neuling bin, aber ich konnte den Code nicht funktionieren lassen. Werde ich Algorithmusnamen von algo_by_name Funktion zurückgeben? –

+0

algo_by_name (aname) muss eine Funktion sein, damit Sie (p, data) daran übergeben können. Ich habe ein Beispiel geschrieben. – Tobu

2

Die Art und Weise, wie Sie es tun möchten, scheint mir gut zu sein, oder Sie müssen mehr Informationen über das, was Sie erreichen wollen, veröffentlichen.

Und Beratung: Ich würde den Workflow-Struktur in einer Liste mit Tupeln anstatt ein Wörterbuch setzen

workflow = [ ('dataset', 'some dataset'), 
      ('algorithm1', "parameters"), 
      ('algorithm2', "parameters"), 
      ('algorithm3', "parameters")] 
4

Wenn jeder algorithm Werke auf jedem Element auf dataset würde map() eine elegante Option:

dataset=workflow[0] 
for algorithm in workflow[1:]: 
    dataset=map(algorithm, dataset) 

z nur für die Quadratwurzeln der ungeraden Zahlen, die Verwendung,

>>> 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] 
+0

Weniger prägnant und elegant vielleicht als die am höchsten bewertete Antwort, aber ich würde dies für die Lesbarkeit und weitere Verwendung von anderen Benutzern bevorzugen. – Morlock

1

definieren Dataset Klasse, die Tracks ... Daten ... für Ihr Gerät. Definieren Sie Methoden in dieser Klasse. So etwas wie dieses:

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 

Jetzt iterieren Sie über Ihre "Workflow" dict. Für den ersten Eintrag instanziieren Sie einfach Ihre Dataset Klasse.

myDataset = Dataset() # Whatever actual construction you need to do 

Für jeden nachfolgenden Eintrag ...

  • irgendwie den Schlüssel/Wert-Extrakt (I Ihre Workflow-Datenstruktur zu ändern empfehlen würde, wenn möglich, dict unbequem hier ist)
  • Analysieren Sie die param string zu einem Tupel von Argumenten (dieser Schritt liegt bei Ihnen).
  • Sie jetzt die Zeichenfolge algorithm und das Tupel params für die aktuelle Iteration ...

    getattr (MyDataSet, Algorithmus) (* params)

  • Dies ruft die Funktion auf myDataset mit dem hast Unter der Annahme, Name, der von "algorithm" mit der in "params" enthaltenen Argumentliste angegeben wird.

1

Hier Wie würde ich das machen (alle Codes nicht getestet):

Schritt 1: Sie müssen die Algorithmen erstellen. Der Datensatz könnte wie folgt aussehen:

class Dataset(object): 
    def __init__(self, dataset): 
     self.dataset = dataset 

    def __iter__(self): 
     for x in self.dataset: 
      yield x 

Beachten Sie, dass Sie einen Iterator daraus zu machen, so dass Sie iterieren es ein Element zu einem Zeitpunkt. Es gibt einen Grund dafür, werden Sie später sehen:

Ein anderer Algorithmus könnte wie folgt aussehen:

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 

Schritt 2

Ihre Benutzer würde dann irgendwie eine Kette daraus machen müssen. Nun, wenn er direkt Zugriff auf Python hat, können Sie einfach tun:

dataset = Dataset(range(100)) 
multiplier = Multiplier(dataset, 5) 

und dann die Ergebnisse durch:

for x in multiplier: 
    print x 

Und es würde den Multiplikator für ein Stück von Daten zu einer Zeit fragen und der Multiplikator würde wiederum als Datensatz verwendet. Wenn Sie eine Kette haben, bedeutet dies, dass ein Teil der Daten gleichzeitig bearbeitet wird. Dies bedeutet, dass Sie große Datenmengen verarbeiten können, ohne viel Arbeitsspeicher zu benötigen.

Schritt 3

Wahrscheinlich wollen Sie die Schritte in einer anderen Art und Weise spezifizieren. Zum Beispiel eine Textdatei oder eine Zeichenkette (klingt wie diese kann webbasiert sein?). Dann brauchen Sie eine Registrierung über die Algorithmen. Der einfachste Weg ist, ein Modul namens "registry.py" wie folgt zu erstellen:

algorithms = {} 

Einfach, was? Sie würden einen neuen Algorithmus wie so registrieren:

from registry import algorithms 
algorithms['dataset'] = Dataset 
algorithms['multiplier'] = Multiplier 

Sie auch ein Verfahren bräuchten, die die Kette von den Spezifikationen in einer Textdatei oder etwas schafft. Das überlasse ich dir. ;)

(Ich würde wahrscheinlich die Zope Component Architecture verwenden und Algorithmenkomponenten erstellen und sie in der Komponentenregistrierung registrieren. Aber das ist alles streng genommen Overkill).

Verwandte Themen