PyTorch में वज़न कैसे शुरू करें?


जवाबों:


150

एकल परत

किसी एक परत के भार को आरंभ करने के लिए, एक फ़ंक्शन का उपयोग करें torch.nn.init। उदाहरण के लिए:

conv1 = torch.nn.Conv2d(...)
torch.nn.init.xavier_uniform(conv1.weight)

वैकल्पिक रूप से, आप conv1.weight.data(जो एक है torch.Tensor) को लिखकर मापदंडों को संशोधित कर सकते हैं । उदाहरण:

conv1.weight.data.fill_(0.01)

एक ही पक्षपात के लिए लागू होता है:

conv1.bias.data.fill_(0.01)

nn.Sequential या प्रथा nn.Module

एक इनिशियलाइज़ेशन फंक्शन पास करें torch.nn.Module.apply। यह पूरी तरह से nn.Moduleपुनरावर्ती में भार को आरंभ करेगा ।

लागू ( fn ): लागू होता है fnहर submodule को रिकर्सिवली (के रूप में द्वारा लौटाए गए .children()स्वयं के रूप में) के रूप में अच्छी तरह से। विशिष्ट उपयोग में एक मॉडल के मापदंडों को शुरू करना शामिल है (देखें टॉर्च-एनएन-इनिट भी)।

उदाहरण:

def init_weights(m):
    if type(m) == nn.Linear:
        torch.nn.init.xavier_uniform(m.weight)
        m.bias.data.fill_(0.01)

net = nn.Sequential(nn.Linear(2, 2), nn.Linear(2, 2))
net.apply(init_weights)

6
मुझे reset_parametersकई मॉड्यूल के स्रोत कोड में एक विधि मिली । क्या मुझे वजन आरंभीकरण के लिए विधि को ओवरराइड करना चाहिए?
यांग बो

1
क्या होगा अगर मैं कुछ माध्य और एसटीडी के साथ एक सामान्य वितरण का उपयोग करना चाहता हूं?
चार्ली पार्कर

12
यदि मैं एक निर्दिष्ट नहीं करता हूं तो डिफ़ॉल्ट आरंभीकरण क्या है?
xjcl

कम से कम रैखिक परतों के लिए डिफ़ॉल्ट आरंभीकरण उसके हैं: pytorch.org/docs/stable/nn.html#linear-layers
arash jvan

40

हम समान तंत्रिका-नेटवर्क (एनएन) वास्तुकला का उपयोग करके वजन-आरंभ के विभिन्न मोड की तुलना करते हैं।

सभी जीरो या ओन्स

यदि आप ओकाम के रेजर के सिद्धांत का पालन करते हैं , तो आप सोच सकते हैं कि सभी भार को 0 या 1 पर सेट करना सबसे अच्छा समाधान होगा। यह मामला नहीं है।

प्रत्येक भार के साथ, प्रत्येक परत पर सभी न्यूरॉन्स समान उत्पादन कर रहे हैं। इससे यह तय करना कठिन हो जाता है कि कौन सा वजन समायोजित करना है।

    # initialize two NN's with 0 and 1 constant weights
    model_0 = Net(constant_weight=0)
    model_1 = Net(constant_weight=1)
  • 2 युगों के बाद:

वजन घटाने के साथ प्रशिक्षण नुकसान की साजिश निरंतर

Validation Accuracy
9.625% -- All Zeros
10.050% -- All Ones
Training Loss
2.304  -- All Zeros
1552.281  -- All Ones

यूनिफॉर्म इनिशियलाइज़ेशन

एक समान वितरण में संख्याओं के समूह से किसी भी संख्या को चुनने की समान संभावना होती है।

आइए देखें कि एक समान वजन के आरंभीकरण का उपयोग करके तंत्रिका नेटवर्क कितनी अच्छी तरह से ट्रेन करता है, कहां low=0.0और high=1.0

नीचे, हम नेटवर्क के भार को आरंभीकृत करने के लिए (नेट क्लास कोड के अलावा) एक और तरीका देखेंगे। मॉडल परिभाषा के बाहर वजन को परिभाषित करने के लिए, हम कर सकते हैं:

  1. एक फ़ंक्शन को परिभाषित करें जो नेटवर्क लेयर के प्रकार द्वारा वज़न असाइन करता है, फिर
  2. उन वज़न को एक प्रारंभिक मॉडल का उपयोग करके model.apply(fn)लागू करें, जो प्रत्येक मॉडल परत पर एक फ़ंक्शन लागू करता है।
    # takes in a module and applies the specified weight initialization
    def weights_init_uniform(m):
        classname = m.__class__.__name__
        # for every Linear layer in a model..
        if classname.find('Linear') != -1:
            # apply a uniform distribution to the weights and a bias=0
            m.weight.data.uniform_(0.0, 1.0)
            m.bias.data.fill_(0)

    model_uniform = Net()
    model_uniform.apply(weights_init_uniform)
  • 2 युगों के बाद:

यहां छवि विवरण दर्ज करें

Validation Accuracy
36.667% -- Uniform Weights
Training Loss
3.208  -- Uniform Weights

वजन निर्धारित करने के लिए सामान्य नियम

एक तंत्रिका नेटवर्क में वजन सेट करने के लिए सामान्य नियम उन्हें बहुत छोटा होने के बिना शून्य के करीब होने के लिए सेट करना है।

अच्छा अभ्यास [-y, y] जहां y=1/sqrt(n)
(n किसी दिए गए न्यूरॉन को इनपुट की संख्या है) की सीमा में अपना वजन शुरू करना है ।

    # takes in a module and applies the specified weight initialization
    def weights_init_uniform_rule(m):
        classname = m.__class__.__name__
        # for every Linear layer in a model..
        if classname.find('Linear') != -1:
            # get the number of the inputs
            n = m.in_features
            y = 1.0/np.sqrt(n)
            m.weight.data.uniform_(-y, y)
            m.bias.data.fill_(0)

    # create a new model with these weights
    model_rule = Net()
    model_rule.apply(weights_init_uniform_rule)

नीचे हम एनएन के प्रदर्शन की तुलना करते हैं, एक समान वितरण के साथ आरंभिक वजन [-0.5,0.5) बनाम जिसका वजन प्रारंभिक नियम नियम का उपयोग करके शुरू किया गया है

  • 2 युगों के बाद:

भार बनाम वर्दी के प्रारंभिक नियम के प्रदर्शन को प्रदर्शित करने की साजिश

Validation Accuracy
75.817% -- Centered Weights [-0.5, 0.5)
85.208% -- General Rule [-y, y)
Training Loss
0.705  -- Centered Weights [-0.5, 0.5)
0.469  -- General Rule [-y, y)

वजन को शुरू करने के लिए सामान्य वितरण

सामान्य वितरण में 0 का मतलब और मानक विचलन होना चाहिए y=1/sqrt(n), जहां n एनएन में इनपुट की संख्या है

    ## takes in a module and applies the specified weight initialization
    def weights_init_normal(m):
        '''Takes in a module and initializes all linear layers with weight
           values taken from a normal distribution.'''

        classname = m.__class__.__name__
        # for every Linear layer in a model
        if classname.find('Linear') != -1:
            y = m.in_features
        # m.weight.data shoud be taken from a normal distribution
            m.weight.data.normal_(0.0,1/np.sqrt(y))
        # m.bias.data should be 0
            m.bias.data.fill_(0)

नीचे हम समान-वितरण का उपयोग करके दो एनएन एक के प्रदर्शन को दिखाते हैं और दूसरा सामान्य-वितरण का उपयोग करते हुए

  • 2 युगों के बाद:

सामान्य वितरण बनाम समान वितरण का उपयोग करके वजन आरंभीकरण का प्रदर्शन

Validation Accuracy
85.775% -- Uniform Rule [-y, y)
84.717% -- Normal Distribution
Training Loss
0.329  -- Uniform Rule [-y, y)
0.443  -- Normal Distribution

7
आप किस कार्य के लिए अनुकूलन करते हैं? और सभी शून्य समाधान शून्य नुकसान कैसे दे सकते हैं?
11

19

परतों को शुरू करने के लिए आपको आमतौर पर कुछ भी करने की आवश्यकता नहीं होती है।

PyTorch इसे आपके लिए करेगा। यदि आप सोचते हैं, तो इसका बहुत अर्थ है। हमें लेयर को इनिशियलाइज़ क्यों करना चाहिए, जब PyTorch लेटेस्ट ट्रेंड को फॉलो कर सकता है।

उदाहरण के लिए रेखीय परत की जाँच करें ।

में __init__विधि यह फोन करेगा Kaiming वह init समारोह।

    def reset_parameters(self):
        init.kaiming_uniform_(self.weight, a=math.sqrt(3))
        if self.bias is not None:
            fan_in, _ = init._calculate_fan_in_and_fan_out(self.weight)
            bound = 1 / math.sqrt(fan_in)
            init.uniform_(self.bias, -bound, bound)

अन्य परतों के प्रकारों के लिए भी ऐसा ही है। उदाहरण conv2dके लिए यहाँ जाँच करें

ध्यान दें: उचित आरंभ का लाभ तेज प्रशिक्षण गति है। यदि आपकी समस्या विशेष आरंभ के योग्य है, तो आप इसे बाद में कर सकते हैं।


डिफ़ॉल्ट आरंभीकरण हमेशा सर्वश्रेष्ठ परिणाम नहीं देता है, हालांकि। मैंने हाल ही में Pytorch में VGG16 आर्किटेक्चर को लागू किया और इसे CIFAR-10 डेटासेट पर प्रशिक्षित किया, और मैंने पाया कि xavier_uniformडिफ़ॉल्ट आरंभीकरण का उपयोग करने के बजाय वेट के लिए आरंभीकरण पर स्विच किया जा रहा है (0 के साथ शुरुआती गैसों के बजाय), मेरी सत्यापन सटीकता 30 के बाद। आरएमएसप्रॉप की अवधि 82% से बढ़कर 86% हो गई। Pytorch के अंतर्निहित VGG16 मॉडल (पूर्व-प्रशिक्षित नहीं) का उपयोग करते समय मुझे 86% सत्यापन सटीकता भी मिली, इसलिए मुझे लगता है कि मैंने इसे सही तरीके से लागू किया। (मैंने 0.00001 की सीखने की दर का इस्तेमाल किया।)
छोटो

इसका कारण यह है कि उन्होंने VGG16 में बैच नॉर्म्स का उपयोग नहीं किया है। यह सही है कि उचित इनिशियलाइज़ेशन मायने रखता है और यह कि कुछ आर्किटेक्चर के लिए आप ध्यान देते हैं। उदाहरण के लिए, यदि आप उपयोग करते हैं (nn.conv2d (), ReLU () अनुक्रम) तो आप काइमिंग को हटा देंगे। PyTorch conv2d के बाद आपके सक्रियण फ़ंक्शन की भविष्यवाणी नहीं कर सकता है। यह समझ में आता है कि यदि आप ईग्नेलेवल्स का मूल्यांकन करते हैं, लेकिन आमतौर पर आपको बैच नॉर्म्स का उपयोग करने के लिए ज्यादा कुछ नहीं करना पड़ता है, तो वे आपके लिए आउटपुट को सामान्य कर देंगे। यदि आप SotaBench प्रतियोगिता को जीतने की योजना बनाते हैं तो यह मायने रखता है।
वेश्या

7
    import torch.nn as nn        

    # a simple network
    rand_net = nn.Sequential(nn.Linear(in_features, h_size),
                             nn.BatchNorm1d(h_size),
                             nn.ReLU(),
                             nn.Linear(h_size, h_size),
                             nn.BatchNorm1d(h_size),
                             nn.ReLU(),
                             nn.Linear(h_size, 1),
                             nn.ReLU())

    # initialization function, first checks the module type,
    # then applies the desired changes to the weights
    def init_normal(m):
        if type(m) == nn.Linear:
            nn.init.uniform_(m.weight)

    # use the modules apply function to recursively apply the initialization
    rand_net.apply(init_normal)

5

इतनी देर होने के लिए क्षमा करें, मुझे आशा है कि मेरा उत्तर मदद करेगा।

एक normal distributionउपयोग के साथ वजन को आरंभ करने के लिए:

torch.nn.init.normal_(tensor, mean=0, std=1)

या constant distributionलिखने का उपयोग करने के लिए :

torch.nn.init.constant_(tensor, value)

या एक का उपयोग करने के लिए uniform distribution:

torch.nn.init.uniform_(tensor, a=0, b=1) # a: lower_bound, b: upper_bound

आप यहाँ दसियों को इनिशियलाइज़ करने के लिए अन्य तरीकों की जाँच कर सकते हैं


2

यदि आप कुछ अतिरिक्त लचीलापन चाहते हैं, तो आप मैन्युअल रूप से वजन भी निर्धारित कर सकते हैं

कहो कि आपके पास सभी का इनपुट है:

import torch
import torch.nn as nn

input = torch.ones((8, 8))
print(input)
tensor([[1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1.]])

और आप बिना किसी पूर्वाग्रह के साथ घनी परत बनाना चाहते हैं (ताकि हम कल्पना कर सकें):

d = nn.Linear(8, 8, bias=False)

सभी वज़न को 0.5 पर सेट करें (या कुछ और):

d.weight.data = torch.full((8, 8), 0.5)
print(d.weight.data)

वजन:

Out[14]: 
tensor([[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
        [0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
        [0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
        [0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
        [0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
        [0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
        [0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
        [0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000]])

आपके सभी वजन अब 0.5 हैं। डेटा पास करें:

d(input)
Out[13]: 
tensor([[4., 4., 4., 4., 4., 4., 4., 4.],
        [4., 4., 4., 4., 4., 4., 4., 4.],
        [4., 4., 4., 4., 4., 4., 4., 4.],
        [4., 4., 4., 4., 4., 4., 4., 4.],
        [4., 4., 4., 4., 4., 4., 4., 4.],
        [4., 4., 4., 4., 4., 4., 4., 4.],
        [4., 4., 4., 4., 4., 4., 4., 4.],
        [4., 4., 4., 4., 4., 4., 4., 4.]], grad_fn=<MmBackward>)

याद रखें कि प्रत्येक न्यूरॉन को 8 इनपुट प्राप्त होते हैं, जिनमें से सभी का वजन 0.5 और 1 (और कोई पूर्वाग्रह) का मूल्य नहीं होता है, इसलिए यह प्रत्येक के लिए 4 तक बैठता है।


1

मापदंडों पर Iterate

यदि आप applyउदाहरण के लिए उपयोग नहीं कर सकते हैं यदि मॉडल Sequentialसीधे लागू नहीं होता है:

सभी के लिए समान

# see UNet at https://github.com/milesial/Pytorch-UNet/tree/master/unet


def init_all(model, init_func, *params, **kwargs):
    for p in model.parameters():
        init_func(p, *params, **kwargs)

model = UNet(3, 10)
init_all(model, torch.nn.init.normal_, mean=0., std=1) 
# or
init_all(model, torch.nn.init.constant_, 1.) 

आकार पर निर्भर करता है

def init_all(model, init_funcs):
    for p in model.parameters():
        init_func = init_funcs.get(len(p.shape), init_funcs["default"])
        init_func(p)

model = UNet(3, 10)
init_funcs = {
    1: lambda x: torch.nn.init.normal_(x, mean=0., std=1.), # can be bias
    2: lambda x: torch.nn.init.xavier_normal_(x, gain=1.), # can be weight
    3: lambda x: torch.nn.init.xavier_uniform_(x, gain=1.), # can be conv1D filter
    4: lambda x: torch.nn.init.xavier_uniform_(x, gain=1.), # can be conv2D filter
    "default": lambda x: torch.nn.init.constant(x, 1.), # everything else
}

init_all(model, init_funcs)

आप यह torch.nn.init.constant_(x, len(x.shape))जाँचने की कोशिश कर सकते हैं कि वे उचित रूप से आरंभिक हैं:

init_funcs = {
    "default": lambda x: torch.nn.init.constant_(x, len(x.shape))
}

0

यदि आप एक चेतावनी चेतावनी (@ Fábio पेरेस) देखें ...

def init_weights(m):
    if type(m) == nn.Linear:
        torch.nn.init.xavier_uniform_(m.weight)
        m.bias.data.fill_(0.01)

net = nn.Sequential(nn.Linear(2, 2), nn.Linear(2, 2))
net.apply(init_weights)

1
आप फैबियो पेरेज़ के उत्तरों को साफ रखने के लिए वहां पर टिप्पणी कर सकते हैं ।
फणी ऋत्विज

0

Cuz मुझे अब तक पर्याप्त प्रतिष्ठा नहीं मिली है, मैं एक टिप्पणी नहीं जोड़ सकता

इस सवाल का जवाब द्वारा पोस्ट की गई prosti में 13:16 पर जून 26 '19

    def reset_parameters(self):
        init.kaiming_uniform_(self.weight, a=math.sqrt(3))
        if self.bias is not None:
            fan_in, _ = init._calculate_fan_in_and_fan_out(self.weight)
            bound = 1 / math.sqrt(fan_in)
            init.uniform_(self.bias, -bound, bound)

लेकिन मैं कहना चाहता हूं कि वास्तव में हम कैमिंग ही के पेपर में कुछ धारणाएं जानते हैं , डेलिंग डीप इन रेक्टिफायर्स: इमेजिनेशन क्लासिफिकेशन पर मानव-स्तरीय प्रदर्शन को दरकिनार करना , उचित नहीं है, हालांकि यह ऐसा लगता है कि जानबूझकर डिजाइन किया गया प्रैक्टिस मेथड प्रचलन में है। ।

उदाहरण के लिए, पिछड़े प्रसार मामले के अंतर्गत , वे मानते हैं कि $ w_l $ और $ \ डेल्टा y_l $ एक-दूसरे से स्वतंत्र हैं। लेकिन जैसा कि हम सभी जानते हैं, एक उदाहरण के रूप में स्कोर मैप $ \ डेल्टा y ^ L_i $ लेते हैं, यह अक्सर $ y_i-softmax (y ^ L_i) = y_i-softmax (w ^ L_ix-L_i) $ होता है यदि हम एक ठेठ का उपयोग करते हैं क्रॉस एन्ट्रापी लॉस फ़ंक्शन का उद्देश्य।

इसलिए मुझे लगता है कि असली अंतर्निहित कारण यह है कि प्रारंभ में काम करता है अच्छी तरह से खुला रहता है। Cuz सभी ने गहन शिक्षण प्रशिक्षण को बढ़ावा देने के लिए अपनी शक्ति देखी है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.