পাইটরঞ্চ, গ্রেডিয়েন্ট আর্গুমেন্টগুলি কী


112

আমি পাইটর্চের ডকুমেন্টেশনগুলি পড়ছি এবং যেখানে তারা লিখেছে তার একটি উদাহরণ পেয়েছি

gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)

যেখানে x হল প্রাথমিক পরিবর্তনশীল, যেখান থেকে y নির্মিত হয়েছিল (একটি 3-ভেক্টর)। প্রশ্নটি হল, গ্রেডিয়েন্টস টেনসারের 0.1, 1.0 এবং 0.0001 টি আর্গুমেন্ট কী? ডকুমেন্টেশন যে খুব স্পষ্ট নয়।

উত্তর:


15

মূল কোড আমি পাইটর্চ ওয়েবসাইটে আর পাই নি।

gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)

উপরের কোডটিতে সমস্যাটি গ্রেডিয়েন্টগুলি গণনা করতে হবে তার ভিত্তিতে কোনও ফাংশন নেই। এর অর্থ আমরা জানি না যে কতগুলি পরামিতি (আর্গুমেন্টটি ফাংশনটি নেয়) এবং পরামিতিগুলির মাত্রা।

এটি পুরোপুরি বুঝতে আমি মূলটির কাছাকাছি একটি উদাহরণ তৈরি করেছি:

উদাহরণ 1:

a = torch.tensor([1.0, 2.0, 3.0], requires_grad = True)
b = torch.tensor([3.0, 4.0, 5.0], requires_grad = True)
c = torch.tensor([6.0, 7.0, 8.0], requires_grad = True)

y=3*a + 2*b*b + torch.log(c)    
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients,retain_graph=True)    

print(a.grad) # tensor([3.0000e-01, 3.0000e+00, 3.0000e-04])
print(b.grad) # tensor([1.2000e+00, 1.6000e+01, 2.0000e-03])
print(c.grad) # tensor([1.6667e-02, 1.4286e-01, 1.2500e-05])

আমি ধরে নিলাম যে আমাদের ফাংশনটি রয়েছে y=3*a + 2*b*b + torch.log(c)এবং পরামিতিগুলি ভিতরে তিনটি উপাদান সহ টেনারগুলি।

আপনি gradients = torch.FloatTensor([0.1, 1.0, 0.0001])এটির মতো ভাবতে পারেন এটি সঞ্চালক।

আপনি যেমন শুনতে পাচ্ছেন পাইটর্চ অটোগ্রাড সিস্টেম গণনা জ্যাকবিয়ান পণ্যের সমান।

Jacobian

আপনার মতো কোনও ফাংশন থাকলে যেমন আমরা করেছি:

y=3*a + 2*b*b + torch.log(c)

জ্যাকবিয়ান হবে [3, 4*b, 1/c]। যাইহোক, এই জ্যাকবীয় নয় যে পাইটর্চ কীভাবে নির্দিষ্ট সময়ে গ্রেডিয়েন্টগুলি গণনা করার জন্য জিনিসগুলি করছে।

পাইটর্চ ফরওয়ার্ড পাস এবং ব্যাকওয়ার্ড মোড স্বয়ংক্রিয় পার্থক্য ব্যবহার করে (AD) ব্যবহার করে।

কোনও প্রতীকী গণিত জড়িত নেই এবং কোনও সাংখ্যিক পার্থক্য নেই।

সংখ্যাগত পার্থক্য গণনা করা হবে δy/δb, যেখানে b=1এবং b=1+εযেখানে ε ছোট।

আপনি যদি এখানে গ্রেডিয়েন্ট ব্যবহার না করেন y.backward():

উদাহরণ 2

a = torch.tensor(0.1, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(0.1, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)

y.backward()

print(a.grad) # tensor(3.)
print(b.grad) # tensor(4.)
print(c.grad) # tensor(10.)

আপনি সহজ কিভাবে আপনি আপনার সেট উপর ভিত্তি করে কোনো সময়ে ফলাফলের পাবেন a, b, ctensors প্রাথমিকভাবে।

সতর্কতা অবলম্বন করা আবশ্যক কিভাবে আপনি আপনার আরম্ভ a, b, c:

উদাহরণ 3:

a = torch.empty(1, requires_grad = True, pin_memory=True)
b = torch.empty(1, requires_grad = True, pin_memory=True)
c = torch.empty(1, requires_grad = True, pin_memory=True)

y=3*a + 2*b*b + torch.log(c)

gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)

print(a.grad) # tensor([3.3003])
print(b.grad) # tensor([0.])
print(c.grad) # tensor([inf])

আপনি যদি ব্যবহার করেন torch.empty()এবং ব্যবহার না করেন তবে pin_memory=Trueআপনার প্রতিবার বিভিন্ন ফলাফল হতে পারে।

এছাড়াও, নোট গ্রেডিয়েন্টগুলি সংগ্রহকারীর মতো তাই যখন প্রয়োজন হয় তখন সেগুলি শূন্য করে।

উদাহরণ 4:

a = torch.tensor(1.0, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(1.0, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)

y.backward(retain_graph=True)
y.backward()

print(a.grad) # tensor(6.)
print(b.grad) # tensor(8.)
print(c.grad) # tensor(2.)

পাইটর্চ শর্তাদি ব্যবহারের সর্বশেষে কয়েকটি টিপস:

পাইটর্চ একটি ডায়নামিক কম্পিউটেশনাল গ্রাফ তৈরি করেফরোয়ার্ড পাসে গ্রেডিয়েন্টগুলি গণনা করার সময় । এটি দেখতে অনেকটা গাছের মতো।

তাই আপনি যদি প্রায়ই শুনতে পাবে পাতার এ গাছের হয় ইনপুট tensors এবং রুট হল আউটপুট টেন্সর

গ্রেডিয়েন্টগুলি গ্রাফটিকে শিকড় থেকে পাতায় ট্রেস করে এবং চেইন বিধিটি ব্যবহার করে প্রতিটি গ্রেডিয়েন্টকে গুণের মাধ্যমে গণনা করা হয় । পিছনের পাসে এই গুণটি ঘটে।


দুর্দান্ত উত্তর! যাইহোক, আমি মনে করি না পাইটোর্চ সংখ্যাসূচক পার্থক্য করে ("পূর্ববর্তী ফাংশনের জন্য পাইটর্চ উদাহরণস্বরূপ by / bb করবে, খ = 1 এবং খ = 1 + ε যেখানে small ছোট। তাই এখানে প্রতীকী গণিতের মতো কিছুই নেই। ") - আমি বিশ্বাস করি এটি স্বয়ংক্রিয় পার্থক্য করে।
সর্বোচ্চ_ম্যাক্স_মির

হ্যাঁ, এটি AD বা স্বয়ংক্রিয় পার্থক্য ব্যবহার করে, পরে আমি এই পিডিএফটির মতো এডি আরও তদন্ত করেছিলাম , যাইহোক, আমি যখন এই উত্তরটি সেট করি তখন আমাকে বেশ কিছু জানানো হয়নি।
prosti থেকে

উদাহরণস্বরূপ 2 রানটাইমআরার দেয়: আকারে মেলেনি: গ্রেড_আউটপুট [0] এর একটি মশাল রয়েছে ize আকার ([3]) এবং আউটপুট [0] এর মশাল একটি আকার রয়েছে S আকার ([])।
আন্দ্রেয়াস কে।

@ আন্দ্রেসাক।, আপনি ঠিক বলেছেন, পাইটর্চ সম্প্রতি শূন্য আকারের টেনজার প্রবর্তন করেছিল এবং এটি আমার আগের উদাহরণগুলিতে প্রভাব ফেলেছিল। এই উদাহরণগুলি গুরুত্বপূর্ণ ছিল না তাই অপসারণ।
prosti থেকে

100

ব্যাখ্যা

নিউরাল নেটওয়ার্কগুলির জন্য, আমরা সাধারণত lossনির্ধারণ করতে ব্যবহার করি যে ইনপুট চিত্র (বা অন্যান্য টাস্ক) শ্রেণিবদ্ধ করতে নেটওয়ার্ক কতটা ভাল শিখেছে। lossশব্দটি সাধারণত একটি স্কেলার মান। নেটওয়ার্কের প্যারামিটারগুলি আপডেট করার জন্য, আমাদের lossপ্যারামিটারগুলিতে আর্টের গ্রেডিয়েন্ট গণনা করতে হবে যা আসলে leaf nodeগণনা গ্রাফে রয়েছে (উপায় দ্বারা, এই পরামিতিগুলি বেশিরভাগই বিভিন্ন স্তরগুলির ওজন এবং পক্ষপাত যেমন কনভোলিউশন, লিনিয়ার এবং শীঘ্রই).

শৃঙ্খলা বিধি অনুসারে, lossএকটি পাতার নোডে কব্জিটির গ্রেডিয়েন্ট গণনা করার জন্য , আমরা lossকব্জি কিছু মধ্যবর্তী পরিবর্তনশীল এবং পাতার ভেরিয়েবলের মধ্যে অন্তর্বর্তী ভেরিয়েবল আর্টের গ্রেডিয়েন্ট গণনা করতে পারি, একটি বিন্দুর পণ্য তৈরি করতে পারি এবং এই সমস্তগুলি যোগ করতে পারি।

gradientএকটি অফ আর্গুমেন্ট Variableএর backward()পদ্ধতি ব্যবহার করা হয় wrt একটি পরিবর্তনশীল প্রতিটি উপাদান একটি ভরযুক্ত সমষ্টি নিরূপণ পাতার চলকএই ওজন lossঅন্তর্বর্তী ভেরিয়েবলের প্রতিটি উপাদানকে চূড়ান্ত কব্জি থেকে পাওয়া যায়।

একটি দৃ concrete় উদাহরণ

আসুন এটি বোঝার জন্য একটি কংক্রিট এবং সাধারণ উদাহরণ গ্রহণ করুন।

from torch.autograd import Variable
import torch
x = Variable(torch.FloatTensor([[1, 2, 3, 4]]), requires_grad=True)
z = 2*x
loss = z.sum(dim=1)

# do backward for first element of z
z.backward(torch.FloatTensor([[1, 0, 0, 0]]), retain_graph=True)
print(x.grad.data)
x.grad.data.zero_() #remove gradient in x.grad, or it will be accumulated

# do backward for second element of z
z.backward(torch.FloatTensor([[0, 1, 0, 0]]), retain_graph=True)
print(x.grad.data)
x.grad.data.zero_()

# do backward for all elements of z, with weight equal to the derivative of
# loss w.r.t z_1, z_2, z_3 and z_4
z.backward(torch.FloatTensor([[1, 1, 1, 1]]), retain_graph=True)
print(x.grad.data)
x.grad.data.zero_()

# or we can directly backprop using loss
loss.backward() # equivalent to loss.backward(torch.FloatTensor([1.0]))
print(x.grad.data)    

উপরের উদাহরণে, প্রথম ফলাফল printহল

2 0 0 0
[আকার 1x4 আকারের ফ্ল্যাটটেন্সার]

যা হ'ল এক্স-এর থেকে z_1 আর্টের ডেরাইভেটিভ।

দ্বিতীয় ফলাফল print:

0 2 0 0
[আকার 1x4 আকারের ফ্ল্যাটটেন্সার]

যা z2 আর্ট থেকে এক্স এর ডেরাইভেটিভ।

এখন z 1t থেকে x এর ডেরিভেটিভ এক্স গণনা করতে [1, 1, 1, 1] এর ওজন ব্যবহার করলে ফলাফলটি হয় 1*dz_1/dx + 1*dz_2/dx + 1*dz_3/dx + 1*dz_4/dx। সুতরাং আশ্চর্যের কিছু নেই, 3 য় এর আউটপুট printহল:

2 2 2 2
[আকার 1x4 আকারের ফ্ল্যাটটেন্সার]

এটি লক্ষ করা উচিত যে ওজন ভেক্টর [1, 1, 1, 1] losszt, z_2, z_3 এবং z_4 এ হুবহু থেকে সঠিকভাবে ডাইরেক্টিভ। lossরিট এর ডেরাইভেটিভ xহিসাবে গণনা করা হয়:

d(loss)/dx = d(loss)/dz_1 * dz_1/dx + d(loss)/dz_2 * dz_2/dx + d(loss)/dz_3 * dz_3/dx + d(loss)/dz_4 * dz_4/dx

সুতরাং 4 র্থ আউটপুট print3 য় print:

2 2 2 2
[আকার 1x4 আকারের ফ্ল্যাটটেন্সার]


1
কেবল একটি সন্দেহ, কেন আমরা ক্ষতির জন্য গ্রেডিয়েন্টগুলির জন্য x.grad.data গণনা করছি
প্রিয়ঙ্ক পাঠক

7
হতে পারে আমি কিছু মিস করেছি, তবে আমার মনে হয়েছে যে সরকারী ডকুমেন্টেশনগুলি সত্যই gradientযুক্তিটি আরও ভালভাবে ব্যাখ্যা করতে পারত । আপনার উত্তরের জন্য ধন্যবাদ.
নায়ক নায়ক

3
@jdhao "এটা উল্লেখ করা উচিত যে ওজন ভেক্টর [1, 1, 1, 1]ঠিক ব্যুৎপন্ন হয় lossকরতে wrt z_1, z_2, z_3এবং z_4।" আমি মনে করি এই বিবৃতিটি উত্তরের চাবিকাঠি। ওপির কোডটির দিকে তাকানোর সময় একটি বড় প্রশ্ন চিহ্ন হ'ল গ্রেডিয়েন্টের জন্য এই স্বেচ্ছাচারিত (যাদু) নম্বরগুলি কোথা থেকে আসে। আপনার দৃ concrete় উদাহরণে আমি মনে করি যে খুব শীঘ্রই [1, 0, 0 0]টেনসর এবং lossফাংশনটির মধ্যে সম্পর্ক চিহ্নিত করার জন্য এটি খুব সহায়ক হবে যাতে কেউ দেখতে পাবে যে এই উদাহরণগুলিতে মানগুলি নির্বিচারে নয়।
a_guest

1
@ এসএমউইকিপিডিয়া, এটি সত্য নয়। আমরা যদি প্রসারিত loss = z.sum(dim=1)করি তবে তা হয়ে উঠবে loss = z_1 + z_2 + z_3 + z_4। আপনি সহজ ক্যালকুলাস জানেন তাহলে, তোমরা জানবে যে ডেরিভেটিভ losswrt করতে z_1, z_2, z_3, z_4হয় [1, 1, 1, 1]
jdhao

1
আমি তোমায় ভালোবাসি. আমার সন্দেহ সমাধান!
ব্ল্যাক জ্যাক 21

45

সাধারণত, আপনার কম্পিউটেশনাল গ্রাফটিতে একটি স্কেলার আউটপুট রয়েছে loss। তারপরে আপনি lossকব্জি দিয়ে ওয়েট ( w) এর গ্রেডিয়েন্টটি গণনা করতে পারেন loss.backward()। কোথায় ডিফল্ট যুক্তি backward()হল 1.0

যদি আপনার আউটপুটে একাধিক মান থাকে (উদাহরণস্বরূপ loss=[loss1, loss2, loss3]), আপনি ক্ষতির গ্রেডিয়েন্টগুলি ওজন দ্বারা আঁকতে পারেন loss.backward(torch.FloatTensor([1.0, 1.0, 1.0]))

তদতিরিক্ত, আপনি যদি বিভিন্ন ক্ষতির মধ্যে ওজন বা আমদানি যুক্ত করতে চান তবে আপনি ব্যবহার করতে পারেন loss.backward(torch.FloatTensor([-0.1, 1.0, 0.0001]))

এর অর্থ -0.1*d(loss1)/dw, d(loss2)/dw, 0.0001*d(loss3)/dwএকসাথে গণনা করা ।


1
"আপনি যদি বিভিন্ন লোকসানে ওজন বা আমদানি যুক্ত করতে চান তবে আপনি লোকস.বওয়ারওয়ার্ড (টর্চ। ফ্লাটটেন্সর ([- 0.1, 1.0, 0.0001])) ব্যবহার করতে পারেন।" -> এটি সত্য তবে কিছুটা বিভ্রান্তিকর কারণ আমরা পাস করার মূল কারণ grad_tensorsহ'ল তাদের আলাদাভাবে ওজন না করা বরং তারা সংশ্লিষ্ট টেনারগুলির প্রতিটি উপাদানকে গ্রেডিয়েন্ট করে।
অ্যারিন

27

এখানে, ফরওয়ার্ডের আউটপুট (), অর্থাৎ y এএ 3-ভেক্টর or

তিনটি মান নেটওয়ার্কের আউটপুটে গ্রেডিয়েন্ট। এগুলি সাধারণত y তে নির্ধারণ করা হয় যদি y চূড়ান্ত আউটপুট হয় তবে অন্যান্য মানও থাকতে পারে, বিশেষত যদি y একটি বড় নেটওয়ার্কের অংশ হয়।

যেমন যেমন x যদি ইনপুট হয়, y = [y1, y2, y3] একটি মধ্যবর্তী আউটপুট যা চূড়ান্ত আউটপুট z গণনা করতে ব্যবহৃত হয়,

তারপর,

dz/dx = dz/dy1 * dy1/dx + dz/dy2 * dy2/dx + dz/dy3 * dy3/dx

সুতরাং এখানে, পিছনে তিনটি মান হয়

[dz/dy1, dz/dy2, dz/dy3]

এবং তারপরে () গণনা ডিজে / ডিএক্স utes


5
উত্তরের জন্য ধন্যবাদ তবে বাস্তবে এটি কীভাবে কার্যকর? মানে আমাদের হার্ডকোডিং ব্যাকপ্রপ ব্যতীত [dz / dy1, dz / dy2, dz / dy3] কোথায় দরকার?
হাই 15

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