Nachdem nun Pläne behandelt wurden, wird es jetzt um ein neues Objekt names Protokoll gehen. Ein Protokoll koordiniert eine Sequenz von Plänen und wendet sie auf entfernten Helfern in einem einzigen Durchgang an.
Es ist ein Objekt höchster Ebene und beinhaltet die Logik einer komplexen Berechnung auf mehreren verteilten Helfern. Die wichtigste Eigenschaft eines Protokolls ist die Fähigkeit von Helfern gesendet / gesucht / geholt zu werden und schließlich auf festgelegten Helfern angewendet zu werden.
Somit kann ein Nutzer ein Protokoll erstellen und auf einem Helfer in der Cloud bereit stellen. Jeder andere Helfer kann dieses Protokoll dort suchen, herunterladen und bei sich und allen mit ihm verbundenen Helfern anwenden.
Im Folgenden können Sie sehen, wie das erreicht wird.
Autoren:
Übersetzer:
Protokolle werden mit Listen aus (worker, plan)
-Paaren erstellt. Dabei kann worker
entweder ein echter Helfer, eine Helfer-Id oder auch ein String eines fiktiven Helfers sein. Der letzte Fall kann verwendet werden, um beim Erstellen zu spezifizieren, dass zwei Pläne beim Anwenden zum selben Helfer gehören (oder auch nicht). plan
kann entweder einen Plan oder auch einen PointerPlan enthalten.
In [ ]:
import torch as th
import syft as sy
hook = sy.TorchHook(th)
# IMPORTANT: Local worker should not be a client worker
hook.local_worker.is_client_worker = False
Es werden drei unterschiedliche Pläne erstellt und in einem Protokoll vereint. Jeder der Pläne erhöht den Zähler jeweils um eins.
In [ ]:
@sy.func2plan(args_shape=[(1,)])
def inc1(x):
return x + 1
@sy.func2plan(args_shape=[(1,)])
def inc2(x):
return x + 1
@sy.func2plan(args_shape=[(1,)])
def inc3(x):
return x + 1
protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])
Nun muss das Protokoll noch an die Helfer gebunden werden. Dies wird erreicht mit dem Aufrufen von .deploy(*workers)
. Dafür werden drei Helfer erstellt.
In [ ]:
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
charlie = sy.VirtualWorker(hook, id="charlie")
In [ ]:
workers = alice, bob, charlie
protocol.deploy(*workers)
Wie zu erkennen ist, wurden die Pläne gleich an die richtigen Helfer gesendet: das Protokoll wurde verteilt!
Dies geschah in zwei Phasen:
Ein Protokoll zu starten, bedeutet alle seine Pläne der Reihe nach abzuarbeiten. Dafür werden die Eingabe-Daten an den Ort des ersten Planes gesendet. Dieser erste Plan wird auf die Daten angewendet und seine Ausgabe-Daten an den zweiten Plan weiter geleitet. Dies setzt sich so fort.
Das letzte Ergebnis wird zurückgegeben, sobald alle Pläne abgeschlossen sind. Es enthält Pointer auf den Ort des letzten Planes.
In [ ]:
x = th.tensor([1.0])
ptr = protocol.run(x)
ptr
In [ ]:
ptr.get()
Die Eingabe 1.0
durchlief alle drei Pläne und wurde dort jeweils um eins erhöht. Deshalb entspricht die Ausgabe einer 4.0
!
Selbstverständlich können Protokolle auch mit Pointern arbeiten.
In [ ]:
james = sy.VirtualWorker(hook, id="james")
In [ ]:
protocol.send(james)
In [ ]:
x = th.tensor([1.0]).send(james)
ptr = protocol.run(x)
ptr
Wie zu erkennen ist, ist das Ergebnis ein Pointer zu james
.
In [ ]:
ptr = ptr.get()
ptr
In [ ]:
ptr = ptr.get()
ptr
Dafür wir ein nicht verteiltes Protokoll erstellt und auf einem Helfer bereit gestellt.
In [ ]:
protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])
protocol.tag('my_protocol')
protocol.send(james)
In [ ]:
me = sy.hook.local_worker # get access to me as a local worker
Nun wird eine Suche nach dem Protokoll gestartet.
In [ ]:
responses = me.request_search(['my_protocol'], location=james)
responses
Zurückgegeben wurde ein Pointer auf das Protokoll.
In [ ]:
ptr_protocol = responses[0]
Wie gewohnt kann der Pointer genutzt werden um das Objekt zu holen:
In [ ]:
protocol_back = ptr_protocol.get()
protocol_back
Von hier wird genau wie in Teil 1. & 2. verfahren.
In [ ]:
protocol_back.deploy(alice, bob, charlie)
x = th.tensor([1.0])
ptr = protocol_back.run(x)
ptr.get()
Weitere Beispiele mit Protokollen und echten Szenarien sind in Vorbereitung, doch die Möglichkeiten eines solchen Objektes sollten nun schon erkennbar sein!
Der einfachste Weg, unserer Community zu helfen, besteht darin, die GitHub-Repos mit Sternen auszuzeichnen! Dies hilft, das Bewusstsein für die coolen Tools zu schärfen, die wir bauen.
Wir haben hilfreiche Tutorials erstellt, um ein Verständnis für Federated und Privacy-Preserving Learning zu entwickeln und zu zeigen wie wir die einzelnen Bausteine weiter entwickeln.
Der beste Weg, um über die neuesten Entwicklungen auf dem Laufenden zu bleiben, ist, sich unserer Community anzuschließen! Sie können dies tun, indem Sie das Formular unter http://slack.openmined.org ausfüllen.
Der beste Weg, um zu unserer Community beizutragen, besteht darin, Entwickler zu werden! Sie können jederzeit zur PySyft GitHub Issues-Seite gehen und nach "Projects" filtern. Dies zeigt Ihnen alle Top-Level-Tickets und gibt einen Überblick darüber, an welchen Projekten Sie teilnehmen können! Wenn Sie nicht an einem Projekt teilnehmen möchten, aber ein wenig programmieren möchten, können Sie auch nach weiteren "einmaligen" Miniprojekten suchen, indem Sie nach GitHub-Problemen suchen, die als "good first issue" gekennzeichnet sind.
Wenn Sie keine Zeit haben, zu unserer Codebase beizutragen, aber dennoch Unterstützung leisten möchten, können Sie auch Unterstützer unseres Open Collective werden. Alle Spenden fließen in unser Webhosting und andere Community-Ausgaben wie Hackathons und Meetups!
In [ ]: