3.3.2 · HinglishDeep Learning Frameworks

Autograd and computational graphs in PyTorch

3,659 words17 min readRead in English

3.3.2 · AI-ML › Deep Learning Frameworks

Overview

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.

Figure — Autograd and computational graphs in PyTorch

Core Concepts

Autograd Kaise Kaam Karta Hai: Step-by-Step Derivation

Step 1: Forward Pass aur Graph Construction

Jab aap requires_grad=True wale tensors par operations perform karte hain, PyTorch unhe record karta hai:

import torch
 
x = torch.tensor([2.0], requires_grad=True)
y = torch.tensor([3.0], requires_grad=True)
 
z = x * y + x**2  # z = 3x + x²

Internally kya hota hai:

  • x * y ek node create karta hai grad_fn=<MulBackward> ke saath
  • x**2 ek node create karta hai grad_fn=<PowBackward> ke saath
  • + inhe grad_fn=<AddBackward> ke saath combine karta hai
  • z ab z.grad_fn = <AddBackward> ke saath poore graph ki taraf point karta hai

Yeh kyun matter karta hai: Graph structure operations ki chain encode karta hai, jo exactly wahi hai jo humein chain rule ke liye chahiye.

Step 2: Backward Pass aur Chain Rule

Chain rule kehta hai: agar , toh .

Hamare example ke liye:

First principles se Derivation:

Derivative ki definition se shuru karte hain:

Yeh step kyun? Hum function ko par expand karte hain, terms cancel karte hain, factor out karte hain, aur limit lete hain. Yahi derivative ki fundamental definition hai.

PyTorch ise automate karta hai:

z.backward()  # Compute dz/dx and dz/dy
print(x.grad)  # tensor([8.]) = 3+ 2*2
print(y.grad)  # tensor([2.]) = 2

Step 3: Gradient Accumulation

Default se, .backward() call karna gradients ko .grad mein accumulate karta hai:

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:

Gradient hai:

Agar hum har sample ke liye alag compute karte hain, toh humein unhe sum karna hoga. Accumulation is sum ko automatically implement karta hai.

Detailed Examples

Common Mistakes

Dynamic vs Static Graphs

The .grad_fn Chain

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 * 2
z = y + 3
 
print(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)  # True
print(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.

Advanced: torch.no_grad() aur Inference Mode

Inference ke dauran gradients ki zaroorat nahi hoti. Autograd disable karne se memory bachti hai aur computation fast hota hai:

with torch.no_grad():
    output = model(x)  # No graph built

Yeh kyun kaam karta hai: PyTorch grad_fn assignment skip karta hai, jis se overhead khatam ho jaata hai.

Mathematical insight: Inference mein sirf forward pass chahiye:

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.

Memory Management

Strategies:

  1. Gradient checkpointing: Backward pass ke dauran intermediate activations recompute karo (memory ke liye compute trade karo)
  2. Graphs use ke baad delete karo: PyTorch ka default (graphs .backward() ke baad free ho jaate hain)
  3. Unnecessary tensors detach karo: Jahan zaroorat nahi, wahan gradients rok lo

Memory cost ka formula: jahan = number of layers, = activation size. Gradient checkpointing isse tak reduce karta hai compute ki cost par.

Active Recall Exercises

Recall Ek 12-Saal Ke Bachche Ko Samjhao

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!

Connections

  • 3.301-Introduction-to-PyTorch-tensors-and-operations - Tensors ki foundation jis par autograd operate karta hai
  • 3.2.04-Backpropagation-algorithm - Woh mathematical algorithm jo autograd implement karta hai
  • 3.4.01-Building-neural-networks-with-torch.nn.Module - Models train karne ke liye autograd use karta hai
  • 3.5.02-Gradient-descent-variants - Optimizers jo autograd ke computed gradients consume karte hain
  • 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 compute karta hai jahan 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.
In-place operations (jaise +=) kabhi kabhi autograd kyun tod dete hain?
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 ke liye chain rule formula kya hai?
. 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.

ko limit definition se derive karo ::

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: . 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?
jahan operations/layers ki sankhya hai aur activations ka size hai. Har operation backward pass ke liye inputs aur metadata store karta hai. Gradient checkpointing isse tak reduce karta hai activations recompute karke.

Concept Map

builds

is a

nodes are

enables

triggers tracking by

records ops into

each op stores

traverses graph via

computes

stored in

built dynamically as

Autograd System

Computational Graph

Directed Acyclic Graph

Tensors and Operations

Automatic Differentiation

requires_grad True

Forward Pass

grad_fn

backward call

Chain Rule

Gradients

grad attribute

Define-by-Run