পাইটর্চে ওজন কীভাবে শুরু করবেন?


উত্তর:


160

একক স্তর

একটি একক স্তরের ওজন সূচনা করতে, থেকে একটি ফাংশন ব্যবহার করুন 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 করতে যাও recursively (যেমন দ্বারা ফিরে .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অনেকগুলি মডিউলগুলির উত্স কোডে একটি পদ্ধতি পেয়েছি । ওজন প্রারম্ভিককরণের জন্য আমার কি পদ্ধতিটি ওভাররাইড করা উচিত?
ইয়াং বো

4
আমি যদি কিছু গড় এবং এসটিডি সহ একটি সাধারণ বিতরণ ব্যবহার করতে চাই তবে কী হবে?
চার্লি পার্কার 21

12
আমি যদি একটি নির্দিষ্ট না করি তবে ডিফল্ট সূচনাটি কী?
xjcl 10'19

অন্তত রৈখিক স্তরগুলির জন্য ডিফল্ট আরম্ভের তার আছেন: pytorch.org/docs/stable/nn.html#linear-layers
আরাশ যবন

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 যুগের পরে:

ধ্রুবক থেকে ওজন সূচনা সহ প্রশিক্ষণ হ্রাসের প্লট of

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)
(এন প্রদত্ত নিউরনের ইনপুটগুলির সংখ্যা)।

    # 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), যেখানে এন এন-এ ইনপুটগুলির সংখ্যা

    ## 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
আপনি কোন কাজটির জন্য অনুকূলিত হন? এবং সমস্ত শূন্য সমাধান কীভাবে শূন্য হ্রাস দিতে পারে?
ছাড়ুন

19

স্তরগুলি আরম্ভ করার জন্য আপনার সাধারণত কিছু করার প্রয়োজন হয় না।

পাইটর্চ এটি আপনার জন্য করবে। যদি আপনি এটি সম্পর্কে ভাবেন, এটি অনেক জ্ঞান আছে। আমাদের স্তরগুলি কেন শুরু করা উচিত, যখন পাইটর্চ এটি করতে পারে সর্বশেষ প্রবণতাগুলি অনুসরণ করে।

উদাহরণস্বরূপ লিনিয়ার স্তরটি পরীক্ষা করুন

__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উদাহরণস্বরূপ পরীক্ষা এখানে

দ্রষ্টব্য: সঠিক আরম্ভের লাভটি দ্রুত প্রশিক্ষণের গতি। যদি আপনার সমস্যাটি বিশেষ সূচনার দাবি রাখে তবে আপনি এটি আফটারওয়ার্ড করতে পারেন।


যদিও ডিফল্ট সূচনা সর্বদা সেরা ফলাফল দেয় না। আমি সম্প্রতি পাইটোর্কে ভিজিজি 16 আর্কিটেকচার বাস্তবায়ন করেছি এবং এটি সিআইএফএআর -10 ডেটাসেটে প্রশিক্ষণ দিয়েছি এবং আমি দেখতে পেয়েছি যে xavier_uniformডিফল্ট আরম্ভকরণের পরিবর্তে ওজনগুলির জন্য (বায়াসগুলি প্রাথমিকভাবে 0-এ শুরু করা হয়েছে) পরিবর্তনের পরিবর্তে 30 এর পরে আমার বৈধতার যথার্থতা রয়েছে আরএমএসপ্রপের পর্বগুলি 82% থেকে 86% এ বৃদ্ধি পেয়েছে। পাইটর্চের অন্তর্নির্মিত ভিজিজি 16 মডেলটি (প্রাক প্রশিক্ষণপ্রাপ্ত নয়) ব্যবহার করার সময় আমি 86% বৈধতার যথার্থতা পেয়েছি, তাই আমি মনে করি আমি এটি সঠিকভাবে প্রয়োগ করেছি। (আমি 0.00001 এর শিক্ষার হার ব্যবহার করেছি))
ছোট্ট

এর কারণ, তারা ভিজিজি 16 এ ব্যাচের নর্ম ব্যবহার করেনি। এটি সত্য যে সঠিক সূচনাটি গুরুত্বপূর্ণ এবং কিছু আর্কিটেকচারের জন্য আপনি মনোযোগ দিন। উদাহরণস্বরূপ, আপনি যদি (nn.conv2d (), আরএলইউ () অনুক্রম) ব্যবহার করেন তবে আপনি কাইমিং তিনি ইনিশিয়ালাইজেশন শুরু করবেন যা আপনার কনফর্ম স্তরটি রিলু করার জন্য তৈরি করা হয়েছে। পাই টর্চ কনফি 2 এর পরে আপনার অ্যাক্টিভেশন ফাংশনটির পূর্বাভাস দিতে পারে না। আপনি যদি eignevalues ​​মূল্যায়ন করেন তবে এটি বোধগম্য হয় তবে সাধারণত আপনি যদি ব্যাচ নর্ম ব্যবহার করেন তবে আপনাকে বেশি কিছু করতে হবে না, তারা আপনার ফলাফলগুলি স্বাভাবিক করবে। আপনি যদি সোটাবেঞ্চ প্রতিযোগিতায় জিততে চান তবে এটি গুরুত্বপূর্ণ।
prosti থেকে

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

আপনি এখানে টেনারগুলি আরম্ভ করার জন্য অন্যান্য পদ্ধতিগুলি পরীক্ষা করতে পারেন


3

আপনি যদি কিছু অতিরিক্ত নমনীয়তা চান, আপনি নিজেও ওজন সেট করতে পারেন

বলুন আপনার কাছে সকলের ইনপুট রয়েছে:

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

পরামিতি ওভার নিখরচায়

যদি 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

যদি আপনি অবমূল্যায়নের সতর্কতা (@ ফ্যাবিও পেরেজ) দেখেন ...

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)

4
উত্তরগুলি পরিষ্কার রাখার জন্য আপনি সেখানে ফ্যাবিও পেরেজের মন্তব্যে মন্তব্য করতে পারেন ।
ফানি ithত্বভিজ

0

কুউজ আমি এখনও পর্যন্ত যথেষ্ট খ্যাতি পাই নি, আমি এর অধীনে কোনও মন্তব্য যুক্ত করতে পারি না

উত্তর পোস্ট করেছে 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 each একে অপরের থেকে স্বতন্ত্র। তবে যেমনটি আমরা সকলেই জানি, স্কোর মানচিত্রটিকে $ \ ডেল্টা ওয়াই ^ এল_আই take উদাহরণ হিসাবে ধরুন, এটি প্রায়শই $ y_i-softmax (y ^ L_i) = y_i-softmax (w ^ L_ix ^ L_i) $ যদি আমরা একটি সাধারণ ব্যবহার করি ক্রস এনট্রপি ক্ষতি ফাংশন উদ্দেশ্য।

সুতরাং আমি মনে করি যে কেন তিনি ইনিশিয়ালাইজেশন ভালভাবে কাজ করেন তার প্রকৃত অন্তর্নিহিত কারণটি অবমুক্ত করা যায়। কিউজ প্রত্যেকে গভীর শিক্ষার প্রশিক্ষণ বৃদ্ধিতে এর শক্তি প্রত্যক্ষ করেছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.