<jupyter_start><jupyter_text>Partie 3: Outils avancés d'exécution à distanceDans la dernière section, nous avons formé un modèle de jouet en utilisant l'apprentissage fédéré. Nous l'avons fait en appelant .send () et .get () sur notre modèle, en l'envoyant à l'emplacement des données d'entraînement, en le mettant à jour, puis en le rapportant. Cependant, à la fin de l'exemple, nous avons réalisé que nous devions aller un peu plus loin pour protéger la vie privée des gens. A savoir, nous voulons faire la moyenne des gradients **avant** d'appeler .get (). De cette façon, nous ne verrons jamais le gradient exact de personne (protégeant ainsi mieux sa vie privée !!!)Mais pour ce faire, nous avons besoin de quelques pièces supplémentaires:- utiliser un pointeur pour envoyer un tenseur directement à un autre travailleurEt en plus, pendant que nous sommes ici, nous allons en apprendre davantage sur quelques opérations de tenseur plus avancées qui nous aideront à la fois avec cet exemple et quelques-unes à l'avenir!Auteurs:- <NAME> - Twitter: [@iamtrask] (https://twitter.com/iamtrask)<jupyter_code>import torch
import syft as sy
hook = sy.TorchHook(torch)<jupyter_output><empty_output><jupyter_text>Section 3.1 - Pointeurs vers pointeursComme vous le savez, les objets PointerTensor ressemblent à des tenseurs normaux. En fait, ils sont _tellement semblables à des tenseurs_ que nous pouvons même avoir des pointeurs **à** les pointeurs. Vérifiez-le!<jupyter_code>bob = sy.VirtualWorker(hook, id='bob')
alice = sy.VirtualWorker(hook, id='alice')
# c'est un tenseur local
x = torch.tensor([1,2,3,4])
x
# cela envoie le tenseur local à Bob
x_ptr = x.send(bob)

# c'est maintenant un pointeur
x_ptr
# maintenant nous pouvons ENVOYER LE POINTEUR à alice !!!
pointer_to_x_ptr = x_ptr.send(alice)

pointer_to_x_ptr<jupyter_output><empty_output><jupyter_text>Qu'est-il arrivé?Ainsi, dans l'exemple précédent, nous avons créé un tenseur appelé «x» et l'envoyer à Bob, créant un pointeur sur notre machine locale («x _ptr»).Ensuite, nous avons appelé `x_ ptr.send (alice)` qui **a envoyé le pointeur** à Alice.Remarque, cela n'a PAS déplacé les données! Au lieu de cela, il a déplacé le pointeur vers les données !!<jupyter_code># Comme vous pouvez le voir ci-dessus, Bob a toujours les données réelles 
# (les données sont toujours stockées dans un type LocalTensor).
bob._objects
# Alice, en revanche, a x_ptr !! (remarquez comment ça pointe sur bob)
alice._objects<jupyter_output><empty_output><jupyter_text><jupyter_code># et nous pouvons utiliser .get () pour récupérer x_ptr d'Alice

x_ptr = pointer_to_x_ptr.get()
x_ptr
#puis nous pouvons utiliser x_ptr pour récupérer x de Bob!

x = x_ptr.get()
x<jupyter_output><empty_output><jupyter_text>Arithmétique sur pointeur -> Pointeur -> Objet de donnéesEt tout comme avec les pointeurs normaux, nous pouvons effectuer des opérations PyTorch arbitraires sur ces tenseurs<jupyter_code>bob._objects
alice._objects
p2p2x = torch.tensor([1,2,3,4,5]).send(bob).send(alice)

y = p2p2x + p2p2x
bob._objects
alice._objects
y.get().get()
bob._objects
alice._objects
p2p2x.get().get()
bob._objects
alice._objects<jupyter_output><empty_output><jupyter_text>Section 3.2 - Opérations de la chaîne de pointeursDonc, dans la dernière section, chaque fois que nous avons appelé une opération .send () ou .get (), elle a appelé cette opération directement sur le tenseur de notre machine locale. Cependant, si vous avez une chaîne de pointeurs, vous souhaitez parfois appeler des opérations telles que .get () ou .send () sur le **dernier** pointeur de la chaîne (comme l'envoi de données directement à partir d'un travailleur à un autre). Pour ce faire, vous souhaitez utiliser des fonctions spécialement conçues pour cette opération de préservation de la confidentialité.Ces opérations sont:- `mon _pointer2pointer.move (un autre_ travailleur)`<jupyter_code># x est maintenant un pointeur vers les données qui vivent sur la machine de Bob
x = torch.tensor([1,2,3,4,5]).send(bob)
print('  bob:', bob._objects)
print('alice:',alice._objects)
x = x.move(alice)
print('  bob:', bob._objects)
print('alice:',alice._objects)
x<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08623984710941232, 'fraction_numerical': 0.006688963210702341, 'mean_word_length': 5.635499207606973, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 28, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '229028', 'license': 'Apache-2.0', 'n_tokens_mistral': 1483, 'n_tokens_neox': 1469, 'n_words': 522, 'path': 'examples/tutorials/translations/french/Part 03 - Advanced Remote Execution Tools.ipynb', 'repo_name': 'Metrix1010/PySyft', 'size': '4192'}