Ebook Robotics · RL–UAV
Lecture 22 — Convolutional Neural Networks (CNN)
Chương D** · encoder ảnh chuẩn — vì sao không trải phẳng mọi pixel vào MLP
Chế độ Slide · phím ← → · F toàn màn · Esc về đọc · S mở slide
Chương D** · encoder ảnh chuẩn — vì sao không trải phẳng mọi pixel vào MLP
Chương D · encoder ảnh chuẩn — vì sao không trải phẳng mọi pixel vào MLP
| # | Câu hỏi | Trả lời ngắn |
|---|---|---|
| 1 | Tại sao cần? | MLP trên pixel phẳng tốn tham số, phá cấu trúc cục bộ, khó học cạnh→vật. |
| 2 | So với cái khác? | Vs MLP: weight sharing, receptive field tăng theo độ sâu. Vs ViT: CNN vẫn phổ biến khi data/latency hạn chế trên drone. Vs handcraft: học feature thay viết tay. |
| 3 | Giải quyết gì & thế nào? | Conv+pool xếp tầng cạnh→bộ phận→vật; head detect/policy; chia sẻ trọng số. |
| 4 | Kết quả ra sao? | Encoder cho Lab 4 / image-based RL; feature map / embedding cho bbox, depth thô, hoặc \(\pi(z_{\text{img}})\). |
| 5 | Nên dùng khi nào? | Ảnh làm obs; freeze pretrained + train head khi ít sample; coverage xác nhận bằng seg. |
| 6 | Không nên khi nào? | Backbone quá nặng phá FPS vòng điều khiển; state thấp chiều đã đủ; aug phá tín hiệu horizon/trọng lực. |
🖼️ Hình nhanh: Conv nhìn cục bộ + chia sẻ lọc; sâu hơn → “cửa sổ” lớn hơn (receptive field).
```
Ảnh conv 3×3 conv+pool head
┌────┐ cạnh/texture bộ phận class/bbox/π
│····│ ──► [████] ─────► [────────] ─────► (actor/critic)
│·██·│ RF nhỏ RF lớn
└────┘MLP phẳng: mỗi pixel ↔ mọi trọng số → ★ nổ tham số, mất tính cục bộ
CNN: cùng bộ lọc trượt khắp ảnh → ít tham số, đẳng biến tịnh tiến ≈
```🇻🇳 Chuyện thật (sân A): Weight sharing = cùng một kính lúp trượt trên ảnh luống chè — cạnh lá / khoảng trống được nhận cùng một bộ lọc dù nằm góc nào của khung hình.
MLP trải phẳng thì mỗi vị trí pixel có “kính” riêng: nổ tham số, mất tính cục bộ, khó học khi data drone vốn ít.
Chốt: CNN là inductive bias đúng cho ảnh phủ / detect trước khi gắn head policy.../00C.
Hình gốc hoặc minh họa cho ebook — không cắt từ slide Princeton. Dùng Present: bật Slide · F toàn màn.
Nhận mặt người: trước hết thấy cạnh mắt/mũi, sau mới ghép thành “đó là An”.
CNN bắt chước sự xếp tầng đó: lọc cục bộ → khái niệm lớn dần theo độ sâu.
Nhận diện ổ gà trên đường: bạn dùng cùng một “mẫu nhìn” ở mọi chỗ trên ảnh — đó là weight sharing. Không cần học lại từ đầu cho góc trên-trái và dưới-phải.
Với ảnh đồi chè từ UAV: lớp nông bắt ranh hàng / texture lá; lớp sâu bắt “khối hàng chưa phủ” hay “vật cản”. Nếu bạn flatten 84×84×3 vào MLP, mạng phải tự học lại rằng pixel cạnh nhau liên quan — vừa tốn mẫu vừa dễ overfit (Lec 21).
| Tính chất | CNN (conv) | MLP trên pixel phẳng |
|---|---|---|
| Tham số | Lọc nhỏ, chia sẻ khắp ảnh | \(O(\text{H·W·C·d})\) rất lớn |
| Cấu trúc cục bộ | Có — kernel nhìn lân cận | Không — phải học từ đầu |
| Tịnh tiến | Gần đẳng biến / equivariant | Phá khi vật dịch trừ khi data đủ |
| Receptive field | Tăng theo tầng | “Toàn ảnh” ngay nhưng hỗn loạn |
\[ (I * k)(x,y) = \sum_{i,j} I(x+i,y+j)\,k(i,j) \]
ảnh H×W×3
│
▼
[conv + ReLU] × N ← cạnh, gradient cục bộ (RF nhỏ)
│
▼
pool / stride ← RF tăng, độ phân giải giảm
│
▼
[conv + ReLU] × M ← bộ phận / texture hàng chè (RF lớn)
│
▼
head: class | bbox | depth | π_θ (± V_φ)
| Thao tác | Ảnh hưởng RF (ý tưởng) | Ý nghĩa robot |
|---|---|---|
| Thêm conv \(k\times k\) | RF tăng ~ \(k-1\) (stride 1) | Cạnh → texture |
| Stride / pool 2 | RF (theo ảnh gốc) tăng nhanh | Thấy vật lớn hơn |
| Dilation | RF lớn không tăng số tham số tương ứng | Cảnh rộng, ít params |
Thực dụng: YOLO / Faster R-CNN (detection), U-Net / DeepLab (segmentation). Trên Crazyflie-class: mạng thường chạy trên laptop/companion (≥ ~30 Hz ở Lab 4), không phải MCU bay.
Ảnh 64×64, ẩn 128:
MLP 1 lớp: 64*64 * 128 ≈ 524k trọng số (chỉ một lớp!)
Conv 3×3, 32 kênh: 3*3*3*32 ≈ 864 trọng số / lớp (RGB→32)
★ CNN thắng vì chia sẻ — không vì “thần kỳ deep learning”.
| Tính chất CNN | Ý nghĩa với UAV của bạn |
|---|---|
| Local connectivity | cạnh luống, texture chè, vật cản cục bộ |
| Weight sharing | vật / khoảng trống xuất hiện mọi nơi trên ảnh |
| Hierarchy | từ cạnh → hàng chè / tòa nhà → scene coverage |
"""
Demo Lec22: (1) đếm tham số MLP vs conv;
(2) hiện tượng: lọc cạnh 3×3 cho đáp ứng dịch khi ảnh dịch — tinh thần equivariance.
"""
import numpy as np
H = W = 64
mlp_in = H * W
mlp_hidden = 128
mlp_params = mlp_in * mlp_hidden + mlp_hidden # +bias
conv_params = 3 * 3 * 1 * 32 + 32 # 1 kênh → 32, +bias
print("Tham số MLP một lớp ~", mlp_params)
print("Tham số conv 3×3×32 ~", conv_params)
print("Tỉ lệ MLP/conv ~", round(mlp_params / conv_params, 1))
# Ảnh có một cạnh dọc; dịch sang phải
img = np.zeros((7, 7))
img[:, 2] = 1.0
img_shift = np.zeros_like(img)
img_shift[:, 3] = 1.0
# Lọc gradient ngang Sobel-ish
k = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]], dtype=float)
def conv2d_valid(x, k):
kh, kw = k.shape
out = np.zeros((x.shape[0] - kh + 1, x.shape[1] - kw + 1))
for i in range(out.shape[0]):
for j in range(out.shape[1]):
out[i, j] = np.sum(x[i:i+kh, j:j+kw] * k)
return out
r0 = conv2d_valid(img, k)
r1 = conv2d_valid(img_shift, k)
# So khớp: đáp ứng gốc dịch 1 cột có gần đáp ứng ảnh dịch không?
r0_shifted = np.zeros_like(r1)
r0_shifted[:, 1:] = r0[:, :-1]
err = np.mean(np.abs(r1 - r0_shifted))
print("||resp(shift(img)) - shift(resp(img))|| ~", round(float(err), 6))
print("→ Conv: dịch ảnh ≈ dịch feature (trong vùng hợp lệ). MLP phẳng không có sẵn.")
🧪 Kỳ vọng demo:
- MLP một lớp có ~ hàng trăm nghìn tham số; conv 3×3×32 chỉ ~ hàng trăm–nghìn.
- Sai số equivariance gần 0 trên ví dụ cạnh dịch — minh họa vì sao CNN “hiểu” tịnh tiến.
- Kết luận: ảnh cần inductive bias cục bộ trước khi đổ sample RL.
| Thiết kế | Khi nào chọn |
|---|---|
| Freeze CNN + RL head | Ít sample, có pretrained gần domain |
| Fine-tune nhẹ encoder | Domain drone khác ImageNet rõ |
| Train end-to-end từ đầu | Data/sim cực nhiều; đã có baseline |
| Không dùng CNN | Obs đã là \(\hat{x}\)+goal / tia khoảng cách đủ task |
| ✅ Nên | ❌ Không nên | |
|---|---|---|
| CNN encoder | Obs ảnh / depth map | Ép CNN khi obs đã là vector 10 chiều |
| Freeze pretrained | Ít episode RL | Domain lệch hoàn toàn mà không đánh giá lại |
| Backbone lớn (SOTA detect) | Offline / companion mạnh | Vòng điều khiển chặt trên MCU / Pi yếu |
| Nghĩa phủ / năng lượng / gió | Seg coverage + policy nhẹ | Mạng nặng → phải bay chậm / chờ suy luận → tốn pin |
⚡ Nhớ một câu: Ảnh cần lọc cục bộ chia sẻ trọng số — CNN mua inductive bias bằng ít tham số; RF phải đủ lớn cho task.
🔗 Sang bài sau mang theo: Đủ dynamics–plan–estimate–vision → Lec 23 đặt RL đúng tầng trong stack và chốt pipeline nghiên cứu.
Trước: Lec21 — Overfitting · Sau: Lec23 — RL trong Robotics