PyTorch ka autograd system woh engine hai jo automatic differentiation ko power karta hai—yeh tensors par operations ko track karta hai aur gradients automatically compute karta hai. Isse backpropagation ke dauran manual derivative calculations ki zaroorat nahi rehti, jis se deep learning research fast aur error-free ban jaati hai.
Chain rule kehta hai: agar z=f(g(x)), toh dxdz=dgdz⋅dxdg.
Hamare example z=xy+x2 ke liye:
dxdz=∂x∂(xy)+∂x∂(x2)=y+2x
dydz=∂y∂(xy)+∂y∂(x2)=x+0=x
First principles se Derivation:
Derivative ki definition se shuru karte hain:
dxdz=limh→0hz(x+h,y)−z(x,y)
=limh→0h[(x+h)y+(x+h)2]−[xy+x2]
=limh→0hxy+hy+x2+2xh+h2−xy−x2
=limh→0hhy+2xh+h2=limh→0(y+2x+h)=y+2x
Yeh step kyun? Hum function ko x+h par expand karte hain, terms cancel karte hain, h factor out karte hain, aur limit lete hain. Yahi derivative ki fundamental definition hai.
Default se, .backward() call karna gradients ko .grad mein accumulate karta hai:
tensor.grad←tensor.grad+∂tensor∂L
Accumulation kyun? Mini-batch training mein, weights update karne se pehle aap multiple samples ke gradients sum karte hain. Lekin iska matlab hai aapko iterations ke beech gradients zero karne padte hain:
x.grad.zero_() # Clear previous gradients
Derivation ki accumulation kyun zaroori hai:
Batch gradient descent mein, loss hai:
Lbatch=N1∑i=1NLi
Gradient hai:
∂w∂Lbatch=N1∑i=1N∂w∂Li
Agar hum har sample ke liye ∂w∂Li alag compute karte hain, toh humein unhe sum karna hoga. Accumulation is sum ko automatically implement karta hai.
Kisi operation se bane har tensor mein us function ka reference store hota hai jisne use banaya:
x = torch.tensor([1.0], requires_grad=True)y = x * 2z = y + 3print(y.grad_fn) # <MulBackward0>print(z.grad_fn) # <AddBackward0>print(z.grad_fn.next_functions) # Shows MulBackward0
Yahi chain computational graph hai. grad_fn pointers ko backward follow karne se poora computation reconstruct ho jaata hai.
Leaf tensors (user ne banaye, operations se nahi) ka grad_fn=None aur is_leaf=True hota hai:
print(x.is_leaf) # Trueprint(y.is_leaf) # False (created by operation)
Yeh kyun matter karta hai: By default sirf leaf tensors mein gradients store hote hain. Intermediate gradients free ho jaate hain jab tak aap retain_grad() call nahi karte.
∂θ∂L compute karne ki zaroorat nahi, toh koi graph nahi chahiye.
Inference mode (newer, faster):
with torch.inference_mode(): output = model(x)
Difference: inference_mode() zyada aggressive hai—andar banaye gaye tensors baad mein gradient computation mein use nahi ho sakte (context se bahar bhi). Pure inference ke liye use karo; agar baad mein gradients chahiye ho toh no_grad() use karo.
Gradient checkpointing: Backward pass ke dauran intermediate activations recompute karo (memory ke liye compute trade karo)
Graphs use ke baad delete karo: PyTorch ka default (graphs .backward() ke baad free ho jaate hain)
Unnecessary tensors detach karo: Jahan zaroorat nahi, wahan gradients rok lo
Memory cost ka formula:Memory≈O(N⋅S)
jahan N = number of layers, S = activation size. Gradient checkpointing isse O(N⋅S) tak reduce karta hai 2× compute ki cost par.
Socho tum LEGO blocks se ek bahut unchi tower bana rahe ho. Har baar jab tum ek block rakhte ho, tum ek kagaz par likhte ho: "Maine block #5 ko block #3 ke upar rakha." Woh notes ki list tumhara computational graph hai—yeh record hai ki tumne tower kaise banaya.
Ab, end mein koi tumhe kehta hai, "Tower 2 inch zyada unchi hai." Tumhe pata karna hai ki kaunse blocks hatane hain. Tum upar se peeche kaam karte ho: "Agar main yeh block hatata hoon, tower 1 inch choti ho jaati hai. Agar neeche wala hatata hoon, ek aur inch chhoti hoti hai." Yahi backpropagation hai—apne notes mein backward jaana yeh dekhne ke liye ki har piece ne final height mein kitna contribute kiya.
PyTorch ka autograd ek robot ki tarah hai jo automatically woh notes likhta hai aur calculate karta hai ki har block change karne se tower ki height par kya asar padega. Tum bas banao (forward pass), aur robot changes figure out kar leta hai (backward pass) tumhare liye!
4.2.03-Batch-normalization - Layer jiske running stats ko carefully handle karna padta hai (graph se detach)
5.3.01-Transfer-learning - Fine-tuning mein control karna hota hai ki kaun se layers mein requires_grad ho
6.4.02-Gradient-checkpointing - Deep networks ke liye advanced memory optimization technique
#flashcards/ai-ml
PyTorch mein computational graph kya hota hai? :: Ek directed acyclic graph (DAG) jahan nodes tensors/operations hain aur edges data flow hain. PyTorch ise forward pass ke dauran dynamically build karta hai aur backward pass mein chain rule se gradients compute karne ke liye use karta hai.
requires_grad=True kya karta hai?
Ek tensor ko gradient tracking ke liye mark karta hai. PyTorch aise tensors par saare operations record karta hai, computational graph banata hai jo backpropagation ke dauran automatic differentiation enable karta hai.
Har training iteration se pehle optimizer.zero_grad() call kyun karna chahiye?
PyTorch by default gradients accumulate karta hai (naye gradients existing .grad values mein add karta hai). Zero kiye bina, pichli iterations ke gradients galat tarike se jud jaate hain, jis se parameter updates galat ho jaate hain.
torch.no_grad() aur torch.inference_mode() mein kya fark hai?
Dono gradient tracking disable karte hain. no_grad() tensors ko baad mein gradient computation mein use karne deta hai (context se bahar nikalne ke baad). inference_mode() zyada aggressive hai—andar banaye gaye tensors baad mein autograd mein participate nahi kar sakte, lekin pure inference ke liye faster hai.
.backward() ko scalar input kyun chahiye?
Backpropagation ∂x∂L compute karta hai jahan L scalar hai. Vector outputs ke liye, gradient ek Jacobian matrix hogi. Scalar mein reduce karna zaroori hai (sum, mean, ya indexing se) ya gradient argument provide karna padega.
.detach() kya karta hai?
Ek naya tensor create karta hai jo original ke saath data share karta hai lekin requires_grad=False aur grad_fn=None ke saath. Detached tensors ke through gradients flow nahi karte—unhe computational graph mein constants ki tarah treat kiya jaata hai.
grad_fn kya hai?
Us function ka reference jo tensor create karta hai (jaise <MulBackward>, <AddBackward>). Yeh computational graph banata hai—grad_fn pointers ko backward follow karne se backpropagation ke liye operations ka sequence reconstruct hota hai.
Autograd ko correct gradients compute karne ke liye original values chahiye. In-place ops history overwrite kar dete hain. Agar aap ek tensor modify karte hain jo backward pass mein baad mein zaroori hai, toh gradient computation fail ho jaata hai. Training ke dauran out-of-place operations use karo (y += 1 ki jagah y = y + 1).
Computational graph path x→a→b→z ke liye chain rule formula kya hai?
∂x∂z=∂b∂z⋅∂a∂b⋅∂x∂a. Autograd graph ko backward traverse karke, har node par local gradients multiply karke yeh compute karta hai.
retain_graph=True kab use karoge?
Jab aapko ek hi graph par .backward() multiple baar call karna ho (jaise multi-task learning ya adversarial training mein ek forward pass se multiple losses compute karne ke liye). By default, PyTorch memory bachane ke liye pehle .backward() ke baad graph free kar deta hai.
Leaf tensor kya hota hai?
User ne directly banaya tensor (kisi operation ka result nahi). Iska is_leaf=True aur grad_fn=None hota hai. By default sirf leaf tensors gradients store karte hain; intermediate tensors ko gradients rakhne ke liye retain_grad() chahiye.
dxd(x2) ko limit definition se derive karo :: dxd(x2)=limh→0h(x+h)2−x2=limh→0hx2+2xh+h2−x2=limh→0h2xh+h2=limh→0(2x+h)=2x
PyTorch mein by default gradient accumulation kyun hoti hai?
Mini-batch training support karne ke liye jahan aap multiple samples ke gradients sum karte hain: ∂w∂Lbatch=N1∑i=1N∂w∂Li. Accumulation is sum ko implement karta hai. Training iterations ke beech manually zero karna padta hai.
Computational graph store karne ki memory complexity kya hai?
O(N⋅S) jahan N operations/layers ki sankhya hai aur S activations ka size hai. Har operation backward pass ke liye inputs aur metadata store karta hai. Gradient checkpointing isse O(N⋅S) tak reduce karta hai activations recompute karke.