भाग 8 - योजनाओं का परिचय

प्रसंग

हम यहां एक ऐसी वस्तु का परिचय देते हैं जो औद्योगिक फेडरेटेड लर्निंग: द प्लान (plan) के पैमाने पर महत्वपूर्ण है। यह नाटकीय रूप से बैंडविड्थ उपयोग को कम करता है, अतुल्यकालिक योजनाओं की अनुमति देता है और दूरस्थ उपकरणों को अधिक स्वायत्तता देता है। योजना की मूल अवधारणा को पेपर Towards Federated Learning at Scale: System Design में पाया जा सकता है, लेकिन इसे PySyft लाइब्रेरी में हमारी आवश्यकताओं के अनुकूल बनाया गया है।

एक प्लान का उद्देश्य एक कार्य की तरह, torch संचालन के अनुक्रम को संग्रहीत करना है, लेकिन यह संचालन के इस अनुक्रम को दूरस्थ श्रमिकों को भेजने और इसके लिए एक संदर्भ रखने की अनुमति देता है। इस तरह, गणित के $n$ संचालन के इस क्रम को दूरस्थ रूप से गणना करने के लिए पॉइंटर्स के माध्यम से संदर्भित कुछ दूरस्थ इनपुट पर, गणितडी $n$ संदेश भेजने के बजाय अब आपको प्लान और बिंदुओं के संदर्भ के साथ एक संदेश भेजने की आवश्यकता है। आप अपने फ़ंक्शन के साथ टेंसर्स भी प्रदान कर सकते हैं (जिसे हम विस्तारित कार्यशीलता के लिए state tensors कहते हैं)। प्लान को या तो एक फ़ंक्शन की तरह देखा जा सकता है जिसे आप भेज सकते हैं, या एक वर्ग की तरह जिसे दूरस्थ रूप से भी भेजा और निष्पादित किया जा सकता है। इसलिए, उच्च स्तर के उपयोगकर्ताओं के लिए, योजना की धारणा गायब हो जाती है और इसे एक जादुई विशेषता द्वारा प्रतिस्थापित किया जाता है जो दूरस्थ श्रमिकों को मनमाने ढंग से कार्यों को भेजने की अनुमति देता है जिसमें अनुक्रमिक torch कार्य शामिल हैं।

ध्यान देने वाली एक बात यह है कि जिन कार्यों को आप प्लान में बदल सकते हैं उनका वर्ग वर्तमान में विशेष रूप से हुक torch के अनुक्रमों तक सीमित है। यह विशेष रूप से तार्किक संरचनाओं में शामिल है जैसे if, for और while कथन, भले ही हम जल्द ही काम करने के लिए काम कर रहे हों। पूरी तरह से सटीक होने के लिए, आप इनका उपयोग कर सकते हैं लेकिन आपके द्वारा लिए जाने वाले तार्किक पथ (उदाहरण के लिए पहले if को गलत और 5 छोरों को for में) अपने प्लान के पहले गणना में सभी के लिए रखा गया एक होगा अगले संगणना, जिसे हम अधिकांश मामलों में बचना चाहते हैं।

लेखक:

nbTranslate का उपयोग करके अनुवादित

संपादक:

आयात और मॉडल विनिर्देशों

पहले आधिकारिक आयात करते हैं।


In [ ]:
import torch
import torch.nn as nn
import torch.nn.functional as F

और PySyft के लिए विशिष्ट, एक महत्वपूर्ण नोट के साथ: स्थानीय कार्यकर्ता को ग्राहक नहीं होना चाहिए। <> गैर ग्राहक श्रमिक वस्तुओं को स्टोर कर सकते हैं और हमें प्लान चलाने के लिए इस क्षमता की आवश्यकता है। <>


In [ ]:
import syft as sy  # import the Pysyft library
hook = sy.TorchHook(torch)  # hook PyTorch ie add extra functionalities 

# IMPORTANT: Local worker should not be a client worker
hook.local_worker.is_client_worker = False


server = hook.local_worker

हम संदर्भ लेख में प्रदान की गई धारणाओं के अनुरूप होने के लिए, दूरस्थ श्रमिकों या devices, को परिभाषित करते हैं। हम उन्हें कुछ डेटा प्रदान करते हैं।


In [ ]:
x11 = torch.tensor([-1, 2.]).tag('input_data')
x12 = torch.tensor([1, -2.]).tag('input_data2')
x21 = torch.tensor([-1, 2.]).tag('input_data')
x22 = torch.tensor([1, -2.]).tag('input_data2')

device_1 = sy.VirtualWorker(hook, id="device_1", data=(x11, x12)) 
device_2 = sy.VirtualWorker(hook, id="device_2", data=(x21, x22))
devices = device_1, device_2

मूल उदाहरण

आइए एक फ़ंक्शन को परिभाषित करें जिसे हम एक योजना में बदलना चाहते हैं। ऐसा करने के लिए, यह फ़ंक्शन परिभाषा के ऊपर एक डेकोरेटर जोड़ने जैसा सरल है!


In [ ]:
@sy.func2plan()
def plan_double_abs(x):
    x = x + x
    x = torch.abs(x)
    return x

चलिए चेक करते हैं, हाँ अब हमारे पास एक प्लान है!


In [ ]:
plan_double_abs

किसी प्लान का उपयोग करने के लिए, आपको दो चीजों की आवश्यकता होती है: प्लान बनाना (अर्थात फ़ंक्शन में मौजूद संचालन के अनुक्रम को पंजीकृत करें) और इसे एक कार्यकर्ता / उपकरण को भेजना। सौभाग्य से आप यह बहुत आसानी से कर सकते हैं!

एक योजना का निर्माण

एक प्लान बनाने के लिए आपको बस कुछ डेटा पर कॉल करना होगा।

चलो पहले कुछ दूरस्थ डेटा का संदर्भ प्राप्त करते हैं: एक अनुरोध नेटवर्क पर भेजा जाता है और एक संदर्भ पॉइंटर लौटाया जाता है।


In [ ]:
pointer_to_data = device_1.search('input_data')[0]
pointer_to_data

यदि हम प्लान को बताते हैं इसे डिवाइस पर दूरस्थ रूप से निष्पादित किया जाना चाहिए location: device_1 ... हम एक त्रुटि प्राप्त करेंगे क्योंकि प्लान अभी तक नहीं बनाया गया था।


In [ ]:
plan_double_abs.is_built

In [ ]:
# Sending non-built Plan will fail
try:
    plan_double_abs.send(device_1)
except RuntimeError as error:
    print(error)

एक योजना बनाने के लिए आपको योजना पर build कॉल करने की आवश्यकता है और प्लान को निष्पादित करने के लिए आवश्यक तर्क पास करें (कुछ डेटा a.k.a)। जब एक प्लान का निर्माण किया जाता है तो सभी कमांड स्थानीय कार्यकर्ता द्वारा क्रमिक रूप से निष्पादित किए जाते हैं, और योजना द्वारा पकड़े जाते हैं और अपने actions विशेषता में संग्रहीत होते हैं!


In [ ]:
plan_double_abs.build(torch.tensor([1., -2.]))

In [ ]:
plan_double_abs.is_built

अगर हम प्लान को भेजने की कोशिश करते हैं तो यह काम करता है!


In [ ]:
# This cell is executed successfully
pointer_plan = plan_double_abs.send(device_1)
pointer_plan

तब तक टेंसर्स के साथ, हमें भेजे गए ऑब्जेक्ट को एक पॉइंटर मिलता है। यहाँ इसे बस एक 'PointerPlan' कहा जाता है।

याद रखने वाली एक महत्वपूर्ण बात यह है कि जब कोई प्लान का निर्माण किया जाता है, तो हम आईडी(एस) को आगे पूर्व निर्धारित करते हैं, जहां परिणाम(ओं) को संग्रहीत किया जाना चाहिए। यह आदेशों को अतुल्यकालिक रूप से भेजने की अनुमति देगा, पहले से ही एक आभासी परिणाम के संदर्भ में और दूरस्थ परिणाम की गणना किए बिना स्थानीय गणना जारी रखने के लिए। एक प्रमुख अनुप्रयोग है जब आपको device_1 पर एक बैच की गणना की आवश्यकता होती है और device_2 पर दूसरे बैच की गणना शुरू करने के लिए इस गणना के समाप्त होने का इंतजार नहीं करना चाहते।

एक योजना दूरस्थ रूप से चलाना

अब हम प्‍वाइंटर को प्‍लान से कुछ डेटा के साथ प्‍लान को कॉल करके रिमोट को रन कर सकते हैं। यह इस योजना को दूरस्थ रूप से चलाने के लिए एक आदेश जारी करता है, ताकि योजना के आउटपुट का पूर्वनिर्धारित स्थान अब परिणाम को शामिल करें (याद रखें कि हम गणना से पहले परिणाम के पूर्व-निर्धारित स्थान को याद करते हैं)। इसके लिए एकल संचार दौर की भी आवश्यकता होती है।

परिणाम बस एक सूचक है, जैसे जब आप एक सामान्य हुक torch फ़ंक्शन कहते हैं!


In [ ]:
pointer_to_result = pointer_plan(pointer_to_data)
print(pointer_to_result)

और आप बस मान वापस पूछ सकते हैं।


In [ ]:
pointer_to_result.get()

एक ठोस उदाहरण की ओर

लेकिन हम जो करना चाहते हैं, वह प्‍लान को गहरी और संघबद्ध शिक्षा पर लागू करना है, है ना? तो चलो थोड़ा और अधिक जटिल उदाहरण देखें, neural नेटवर्क का उपयोग करते हुए जैसा कि आप उन्हें उपयोग करने के लिए तैयार हो सकते हैं। ध्यान दें कि अब हम एक वर्ग को एक योजना में बदल रहे हैं। ऐसा करने के लिए, हम अपनी कक्षा को sy.Plan (nn.Module से विरासत में लेने के बजाय) से वारिस करते हैं।


In [ ]:
class Net(sy.Plan):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(2, 3)
        self.fc2 = nn.Linear(3, 2)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x, dim=0)

In [ ]:
net = Net()

In [ ]:
net

आइए कुछ मॉक डेटा का उपयोग करके प्‍लान का निर्माण करें।


In [ ]:
net.build(torch.tensor([1., 2.]))

अब हम एक दूरस्थ कार्यकर्ता को प्‍लान भेजते हैं


In [ ]:
pointer_to_net = net.send(device_1)
pointer_to_net

चलो कुछ दूरस्थ डेटा पुनर्प्राप्त करते हैं


In [ ]:
pointer_to_data = device_1.search('input_data')[0]

फिर, वाक्यविन्यास सामान्य दूरस्थ अनुक्रमिक निष्पादन की तरह है, अर्थात, स्थानीय निष्पादन की तरह। लेकिन क्लासिक रिमोट निष्पादन की तुलना में, प्रत्येक निष्पादन के लिए एक एकल संचार दौर है।


In [ ]:
pointer_to_result = pointer_to_net(pointer_to_data)
pointer_to_result

और हम हमेशा की तरह परिणाम प्राप्त करते हैं!


In [ ]:
pointer_to_result.get()

Et voilà! हमने देखा है कि स्थानीय कार्यकर्ता (या सर्वर) और दूरस्थ उपकरणों के बीच संचार को नाटकीय रूप से कैसे कम करें!

कार्यकर्ताओं के बीच स्विच करें

एक प्रमुख विशेषता जो हम चाहते हैं कि कई श्रमिकों के लिए एक ही प्‍लान का उपयोग किया जाए, हम जिस डेटा पर विचार कर रहे हैं, उसके आधार पर हम बदलेंगे। विशेष रूप से, हम हर बार जब हम कार्यकर्ता बदलते हैं तो प्‍लान का पुनर्निर्माण नहीं करना चाहते हैं। आइए देखें कि हम अपने छोटे नेटवर्क के साथ पिछले उदाहरण का उपयोग करके यह कैसे करते हैं।


In [ ]:
class Net(sy.Plan):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(2, 3)
        self.fc2 = nn.Linear(3, 2)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x, dim=0)

In [ ]:
net = Net()

# Build plan
net.build(torch.tensor([1., 2.]))

यहां मुख्य कदम हैं जिन्हें हमने निष्पादित किया है


In [ ]:
pointer_to_net_1 = net.send(device_1)
pointer_to_data = device_1.search('input_data')[0]
pointer_to_result = pointer_to_net_1(pointer_to_data)
pointer_to_result.get()

और वास्तव में आप एक ही प्‍लान से अन्य पॉइंटरप्लान(PointerPlans) का निर्माण कर सकते हैं, इसलिए सिंटैक्स किसी अन्य डिवाइस की प्‍लान को दूरस्थ रूप से चलाने के लिए समान है


In [ ]:
pointer_to_net_2 = net.send(device_2)
pointer_to_data = device_2.search('input_data')[0]
pointer_to_result = pointer_to_net_2(pointer_to_data)
pointer_to_result.get()

नोट: वर्तमान में, प्‍लान वर्गों के साथ, आप केवल एक ही विधि का उपयोग कर सकते हैं और आपको इसे "forward" नाम देना होगा।

प्‍लान फ़ंक्शंस का स्वचालित रूप से निर्माण

फ़ंक्शंस के लिए (@ sy.func2plan) हम प्‍लान को स्पष्ट रूप से build कहने के बग़ैर स्वचालित रूप से बना सकते हैं, वास्तव में प्‍लान के निर्माण के क्षण में पहले से ही निर्मित है।

इस कार्यक्षमता को प्राप्त करने के लिए केवल एक प्‍लान बनाते समय आपको बदलने की आवश्यकता होती है, सजावट के लिए एक तर्क स्थापित कर रहा है जिसे args_shape कहा जाता है, जिसमें प्रत्येक तर्क के आकार वाली एक सूची होनी चाहिए।


In [ ]:
@sy.func2plan(args_shape=[(-1, 1)])
def plan_double_abs(x):
    x = x + x
    x = torch.abs(x)
    return x

plan_double_abs.is_built

args_shape पैरामीटर का उपयोग आंतरिक रूप से दिए गए आकार के साथ नकली टेंसर बनाने के लिए किया जाता है जो प्‍लान बनाने के लिए उपयोग किए जाते हैं।


In [ ]:
@sy.func2plan(args_shape=[(1, 2), (-1, 2)])
def plan_sum_abs(x, y):
    s = x + y
    return torch.abs(s)

plan_sum_abs.is_built

आप फ़ंक्शन को state elements भी प्रदान कर सकते हैं!


In [ ]:
@sy.func2plan(args_shape=[(1,)], state=(torch.tensor([1]), ))
def plan_abs(x, state):
    bias, = state.read()
    x = x.abs()
    return x + bias

In [ ]:
pointer_plan = plan_abs.send(device_1)
x_ptr = torch.tensor([-1, 0]).send(device_1)
p = pointer_plan(x_ptr)
p.get()

इसके बारे में अधिक जानने के लिए, आप खोज सकते हैं कि हम ट्यूटोरियल भाग 8 बीआईएस में प्रोटोकॉल के साथ योजनाओं का उपयोग कैसे करते हैं!

GitHub पर स्टार PySyft

हमारे समुदाय की मदद करने का सबसे आसान तरीका सिर्फ रिपॉजिटरी को अभिनीत करना है! यह हमारे द्वारा बनाए जा रहे कूल टूल्स के बारे में जागरूकता बढ़ाने में मदद करता है।

GitHub पर हमारे ट्यूटोरियल चुनना!

हमने फेडरेटेड और प्राइवेसी-प्रिजर्विंग लर्निंग और उसकी संरचना की बेहतर समझ प्राप्त करने के लिए वास्तव में अच्छा ट्यूटोरियल बनाया है।

हमारे Slack में शामिल हों!

नवीनतम प्रगति पर अद्यतित रहने का सबसे अच्छा तरीका हमारे समुदाय में शामिल होना है!

एक कोड परियोजना में शामिल हों!

हमारे समुदाय में योगदान करने का सबसे अच्छा तरीका एक कोड योगदानकर्ता बनना है! यदि आप "one off" मिनी-प्रोजेक्ट्स शुरू करना चाहते हैं, तो आप PySyft GitHub जारी करने वाले पृष्ठ पर जा सकते हैं और Good First Issue के रूप में चिह्नित मुद्दों की खोज कर सकते हैं।

दान करना

यदि आपके पास हमारे कोडबेस में योगदान करने का समय नहीं है, लेकिन फिर भी समर्थन उधार देना चाहते हैं, तो आप हमारे ओपन कलेक्टिव में भी एक बैकर बन सकते हैं। सभी दान हमारी वेब होस्टिंग और अन्य सामुदायिक खर्च जैसे कि हैकाथॉन और मीटअप की ओर जाते हैं!


In [ ]: