2017-06-16 16 views
7

में कस्टम हानि फ़ंक्शन मेरे पास तीन सरल प्रश्न हैं।PyTorch

  1. मेरा कस्टम लॉस फ़ंक्शन अलग-अलग नहीं होने पर क्या होगा? त्रुटि के माध्यम से pytorch होगा या कुछ और करेंगे?
  2. यदि मैं अपने कस्टम फ़ंक्शन में हानि चर घोषित करता हूं जो मॉडल के अंतिम नुकसान का प्रतिनिधित्व करेगा, तो क्या मुझे उस चर के लिए requires_grad = True रखना चाहिए? या इससे कोई फर्क नहीं पड़ता? अगर इससे कोई फर्क नहीं पड़ता, तो क्यों?
  3. मैंने देखा है कि लोग कभी-कभी एक अलग परत लिखते हैं और forward फ़ंक्शन में हानि की गणना करते हैं। कौन सा दृष्टिकोण बेहतर है, एक समारोह या परत लिखना? क्यूं कर?

मुझे अपने भ्रम को हल करने के लिए इन सवालों के लिए एक स्पष्ट और अच्छी व्याख्या की आवश्यकता है। कृपया मदद करे।

उत्तर

7

मुझे जाने दो।

  1. यह "गैर-व्यवहार्य" से आपका क्या मतलब है इस पर निर्भर करता है। पहली परिभाषा जो यहां समझ में आती है वह यह है कि PyTorch नहीं जानता कि ग्रेडियेंट की गणना कैसे करें। यदि आप फिर भी ग्रेडियेंट की गणना करने का प्रयास करते हैं, तो यह एक त्रुटि उठाएगा। दो संभावित परिदृश्य हैं:

    ए) आप एक कस्टम पायटोरच ऑपरेशन का उपयोग कर रहे हैं जिसके लिए ग्रेडियेंट लागू नहीं किए गए हैं, उदाहरण के लिए torch.svd()

    import torch 
    from torch.autograd import Function 
    from torch.autograd import Variable 
    
    A = Variable(torch.randn(10,10), requires_grad=True) 
    u, s, v = torch.svd(A) # raises TypeError 
    

    ख) आप अपनी खुद की कार्रवाई लागू की है, लेकिन backward() को परिभाषित नहीं किया: उस मामले में आप एक TypeError मिल जाएगा। इस मामले में, आप मिल जाएगा एक NotImplementedError:

    class my_function(Function): # forgot to define backward() 
    
        def forward(self, x): 
         return 2 * x 
    
    A = Variable(torch.randn(10,10)) 
    B = my_function()(A) 
    C = torch.sum(B) 
    C.backward() # will raise NotImplementedError 
    

    दूसरी परिभाषा में आता है कि भावना "गणितीय गैर विभेदक" है। स्पष्ट रूप से, एक ऑपरेशन जो गणितीय रूप से भिन्न नहीं है, उसके पास backward() विधि लागू या एक समझदार उप-ढाल नहीं होना चाहिए। उदाहरण torch.abs() जिसका backward() विधि 0 पर subgradient 0 रिटर्न के लिए पर विचार करें:

    A = Variable(torch.Tensor([-1,0,1]),requires_grad=True) 
    B = torch.abs(A) 
    B.backward(torch.Tensor([1,1,1])) 
    A.grad.data 
    

    इन मामलों में, आप PyTorch प्रलेखन के लिए सीधे देखें और सीधे संबंधित आपरेशन के backward() विधि की खुदाई करना चाहिए।

  2. इससे कोई फर्क नहीं पड़ता। requires_grad का उपयोग सबग्राफ के लिए ग्रेडियेंट्स की अनावश्यक गणना से बचने के लिए है। यदि किसी ऑपरेशन में एक इनपुट होता है जिसके लिए ढाल की आवश्यकता होती है, तो इसके आउटपुट को ढाल की भी आवश्यकता होगी। इसके विपरीत, केवल तभी जब सभी इनपुटों को ढाल की आवश्यकता नहीं होती है, तो आउटपुट को इसकी आवश्यकता नहीं होगी। पिछड़ा गणना कभी भी उपग्राफ में नहीं की जाती है, जहां सभी चरों को ग्रेडियेंट की आवश्यकता नहीं होती है।

    चूंकि, Variables (उदाहरण के लिए nn.Module() के उप-वर्ग के पैरामीटर के लिए) की संभावना है, तो आपके loss परिवर्तनीय को स्वचालित रूप से ग्रेडियेंट की आवश्यकता होगी। हालांकि, आपको ध्यान देना चाहिए कि वास्तव में कैसे requires_grad काम करता है (ऊपर देखें), आप अपने ग्राफ के पत्ते चर के लिए केवल requires_grad बदल सकते हैं।

  3. सभी कस्टम PyTorch नुकसान काम करता है, _Loss की उपवर्गों जो nn.Module का एक उपवर्ग है कर रहे हैं।See here. यदि आप इस सम्मेलन में रहना चाहते हैं, तो आपको अपने कस्टम हानि फ़ंक्शन को परिभाषित करते समय _Loss उपclass करना चाहिए। स्थिरता के अलावा, एक फायदा यह है कि आपका उप-वर्ग AssertionError बढ़ाएगा, यदि आपने अपने लक्ष्य चर को volatile या requires_grad = False के रूप में चिह्नित नहीं किया है। एक और फायदा यह है कि आप अपने नुकसान समारोह को nn.Sequential() में घोंसला कर सकते हैं, क्योंकि इसकी nn.Module मैं इन कारणों से इस दृष्टिकोण की अनुशंसा करता हूं।

+0

आपका स्वागत है। दुर्भाग्य से लिंक नहीं खोल सकता है। – mexmex

+0

मैंने वास्तव में सवाल हटा दिया क्योंकि मैंने इसे हल किया। लेकिन क्या आप इस प्रश्न में मेरी मदद कर सकते हैं - https://stackoverflow.com/questions/44580450/cuda-vs-dataparallel-why-the-difference? –

संबंधित मुद्दे