ڈھلوان کی طرف: Gradient Descent، اور وہ دو قدم جو سب چھوڑ دیتے ہیں
learning rate کی عین حد نکالیں، پھر 3,600 سمتوں کی brute-force تلاش کو gradient دوبارہ دریافت کرتے دیکھیں۔
اس صفحے پر
پچھلا باب ایک وادی پر ختم ہوا تھا۔
استعارے والی نہیں: ایک حقیقی curve، جس میں loss کو ایک parameter کے مقابل plot کیا گیا تھا، نیچے جھکتی ہوئی اور پھر واپس اوپر آتی ہوئی۔ اور اس کے نیچے موجود loss اس لیے نہیں چنا گیا تھا کہ وہ صاف ستھرا تھا — اسے measurements میں noise کے بارے میں ایک statement سے derive کیا گیا تھا، اور squared error دوسری طرف convention کے بجائے consequence کے طور پر نکلا تھا۔
تو ہمارے پاس ایک landscape ہے جس کی تہہ ہے، اور یہ ماننے کی وجہ ہے کہ تہہ ہی صحیح جگہ ہے۔ جو چیز ہمارے پاس نہیں ہے وہ وہاں پہنچنے کا طریقہ ہے۔
یہ باب وہ طریقہ بناتا ہے، اور یہی algorithm اس course کے باقی ہر model کو train کرتا ہے — ہر ایک کو، بغیر exception، ان models تک جن میں hundreds of billions parameters ہوتے ہیں۔ یہ تقریباً بیس lines میں آ جاتا ہے۔ مشکل دو حصے ان بیس lines میں نہیں ہیں، اور یہی وہ دو چیزیں ہیں جنہیں تقریباً ہر explanation چھوڑ دیتی ہے:
- minus sign کیوں۔ update gradient کو subtract کرتا ہے۔ ہر tutorial اسے لکھتا ہے؛ بہت کم بتاتے ہیں کہ gradient وہ direction کیوں ہے جو اوپر جاتی ہے، اور یہی واحد fact ہے جو minus sign کو ایمان کے عمل کے بجائے معنی دیتا ہے۔
- قدم کتنا بڑا۔ «بہت بڑا diverge کرتا ہے، بہت چھوٹا slow ہے» درست ہے اور بےکار بھی۔ ایک exact number ہے، loss سے compute کیا جا سکتا ہے، اور یہ باب اسے دو بار compute کرتا ہے — ایک toy parabola کے لیے اور ایک actual data کے لیے۔
setup، اور آپ صرف search کیوں نہیں کر سکتے
اس حصے کا لنک: setup، اور آپ صرف search کیوں نہیں کر سکتےتاکہ یہ باب اپنے پاؤں پر کھڑا رہے، بات دوبارہ: Chapter 1 کے conveyor belt کے آٹھ parts، مگر سوال مختلف۔ accept یا reject نہیں — وہ بعد میں واپس آئے گا — بلکہ کسی part کا weight اس کی width سے predict کرنا۔
import numpy as np
WIDTH = np.array([18.0, 19.5, 20.2, 21.0, 24.0, 25.5, 23.0, 26.0])
WEIGHT = np.array([47.0, 52.0, 49.0, 55.0, 61.0, 66.0, 70.0, 58.0])
x = WIDTH - WIDTH.mean() # 22.15 mm
y = WEIGHT - WEIGHT.mean() # 57.25 gmeasurements centred ہیں، بالکل Chapter 1 کی طرح، اور ایک ایسی وجہ سے جو اس باب کے ختم ہونے سے پہلے سود سمیت واپس آتی ہے۔ model ایک line ہے، ، اور loss وہ mean squared error ہے جو پچھلے باب نے derive کیا تھا:
دو parameters۔ بس بہت سی values try کیوں نہ کر لیں؟ آئیے واقعی کرتے ہیں — سے تک اور سے تک ایک grid، کے steps میں:
grid 501 x 1001 = 501,501 evaluations in 3.67 s
best found: a = 2.1000, b = -0.0000, L = 24.592450دو numbers کو دو decimal places تک pin down کرنے کے لیے آدھا million evaluations — اور وہ second ایک machine پر wall clock ہے، اس لیے rerun تین سے چھ کے بیچ کہیں بھی آ سکتا ہے؛ evaluation count اور minimum وہ حصہ ہیں جو reproduce ہوتا ہے۔ Gradient descent، اس باب کے آخر میں، آٹھ steps میں چار decimal places اور چھتیس میں full float64 answer حاصل کر لیتا ہے۔
مگر speed اصل argument نہیں، اور یہی point پورے course کا فیصلہ کرتا ہے۔ Grid search parameters کے لیے، ہر ایک پر values کے ساتھ، evaluations مانگتی ہے۔ ہر axis پر ایک ہزار values کے ساتھ:
| model | parameters | grid evaluations |
|---|---|---|
| یہ line | 2 | |
| Chapter 5 کا XOR network | 9 | |
| ایک چھوٹا multilayer network | 20,000 |
تیسری row کوئی بڑا number نہیں، ایک بےمعنی number ہے — observable universe میں تقریباً atoms ہیں۔ models بڑھنے پر search slow نہیں ہوتی؛ وہ موجود ہی نہیں رہتی۔ آگے آنے والی ہر چیز اسی table کی وجہ سے موجود ہے۔
derivative ایک measurement ہے جو آپ لے سکتے ہیں
اس حصے کا لنک: derivative ایک measurement ہے جو آپ لے سکتے ہیںایک لمحے کے لیے fix کر دیں تاکہ ایک parameter اور ایک curve رہ جائے، وہی picture جو پچھلا باب چھوڑ گیا تھا۔ اس پر ایک point لیں، ، اور پوچھیں: اگر میں کو ایک چھوٹی مقدار سے nudge کروں تو loss فی unit nudge کتنا move کرتا ہے؟
یہ ratio rise over run ہے — curve پر دو points کے بیچ straight line کی slope۔ جیسے جیسے shrink ہوتا ہے، دونوں points ساتھ ساتھ slide کرتے ہیں اور line tangent بن جاتی ہے۔ اس کی slope derivative ہے: میں change کے فی unit loss کے change کی rate۔ کسی چیز کی approximation نہیں، اور کوئی infinitely small quantity بھی نہیں۔ ordinary ratios کا limit۔
اسے run کرنا worth it ہے، کیونکہ numbers وہ بات کہتے ہیں جو definition نہیں کہتی:
def loss1(a):
return np.mean((a * x - y) ** 2)
for h in [1.0, 1e-2, 1e-4, 1e-6, 1e-8, 1e-10, 1e-12, 1e-14]:
q = (loss1(1.0 + h) - loss1(1.0)) / h
print(f"h = {h:<8.0e} slope estimate = {q:.10f} error = {abs(q + 16.385):.3e}")h = 1e+00 slope estimate = -8.9400000000 error = 7.445e+00
h = 1e-02 slope estimate = -16.3105500000 error = 7.445e-02
h = 1e-04 slope estimate = -16.3842555001 error = 7.445e-04
h = 1e-06 slope estimate = -16.3849925556 error = 7.444e-06
h = 1e-08 slope estimate = -16.3850003787 error = 3.787e-07
h = 1e-10 slope estimate = -16.3850444324 error = 4.443e-05
h = 1e-12 slope estimate = -16.3851154866 error = 1.155e-04
h = 1e-14 slope estimate = -17.0530256582 error = 6.680e-01یہاں دو چیزیں ہوتی ہیں اور دونوں load-bearing ہیں۔
error مبہم طور پر کے proportional نہیں — وہ exact ہے۔ کو سو سے divide کریں، error بھی سو سے divide ہو جاتا ہے، ہر بار چار significant figures تک۔ وہ constant decoration نہیں: وہ loss کے second derivative کا half ہے، اور اس idea کی پہلی جھلک ہے جو دو sections بعد آئے گا — کہ point کے نزدیک curve ایک line plus ایک correction جیسا ہوتا ہے جو کے proportional ہوتا ہے۔
اور پھر pattern ٹوٹ جاتا ہے۔ سے نیچے estimate بدتر ہو جاتا ہے، اور پر وہ second digit میں غلط ہے۔ mathematical کچھ نہیں ہوا؛ پچھلے باب کا floating-point box ہوا۔ اور اپنے پہلے دس digits میں agree کرتے ہیں، انہیں subtract کرنے سے وہ digits تباہ ہو جاتے ہیں، اور wreckage کو tiny number سے divide کرنا باقی بچے ہوئے کو amplify کر دیتا ہے۔ ایک best ہے — یہاں تقریباً ، machine epsilon کے square root کے لگ بھگ — اور اس سے چھوٹا جانا زیادہ careful نہیں، کم careful ہے۔ اسے یاد رکھیں؛ اس باب کے آخر میں ایک function اس پر depend کرتا ہے۔
calculus سے exact slope، measurement کے بجائے، ہے۔ تو ہم measuring روک کر deriving شروع کر سکتے ہیں۔
Composition، اور chain rule
اس حصے کا لنک: Composition، اور chain ruleیہ وہ idea ہے جس پر باقی course built ہے، ایک بار صاف لفظوں میں۔
دو functions کو compose کرنا یعنی ایک کو دوسرے میں feed کرنا: ۔ بس۔
deep network composition جیسا نہیں ہوتا۔ وہ ہے composition۔ layer ایک function ہے؛ layers stack کرنا انہیں compose کرنا ہے؛ «depth» chain میں functions کی تعداد ہے۔ جب Chapter 5 ایک network بناتا ہے تو وہ بنا رہا ہوتا ہے، اور کچھ نہیں۔ جس کا مطلب ہے کہ ہمارے purposes کے لیے calculus کا single most important rule وہ ہے جو composition کو differentiate کرتا ہے:
Rates multiply کرتی ہیں۔ اگر ، کے مقابل تین گنا تیزی سے change کرتا ہے، اور ، کے مقابل دو گنا تیزی سے، تو ، کے مقابل چھ گنا تیزی سے change کرتا ہے۔ یہی پوری بات ہے، اور اسی لیے دس layers سے واپس گزرتا ہوا signal دس numbers سے multiply ہوتا ہے — یہی وجہ ہے کہ Chapter 6 ایک section اس بات پر خرچ کرتا ہے کہ جب وہ numbers سب کے سب ایک سے تھوڑے کم ہوں تو کیا ہوتا ہے۔
اسے اپنے loss پر use کریں۔ residual لکھیں، تاکہ ۔ ہر ، پر inner function کے ذریعے depend کرتا ہے، جس کا derivative ہے۔ Chain rule، term by term:
وہ curly symbols ایک partial derivative mark کرتے ہیں: ایک variable کے respect میں differentiate کریں اور ہر دوسرے کو constant treat کریں۔ کچھ نیا نہیں ہوتا — وہی limit ہے جو پہلے تھا، بس ایک axis کے along لیا گیا۔ partials کو ایک vector میں collect کریں اور آپ کے پاس gradient ہے:
point پر یہ vector ہے۔ دو numbers۔ سوال یہ ہے کہ ان کا مطلب کیا ہے، اور یہی وہ پہلا قدم ہے جسے سب چھوڑ دیتے ہیں۔
gradient uphill کیوں point کرتا ہے
اس حصے کا لنک: gradient uphill کیوں point کرتا ہےgradient axes کے along slopes کا vector ہے۔ ہم نے بس اتنا prove کیا ہے۔ یہ obvious نہیں — obvious ہونا بھی نہیں چاہیے — کہ انہیں vector میں assemble کرنے سے کوئی چیز کسی خاص direction میں point کرتی ہے۔
تو وہ چیز define کریں جو ہمیں واقعی چاہیے۔ ایک unit vector pick کریں، ایک direction۔ directional derivative وہ rate ہے جس سے loss اس direction میں چلنے پر change کرتا ہے:
Chain rule اسے computable بنا دیتا ہے۔ کے along چلنا کو rate سے اور کو rate سے change کرتا ہے، اور contributions add ہو جاتی ہیں:
کسی بھی direction میں rate of change gradient اور اس direction کا dot product ہے۔ اور اب punchline، geometry کی ایک line۔ vectors کے بیچ angle کے ساتھ dot product لکھتے ہوئے،
کیونکہ کی length 1 ہے۔ آپ صرف control کرتے ہیں، جو پر largest اور half turn، degrees پر smallest ہے۔ اس لیے:
- steepest ascent خود کے along ہے، اور وہاں slope exact ہے۔
- steepest descent کے along ہے، اور وہاں slope ہے۔
- gradient کے perpendicular، loss بالکل change نہیں کرتا۔ اسی لیے contour map کی lines gradient کو right angles پر cross کرتی ہیں۔
یہی minus sign ہے۔ convention نہیں، کسی کا chosen sign flip نہیں: fastest decrease کی direction negative gradient ہے کیونکہ half turn پر minimise ہوتا ہے، اور کسی اور وجہ سے نہیں۔
چونکہ یہ claim تمام directions کے بارے میں ہے، اسے تمام directions کے against test کریں۔ 3,600 directions sample کریں، ہر tenth of a degree پر ایک، اور ہر ایک کو nudge کر کے measure کریں:
theta = np.array([1.0, 4.0])
g = grad(theta)
print("gradient ", g)
print("its length ", np.linalg.norm(g))
print("its angle ", np.degrees(np.arctan2(g[1], g[0])) % 360, "degrees")
best = max(
((loss(theta + 1e-6 * u) - loss(theta - 1e-6 * u)) / 2e-6, np.degrees(ang))
for ang, u in (
(a, np.array([np.cos(a), np.sin(a)])) for a in np.arange(3600) * 2 * np.pi / 3600
)
)
print("steepest slope", best[0], "at", best[1], "degrees")gradient [-16.385 8. ]
its length 18.23371122399386
its angle 153.97598928042032 degrees
steepest slope 18.233709624837502 at 154.0 degreesایک search جسے gradients کے بارے میں کچھ نہیں معلوم، 3,600 directions پر، اپنی steepest climb 154.0 degrees پر پاتی ہے — gradient کی اپنی direction، search کی 0.1-degree resolution کے اندر۔ اور وہاں جو slope ملتی ہے، 18.2337، چھ figures تک gradient کی length ہے۔ theorem gradients کے معنی کی story نہیں؛ یہ measurable fact ہے، اور یہ اس کی measurement ہے۔
downhill ایک چھوٹا step واقعی مدد کیوں کرتا ہے
اس حصے کا لنک: downhill ایک چھوٹا step واقعی مدد کیوں کرتا ہےاب دوسرا skipped step۔ ہمیں معلوم ہے down کس طرف ہے۔ اس سے یہ follow نہیں کرتا کہ اس طرف چلنے سے loss کم ہو گا، کیونکہ «down» infinitesimal nudge کے بارے میں statement ہے اور step infinitesimal نہیں ہوتا۔
bridge linearisation ہے۔ ایک point کے near، smooth function اپنی tangent plus correction ہوتا ہے:
یہ first-order Taylor expansion ہے۔ discard کیا گیا curvature ہے — وہی term جس نے slope table کے estimate کو exact سے wrong بنایا۔ وہ step ڈالیں جو ہم لینے کا intend رکھتے ہیں، :
loss سے drop کرتا ہے۔ اس کا ہر part non-negative ہے، اس لیے promise real ہے — کافی چھوٹے کے لیے، کیونکہ neglected term کی طرح grow کرتا ہے اور آخرکار اسے کھا جاتا ہے۔ یہی پوری theory ہے۔ یہ promise پہلے پورا ہوتا، پھر ٹوٹتا ہوا:
eta = 0.2 promised 66.49364500 delivered -16.01619240 ratio -0.240868
eta = 0.1 promised 33.24682250 delivered 12.61936315 ratio 0.379566
eta = 0.01 promised 3.32468225 delivered 3.11840766 ratio 0.937957
eta = 0.001 promised 0.33246822 delivered 0.33040548 ratio 0.993796
eta = 0.0001 promised 0.03324682 delivered 0.03322620 ratio 0.999380
eta = 1e-05 promised 0.00332468 delivered 0.00332448 ratio 0.999938اسے bottom سے پڑھیں۔ جیسے shrink ہوتا ہے delivered drop promised drop پر converge کرتا ہے — ratio 0.99938، پھر 0.99994 — یعنی Taylor's theorem صحیح ہے۔ top سے پڑھیں تو پر delivered «drop» negative sixteen ہے۔ step downhill گیا اور loss اوپر چلا گیا۔
تو update rule ہے
اور اس کے ساتھ ایک condition آتی ہے جو کوئی state نہیں کرتا، کہ کافی چھوٹا ہے۔ کس کے مقابل کافی چھوٹا، exactly، یہ اگلا section ہے۔
learning rate کی ایک ceiling ہے، اور وہ computable ہے
اس حصے کا لنک: learning rate کی ایک ceiling ہے، اور وہ computable ہےسب سے simple valley سے شروع کریں، ، جہاں ۔ gradient descent کا ایک step ہے
position ہر step پر سے multiply ہوتی ہے۔ یہ geometric sequence ہے، اور geometric sequences کا exact ایک rule ہے: جب multiplier absolute value میں 1 سے چھوٹا ہو تو وہ shrink کرتی ہیں، ورنہ grow۔ تو ، یعنی ۔
boundary exactly پر ہے۔ «around 1» نہیں، «1 usually too big ہے» نہیں۔ پر multiplier ہے اور point ہمیشہ اور کے بیچ bounce کرتا رہتا ہے، نہ قریب آتا ہے نہ escape کرتا ہے۔ اس سے نیچے، converge؛ اس سے اوپر، diverge۔ interval دوبارہ پر split ہوتا ہے، جہاں multiplier sign بدلتا ہے: اس سے نیچے approach monotone ہے، اس سے اوپر point overshoot کر کے sides alternate کرتا ہے، اور exact پر multiplier 0 ہے اور ایک ہی step minimum پر land کر جاتا ہے۔
algebra کی چار lines سے چار regimes۔ جا کر boundaries خود cross کریں:
اور اب interesting one:
اب general rule، جو اسی argument سے نکلتا ہے۔ multiplier دراصل تھا، اور minimum کے near multi-parameter loss میں ہر direction کے لیے ایسا ایک number ہوتا ہے — second derivatives کی matrix کے eigenvalues۔ ہر direction کو ایک ساتھ stable ہونا پڑتا ہے، اس لیے ceiling largest سے set ہوتی ہے:
کے لیے، ، ceiling 1، جو ہم نے ابھی derive کیا۔ ہماری belt کے لیے، second-derivative matrix ہے جس میں inputs کی two-column matrix ہے، اور اس کے eigenvalues 2 اور 14.89 ہیں، اس لیے ceiling ہے۔ یہ پانچ significant figures والی prediction ہے۔ اسے test کریں:
lr=0.1343 -> L = 24.5924
lr=0.13431 -> L = 24.5924
lr=0.13432 -> L = 4707.8 BLEW UP
lr=0.13433 -> L = 4.00452e+16 BLEW UP
lr=0.1344 -> L = 1.18229e+107 BLEW UPlinear algebra کی ایک line اور for loop کی ایک hundred thousand iterations کے بیچ پانچ decimal places کی agreement۔
اور یہی وہ جگہ ہے جہاں Chapter 1 واپس آتا ہے۔ اوپر سب کچھ centred measurements کے ساتھ تھا۔ identical code raw millimetres اور grams پر run کریں تو eigenvalues 2 اور 14.89 کے بجائے 0.0298 اور 998.1 ہیں۔ ceiling 0.134 سے collapse ہو کر 0.002004 رہ جاتی ہے — اتنی ہی exact، lr=0.002003 پر converging اور lr=0.002004 پر blowing up۔
ceiling سے بھی worse eigenvalues کے بیچ ratio ہے۔ condition number measure کرتا ہے کہ valley round سے کتنی دور ہے: ایک long thin trench rate کو steep walls کے لیے کافی چھوٹا رکھنے پر مجبور کرتی ہے، اور پھر trench کا floor بھی اسی crawl پر walk ہوتا ہے۔ ہمارا centred میں 7.44 سے raw میں 33,452 ہو جاتا ہے۔ ہر version کی best rate کے ساتھ:
| features | condition number | best rate | optimum کے 1% کے اندر پہنچنے کے steps |
|---|---|---|---|
| centred | 7.44 | 0.1184 | 10 |
| raw millimetres and grams | 33,452 | 0.0020037 | 79,513 |
same data، same code، end پر same answer — اور آٹھ ہزار گنا کام، کیونکہ کسی نے mean subtract نہیں کیا۔ Chapter 1 میں اسی omission نے perceptron کو epochs میں factor of six thousand cost کیا، اور وہاں diagnosis geometric تھی: data origin سے بہت دور float کر رہا تھا۔ یہاں یہی geometry optimisation کے costume میں ہے، اور اسی لیے input normalisation hygiene advice نہیں بلکہ arithmetic ہے۔1
بیس lines
اس حصے کا لنک: بیس linesاوپر کسی چیز کو library کی ضرورت نہیں تھی۔ یہ پورا optimiser ہے۔
def loss(theta):
a, b = theta
return np.mean((a * x + b - y) ** 2)
def grad(theta):
a, b = theta
residual = a * x + b - y
return np.array([np.mean(2 * residual * x), np.mean(2 * residual)])
def descend(theta, lr, steps):
theta = np.array(theta, dtype=float)
for _ in range(steps):
theta = theta - lr * grad(theta)
return theta
theta = descend([0.0, 0.0], lr=0.05, steps=60)
print(theta, loss(theta))[ 2.10040296e+00 -2.76445533e-15] 24.592448791134984ان آٹھ points کے لیے closed-form least-squares answer ، ہے، loss کے ساتھ۔ loop نے یہ آٹھ significant figures تک find کر لیا، یہ جانے بغیر کہ closed form exist کرتی ہے — جو matter کرتا ہے، کیونکہ Chapter 5 کے بعد کوئی closed form نہیں ہو گی۔
trajectory، کیونکہ اسے دیکھنا ہی point ہے:
0 a=0.000000 b=0.000000 L=57.437500
1 a=1.563750 b=0.000000 L=26.736582
2 a=1.963288 b=-0.000000 L=24.732418
5 a=2.098116 b=-0.000000 L=24.592488
10 a=2.100400 b=-0.000000 L=24.592449
60 a=2.100403 b=-0.000000 L=24.592449distance کا زیادہ حصہ پہلے دو steps میں cover ہو جاتا ہے، کیونکہ gradient سب سے بڑا تب ہوتا ہے جب آپ bottom سے سب سے دور ہوتے ہیں اور قریب آتے ہوئے shrink ہوتا ہے۔ Gradient descent minimum کے near خود بخود slow ہو جاتا ہے۔ یہ feature ہے اور Chapter 6 میں problem بھی۔
slope اور کہاں zero ہے
اس حصے کا لنک: slope اور کہاں zero ہےاب تک کے argument میں ایک hole ہے۔ step تب stop ہوتا ہے جب ، اور ہم اسے «the minimum» کہتے آئے ہیں۔ zero gradient والا point critical point ہے، اور minimum ہونا اس کے ایک ہونے کے صرف ایک طریقہ ہے:
- ایک local minimum: ہر direction میں uphill، مگر ممکن ہے anywhere ایسا lowest point نہ ہو؛
- ایک local maximum: ہر direction میں downhill؛
- ایک saddle point: کچھ directions میں uphill اور کچھ میں downhill۔ surface کے پاس ہے، جو origin پر zero ہے، جہاں function -axis کے along minimum اور -axis کے along اسی وقت maximum ہے۔
Gradient descent انہیں apart نہیں tell کر سکتا، کیونکہ وہ صرف gradient کو دیکھتا ہے، اور gradient تینوں پر zero ہے۔
ہماری line کا ایک critical point ہے اور وہی answer ہے — linear model پر squared-error loss convex ہے، ایک single bowl، اور اس پر descent global minimum find کرنے میں fail نہیں ہو سکتا۔ یہ property اس course سے contact survive نہیں کرتی۔ neural network کا loss convex نہیں ہوتا، اور Chapter 5 سے آگے «the minimum» کوئی existing چیز نہیں: بہت سے minima ہوتے ہیں، different depths کے، اور آپ کو کون سا ملتا ہے اس پر depend کرتا ہے کہ آپ نے کہاں start کیا۔ یہ ایک sentence ہے اور ایک sentence ہی رہتا ہے، کیونکہ theory بڑی ہے اور practical consequence چھوٹا۔
آپ پورا consequence ایک curve پر دیکھ سکتے ہیں۔ لیں، جس میں different depths کی دو valleys ہیں:
x = -1.046681 f(x) = -0.352386 minimum
x = 0.101031 f(x) = 0.005026 maximum
x = 0.945649 f(x) = -0.152639 minimumshallow valley میں land کرنا loss میں 56.7% worse ہے، اور algorithm کے پاس جاننے کا کوئی طریقہ نہیں، کیونکہ valley کے اندر سے ہر direction uphill ہے۔ gradient descent میں اس کی کوئی repair نہیں اور آنے بھی نہیں والی۔ practice میں جو ہے وہ finding ہے کہ یہ picture جتنا suggest کرتی ہے اس سے کہیں کم matter کرتا ہے — real network کی very high dimensions میں زیادہ تر critical points traps کے بجائے saddles نکلتے ہیں،2 اور Chapter 5 measure کرتا ہے کہ ایک small network حقیقت میں کتنی بار stuck ہوتا ہے۔
سستے steps: stochastic، minibatch، momentum
اس حصے کا لنک: سستے steps: stochastic، minibatch، momentumاوپر grad کے بارے میں ایک چیز آپ کو bother کرنی چاہیے: یہ ہر step کے لیے پورے dataset پر sum کرتا ہے۔ آٹھ parts کچھ نہیں۔ ایک million یعنی parameters کو ایک بار move کرنے کے لیے ایک million gradient computations۔
escape یہ ہے کہ gradient ایک average ہے، اور average کو sample سے estimate کیا جا سکتا ہے۔ random handful — ایک minibatch — پر compute کریں، اور اسی پر step لیں۔ estimate noisy ہے؛ یہ unbiased بھی ہے، اور hundreds of cheap noisy steps ایک expensive exact step کو beat کرتے ہیں۔ ایک hundred thousand synthetic parts پر، steps کے بجائے per-example gradients count کرتے ہوئے:
| method | optimum کے 0.1% کے اندر پہنچنے کے steps | per-example gradients |
|---|---|---|
| full batch | 7 | 700,000 |
| 32 کا minibatch | 100 | 3,200 |
| ایک example at a time | 17,580 | 17,580 |
same place تک پہنچنے کے لیے two hundred and nineteen times کم arithmetic۔ اور extreme — ایک example at a time، Robbins and Monro3 کی original stochastic approximation — winner نہیں ہے: یہ 32 کے batches سے five times worse ہے، کیونکہ matrices multiply کرنے والے hardware پر 32 examples ایک سے تقریباً کچھ زیادہ cost نہیں کرتے، جبکہ noise batch size کے square root کے ساتھ fall off کرتا ہے۔ یہی trade-off ہے جس کی وجہ سے ہر training script جو آپ کبھی پڑھیں گے اس میں batch_size ہو گا۔
Momentum دوسرا cheap fix ہے، اور اس کا نشانہ سیدھا trench ہے۔ badly conditioned valley میں steps narrow direction کے across zig-zag کرتے ہیں جبکہ long one کے along crawl کرتے ہیں۔ Momentum past gradients کی running average رکھتا ہے، تاکہ oscillating components cancel ہوں اور consistent component accumulate ہو:4
دو extra lines۔ raw uncentred belt پر — condition number 33,452، ہمارے پاس worst case — اس best rate پر جو plain descent لے سکتا ہے:
momentum beta=0.0 -> 79,513 steps to 1%
momentum beta=0.9 -> 1,609 steps to 1%
momentum beta=0.99 -> 461 steps to 1%دو lines of code کے لیے factor of 172۔ Chapter 6 اسے Adam میں بدلتا ہے؛ mechanism پہلے ہی یہاں ہے۔
وہ check جس کی آپ کو Chapter 5 میں ضرورت ہو گی
اس حصے کا لنک: وہ check جس کی آپ کو Chapter 5 میں ضرورت ہو گیاس باب میں ہر gradient hand سے derive کیا گیا تھا، اس لیے wrong ہو سکتا تھا۔ fix beginning کی slope table ہے: derivative کو numerically measure کریں اور compare کریں۔ central difference use کریں، ، جو leading error term cancel کرتا ہے اور اسی کے لیے بہت زیادہ accurate ہے۔
def numeric_grad(f, theta, h=1e-5):
theta = np.asarray(theta, dtype=float)
out = np.zeros_like(theta)
for i in range(theta.size):
bump = np.zeros_like(theta)
bump[i] = h
out[i] = (f(theta + bump) - f(theta - bump)) / (2 * h)
return out
def gradcheck(f, df, theta, h=1e-5):
analytic = np.asarray(df(theta), dtype=float)
numeric = numeric_grad(f, theta, h)
return np.max(np.abs(analytic - numeric) / np.maximum(1e-8, np.abs(analytic) + np.abs(numeric)))comparison کی relative form matter کرتی ہے: کا absolute difference size کے gradient پر disaster ہے اور size کے gradient پر irrelevant۔
relative error: 1.8929136036763527e-11
with 2 dropped: 0.33333333331650744first line اوپر hand-derived gradient ہے۔ second وہی function ہے جس میں ایک component سے factor of 2 چھوڑ دیا گیا — single character کی typo — اور check اسے immediately catch کر لیتا ہے۔ تقریباً سے نیچے کچھ بھی agreement ہے؛ سے اوپر کچھ بھی bug ہے۔ یہ function رکھیں: Chapter 5 اسے automatic differentiation engine debug کرنے کے لیے use کرتا ہے، اور یہی واحد وجہ ہے کہ wrong gradient findable ہے۔
یہ آگے کہاں جاتا ہے
اس حصے کا لنک: یہ آگے کہاں جاتا ہےاس باب کی ہر چیز ایک ایسے assumption پر rest کرتی تھی جو کبھی stated نہیں تھا: کہ آپ لکھ سکتے ہیں۔
دو parameters والی line کے لیے، وہ algebra کی ایک line تھی۔ یہ تقریباً فوراً ہی ایک line رہنا چھوڑ دیتی ہے۔ کسی symbolic algebra system سے network کے loss کا derivative single first-layer weight کے respect میں، single example کے لیے مانگیں، اور answer میں arithmetic count کریں:
| network | ایک partial derivative میں operations |
|---|---|
| چار hidden units، ایک layer | 40 |
| چار hidden units، دو layers | 301 |
| چار hidden units، تین layers | 1,717 |
third row 57 parameters والا network ہے — اتنا small network کہ Chapter 6 میں footnote ہوتا — اور اس کا gradient hand سے لکھنے کا مطلب ایک training example کے لیے تقریباً 97,869 operations ہے۔ کوئی notation اسے rescue نہیں کرتی۔ جو rescue کرتی ہے وہ observation ہے کہ composition پر apply کیا گیا chain rule enormous structure رکھتا ہے، کہ وہی intermediate quantities بار بار appear ہوتی ہیں، اور انہیں right order میں compute کرنے سے تمام derivatives تقریباً ایک forward pass کی price پر مل جاتے ہیں۔ یہی Chapter 5 ہے۔
لیکن پہلے ایک چھوٹا problem ہے، اور وہ فوراً انتظار کر رہا ہے۔
اب ہمارے پاس ایک machine ہے جو کسی بھی differentiable loss پر downhill roll کرے گی۔ اسے belt کے original question پر point کریں — accept یا reject، ایک target جو 1 یا 0 ہے — output پر sigmoid لگائیں تاکہ یہ probability predict کرے، اور squared error minimise کریں۔ یہ run کرے گی۔ یہ تب بمشکل move بھی کرے گی جب یہ سب سے زیادہ wrong ہو، اور gradient بتاتا ہے کیوں:
| output | prediction | truth | squared error کے ساتھ gradient | cross-entropy کے ساتھ gradient |
|---|---|---|---|---|
| 0.5000 | 1 | |||
| 0.1192 | 1 | |||
| 0.0025 | 1 | |||
| 1 |
ایک model جو confidently، catastrophically wrong ہے — 0.0000454 predict کرتے ہوئے جب answer 1 ہے — کا squared-error gradient produce کرتا ہے۔ اسے idea ہی نہیں کہ یہ trouble میں ہے۔ دوسری column، ایک ایسے loss سے جسے ہم نے ابھی derive نہیں کیا، 1.0 report کرتی ہے: maximum urgency، exactly وہاں جہاں deserved ہے۔
جس سے وہ question اٹھتا ہے جس سے اگلا باب شروع ہوتا ہے۔ پچھلے باب نے کہا تھا کہ loss noise کے بارے میں assumption ہے، اور squared error Gaussian noise assume کرتا ہے۔ yes-or-no answer کا noise model کیا ہوتا ہے — اور جب آپ اسی derivation کو اس پر run کرتے ہیں تو کون سا loss نکلتا ہے؟
Sources and method
اس حصے کا لنک: Sources and methodmethod ان سب سے پرانا ہے: Cauchy نے 1847 میں Académie des Sciences کو ایک note میں اسے describe کیا، equations کے systems solve کرنے کے ایک طریقے کے طور پر، ان کے squared residuals کے sum پر downhill چلتے ہوئے۔ اس باب کے ساتھ یہ بھی پڑھنے کے قابل ہیں: Sebastian Ruder کا An overview of gradient descent optimization algorithms (arXiv:1609.04747)، جو momentum سے Adam تک چودہ readable pages میں cover کرتا ہے؛ Nocedal and Wright کی Numerical Optimization (2nd ed., Springer, 2006) کا chapter 3، جس کا theorem 3.3 condition number کے terms میں quadratic پر steepest descent کی convergence rate دیتا ہے — یہی وہ theory ہے جو بتاتی ہے کہ conditioning step count decide کیوں کرتی ہے، اگرچہ یہ اوپر measure کی گئی fixed-step ceiling کے بجائے line search treat کرتی ہے، یا Deisenroth, Faisal and Ong کی Mathematics for Machine Learning کے §5.8 اور §7.1 اسی ground کے لیے کم machinery کے ساتھ؛ Prince کی Understanding Deep Learning کا §6.1 اور Goodfellow, Bengio and Courville کی Deep Learning کا §4.3؛ Dive into Deep Learning §12.1–12.3، جس میں minibatch analysis یہاں جگہ سے زیادہ measurements کے ساتھ ہے؛ اور Géron کی Hands-On Machine Learning (3rd ed.) کا chapter 4، learning rate کا سب سے practical treatment ایک ایسی چیز کے طور پر جسے آپ tune کرتے ہیں، derive نہیں۔ MIT 6.390 notes classification سے پہلے gradient descent رکھتے ہیں، جیسے یہ course کرتا ہے اور اسی وجہ سے۔
حوالہ جات
اس حصے کا لنک: حوالہ جات-
LeCun, Y., Bottou, L., Orr, G. B. and Müller, K.-R. Efficient BackProp, in Neural Networks: Tricks of the Trade (Springer, 1998), pp. 9–50. Section 4.3 recommendation دیتا ہے اور section 5.1 وہ argument جو اوپر detail box میں use ہوا: inputs کو centring اور scaling کرنا second-derivative matrix کے eigenvalues بدلتا ہے، اور therefore steps کی تعداد، نہ کہ صرف numerical comfort۔ ↩
-
Dauphin, Y. N., Pascanu, R., Gulcehre, C., Cho, K., Ganguli, S. and Bengio, Y. Identifying and attacking the saddle point problem in high-dimensional non-convex optimization, arXiv:1406.2572 (2014). یہ argument کہ high dimensions میں critical points overwhelmingly local minima کے بجائے saddles ہوتے ہیں، کیونکہ minimum کے لیے thousands of directions میں سے ہر ایک کو ایک ساتھ upward curve کرنا پڑتا ہے۔ ↩
-
Robbins, H. and Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), pp. 400–407 (1951). وہ paper جس نے establish کیا کہ gradient کا noisy estimate کافی ہے، بشرطیکہ step size right way میں shrink ہو۔ ↩
-
Polyak, B. T. Some methods of speeding up the convergence of iteration methods. USSR Computational Mathematics and Mathematical Physics 4(5), pp. 1–17 (1964). heavy-ball method، جو اوپر momentum update ہے، backpropagation کے اس field تک پہنچنے سے بائیس سال پہلے۔ ↩