Lecture 15
Department of Intelligent Systems, University of Lahore
This is the last new-content lecture of the course; Week 16 is capstone demos and review only.
For query matrix \(Q\), key matrix \(K\), value matrix \(V\) (each a stack of row vectors, key/query dimension \(d_k\)):
\[ \mathrm{Attention}(Q,K,V) = \mathrm{softmax}\!\left(\frac{QK^{T}}{\sqrt{d_k}}\right)V \]
\[ \mathrm{MultiHead}(Q,K,V) = \mathrm{Concat}(\mathrm{head}_1,\dots,\mathrm{head}_h)\,W^{O}, \quad \mathrm{head}_i = \mathrm{Attention}(QW_i^{Q}, KW_i^{K}, VW_i^{V}) \]
\[ PE_{(pos,2i)} = \sin\!\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right), \qquad PE_{(pos,2i+1)} = \cos\!\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \]
x --> [Multi-Head Attn] --> (+x) --> LayerNorm
--> [Feed-Forward MLP] --> (+) --> LayerNorm --> outimport torch, torch.nn as nn
class MultiHeadSelfAttention(nn.Module):
def __init__(self, d_model=768, n_heads=12):
super().__init__()
self.h, self.dk = n_heads, d_model // n_heads
self.qkv = nn.Linear(d_model, 3 * d_model)
self.proj = nn.Linear(d_model, d_model)
def forward(self, x): # x: (B, N, d_model)
B, N, D = x.shape
qkv = self.qkv(x).reshape(B, N, 3, self.h, self.dk)
q, k, v = qkv.permute(2, 0, 3, 1, 4) # each (B, h, N, dk)
attn = (q @ k.transpose(-2, -1)) / self.dk ** 0.5
attn = attn.softmax(dim=-1)
out = (attn @ v).transpose(1, 2).reshape(B, N, D)
return self.proj(out)This is exactly the block you will build (plus the encoder/decoder stack and masking) in Lab 15.
\[ N = \frac{HW}{P^{2}} \quad \text{patches, each mapped to a } d_{\text{model}}\text{-dim embedding} \]
| Property | CNN | ViT |
|---|---|---|
| Locality prior | Strong (small kernels) | None built-in (learned from data) |
| Translation equivariance | Built-in | Only via learned position embeddings |
| Receptive field growth | Gradual, layer by layer | Global from layer 1 |
| Data efficiency | Good on small/medium data | Needs large-scale pretraining to match CNNs |
| Compute pattern | Convolutions (local, cheap) | Full attention (quadratic in tokens) |
Weaker inductive bias is a double-edged sword: worse from-scratch on small data, better once pretrained on enough of it.
\[ \mathrm{sim}(i, t) = \frac{f_{\text{img}}(i) \cdot f_{\text{txt}}(t)}{\lVert f_{\text{img}}(i) \rVert \, \lVert f_{\text{txt}}(t) \rVert} \]
from transformers import CLIPModel, CLIPProcessor
from PIL import Image
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
proc = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
image = Image.open("scene.jpg").convert("RGB")
labels = ["a cat", "a dog", "a drone"]
inputs = proc(text=labels, images=image, return_tensors="pt", padding=True)
probs = model(**inputs).logits_per_image.softmax(dim=1)[0] # zero-shot scores11_clip_visual_search.py).r = model.predict(frame, conf=0.4, classes=keep, verbose=False)[0]
if len(r.boxes):
x0, y0, x1, y1 = largest_box(r.boxes) # pick the target
err = (x0 + x1) / 2 - frame_center_x
yaw = int(0.15 * err) if abs(err) > 40 else 0 # proportional control
tello.send_rc_control(0, 0, 0, yaw) # act on the detectionabs(err) > 40) — a direct, practical instance of the "fail safe" principle: do nothing rather than jitter on noisy small errors.Cumulative, but weighted toward weeks 10–16:
| Week(s) | Block |
|---|---|
| 10 | Calibration & Stereo |
| 11 | Optical Flow & Tracking |
| 12 | Classical Recognition & Neural Networks |
| 13 | CNNs, Segmentation Networks & Reading Research Papers |
| 14 | Edge Vision & the OpenCV 5.0 Deep Dive |
| 15 | Vision Transformers, Advanced Topics & Review |
| 1–9 | Lighter coverage: image formation through segmentation — know the definitions and the pipeline, not just the deep-learning half |
Intelligent Vision Systems; University of Lahore | Dr. Muhammad Kazim