Nhập môn Reinforcement Learning: Kỷ nguyên Deep RL - Phá đảo Discrete với DQN và Continuous với DDPG
Chào mọi người, sau 9 tập ròng rã cày cuốc với các nền tảng toán học, Tabular methods (Q-Table) và Policy Gradient cơ bản, hôm nay chúng ta chính thức bước sang một trang sử mới: Deep Reinforcement Learning (Deep RL).
Nhớ lại bài toán Q-Learning, chúng ta dùng một cái bảng để lưu giá trị $Q(s, a)$. Nhưng nếu môi trường là một bức ảnh game (như Atari) với hàng triệu pixel, số lượng State sẽ lớn hơn cả số nguyên tử trong vũ trụ. Cái bảng của chúng ta sẽ tràn RAM ngay lập tức. Đây chính là "Curse of Dimensionality" (Lời nguyền không gian đa chiều).
Giải pháp? Thay vì dùng bảng, ta sẽ dùng Neural Networks làm công cụ xấp xỉ hàm (Function Approximator). Thay vì tìm chính xác $q_(s,a)$, ta sẽ đi tìm một hàm xấp xỉ được tham số hóa bởi bộ weights $\theta$: $\hat{q}(s, a, \theta) \approx q_(s, a)$.
Bắt đầu từ bài này, mỗi tập tôi sẽ giới thiệu 2 thuật toán song song: một chuyên trị Discrete Action Space (Rời rạc) và một chuyên trị Continuous Action Space (Liên tục) để các bạn thấy rõ sự khác biệt trong tư duy toán học và thiết kế kiến trúc.
Hôm nay, chúng ta sẽ mổ xẻ 2 thuật toán nền móng của Deep RL: DQN và DDPG.
1. Vua của Discrete Control: Deep Q-Networks (DQN)
Năm 2013, DeepMind tung ra một paper chấn động giới AI: Dùng một mạng CNN chơi các trò Atari (chỉ nhìn vào điểm ảnh pixel) mà thắng được cả con người. Cốt lõi của AI đó chính là DQN. Thuật toán này sinh ra để giải quyết các môi trường Discrete Action Space.
1.1 Ví dụ thực tế: Flappy Bird
Hãy tưởng tượng bạn train AI chơi Flappy Bird.
- State ($S_t$): Bạn không thể dùng 1 frame ảnh làm state, vì 1 tấm ảnh tĩnh không cho biết con chim đang bay lên hay rớt xuống. DQN thường stack 4 frames liên tiếp lại thành 1 tensor để làm State.
- Action ($A_t$): Chỉ có 2 hành động:
[0: Không làm gì, 1: Nhấn Space để nhảy]. - Mạng DQN sẽ nhận input là State (4 frames ảnh) đi qua các lớp Convolution, và đẻ ra một output layer gồm đúng 2 node, chứa giá trị dự đoán: $[Q(s, 0), Q(s, 1)]$. Agent chỉ việc lấy $\arg\max_a$ để ra quyết định.
(Kiến trúc của DQN: State đi vào, Q-values của từng Action đi ra)
1.2 Hai "Trick" thần thánh của DQN
Nếu nhét thẳng Neural Network vào phương trình update của Q-Learning, quá trình training sẽ sụp đổ (diverge). Tại sao?
- Thứ nhất: Data sinh ra từ quá trình chơi game có tính liên kết thời gian cực chặt (frame sau gần y hệt frame trước). Nó vi phạm giả định i.i.d (độc lập và phân phối đồng nhất) của Stochastic Gradient Descent (SGD).
- Thứ hai: Hàm mục tiêu (Target) luôn di chuyển. Đang update weights để đuổi theo Target, thì chính cái Target đó cũng bị thay đổi do xài chung một bộ weights.
DeepMind xử lý bằng 2 vũ khí chí mạng:
1. Experience Replay (Bộ nhớ kinh nghiệm) DQN gom các trải nghiệm $(S_t, A_t, R_{t+1}, S_{t+1})$ ném vào một cái buffer khổng lồ $\mathcal{D}$. Khi train, nó bốc ngẫu nhiên (random mini-batch) từ buffer này ra để học. Toán học: Việc sample ngẫu nhiên phá vỡ correlation giữa các data points, đưa bài toán về dạng i.i.d, giúp mảng Loss function cực kỳ ổn định.
2. Target Network (Mạng mục tiêu bị đóng băng) DQN tạo ra 2 mạng Neural giống hệt nhau:
- Main Network ($Q$ với weights $\theta$): Dùng để chọn action và được update liên tục bằng gradient descent.
- Target Network ($\hat{Q}$ với weights $\theta^-$): Dùng để tính toán giá trị Target $y_i$. Mạng này bị đóng băng, và chỉ copy weights từ Main Network sang sau mỗi $C$ steps.
Hàm Loss của DQN (Mean Squared Error): $$ L_i(\theta_i) = \mathbb{E}{(s,a,r,s') \sim U(\mathcal{D})} \left[ \left( \underbrace{r + \gamma \max{a'} \hat{Q}(s', a'; \theta_i^-)}{\text{Target } y_i} - \underbrace{Q(s, a; \theta_i)}{\text{Prediction}} \right)^2 \right] $$
1.3 Pseudocode của DQN
Khởi tạo Replay Buffer D với dung lượng N.
Khởi tạo Main Action-Value function Q với weights ngẫu nhiên θ.
Khởi tạo Target Action-Value function Q^ với weights θ^- = θ.
Lặp cho mỗi episode = 1 tới M:
Khởi tạo trạng thái ban đầu s_1 (có thể cần tiền xử lý ảnh)
Lặp cho mỗi step t = 1 tới T:
// 1. Chọn hành động (Epsilon-Greedy)
Với xác suất ε chọn hành động a_t ngẫu nhiên.
Ngược lại, chọn a_t = argmax_a Q(s_t, a; θ).
// 2. Tương tác môi trường
Thực hiện a_t, nhận reward r_t và state tiếp theo s_{t+1}.
Lưu transition (s_t, a_t, r_t, s_{t+1}) vào D.
// 3. Huấn luyện (Học từ quá khứ)
Sample ngẫu nhiên một mini-batch các transitions (s_j, a_j, r_j, s_{j+1}) từ D.
Nếu s_{j+1} là terminal state:
y_j = r_j
Ngược lại:
y_j = r_j + γ * max_{a'} Q^(s_{j+1}, a'; θ^-) // Tính bằng Target Network
Thực hiện Gradient Descent trên hàm Loss (y_j - Q(s_j, a_j; θ))^2 theo bộ weights θ.
// 4. Update Target Network
Sau mỗi C steps, reset weights mạng Target: θ^- ← θ.
2. Bước tiến tới Continuous Control: DDPG (Deep Deterministic Policy Gradient)
DQN cực kỳ đỉnh, nhưng nó không thể hoạt động trong môi trường Continuous Action Space.
Hãy thử nghĩ xem: Trong DQN, để tính Target, ta phải tính $\max_{a'} Q(s', a')$. Nếu Action Space là rời rạc (4-5 nút bấm), tìm max rất dễ (chỉ cần chạy qua 5 giá trị rồi lấy số lớn nhất). Nhưng nếu Action Space là một số thực liên tục (ví dụ: góc bẻ lái vô lăng từ -1.0 đến 1.0, góc xoay khớp robot), làm sao để tìm max của hàm $Q$ tại MỖI STEP? Nó biến thành một bài toán Tối ưu hóa phi tuyến tính cồng kềnh và đắt đỏ vô cùng.
Giải pháp: Ta dùng một mạng Actor riêng biệt để xấp xỉ trực tiếp cái hàm $\arg\max_a$. Đó là cơ sở ra đời của thuật toán DDPG (Deep Deterministic Policy Gradient). DDPG là một thuật toán Actor-Critic dành riêng cho không gian liên tục.
2.1 Ví dụ thực tế: Điều khiển xe tự lái
- State ($S_t$): Tốc độ xe, khoảng cách tới làn đường, góc của xe.
- Action ($A_t$): Không phải là nút bấm nữa. Ở đây Action là một vector số thực liên tục:
[Góc bẻ lái (-1.0 tới 1.0), Lực đạp ga (0.0 tới 1.0), Lực phanh (0.0 tới 1.0)]. DDPG sẽ xuất thẳng ra các con số thực này để điều khiển xe một cách mượt mà nhất.
2.2 Kiến trúc Actor-Critic của DDPG
DDPG dùng tới 4 mạng Neural (2 mạng chính + 2 Target Networks):
1. Mạng Actor $\mu(s|\theta^\mu)$:
- Nhận input là State $s$, nó trực tiếp output ra một vector giá trị thực đại diện cho action (Deterministic - Xác định).
2. Mạng Critic $Q(s, a|\theta^Q)$:
- Nhận input là State $s$ VÀ Action $a$ (được đẻ ra từ Actor). Output là giá trị $Q(s,a)$ để đánh giá xem hành động đó tốt tới đâu.
(Kiến trúc DDPG: Actor xuất ra Action, Critic nhận cả State và Action để chấm điểm Q)
2.3 Giải phẫu quá trình Update của DDPG
DDPG thừa hưởng Replay Buffer từ DQN, nhưng cách nó update Target Network và Actor phức tạp hơn nhiều.
1. Update Critic (Đứa chấm điểm): Critic học giống hệt DQN bằng cách tối thiểu hóa Mean Squared Error: $$ L_{Critic} = \frac{1}{N} \sum_i \left( y_i - Q(s_i, a_i | \theta^Q) \right)^2 $$ Với Target $y_i = r_i + \gamma Q'(s_{i+1}, \mu'(s_{i+1} | \theta^{\mu'}) | \theta^{Q'})$. (Chú ý: Action cho state tiếp theo được sinh ra từ Target Actor $\mu'$, sau đó nhét vào Target Critic $Q'$).
2. Update Actor (Đứa thi tuyển - Ứng dụng Chain Rule): Mục tiêu của Actor là chỉnh weights $\theta^\mu$ sao cho output action của nó làm tối đa hóa giá trị $Q(s, a)$ mà Critic đánh giá. Định lý Deterministic Policy Gradient chỉ ra rằng ta có thể áp dụng quy tắc đạo hàm hàm hợp (Chain Rule) để tính gradient cho Actor: $$ \nabla_{\theta^\mu} J \approx \frac{1}{N} \sum_i \left[ \nabla_a Q(s, a | \theta^Q)|{a=\mu(s_i)} \cdot \nabla{\theta^\mu} \mu(s | \theta^\mu)|_{s_i} \right] $$
- $\nabla_{\theta^\mu} \mu(s | \theta^\mu)$: Đạo hàm của Actor đối với weights của nó.
- $\nabla_a Q(s, a | \theta^Q)$: Đạo hàm của Critic đối với cái action đầu vào. Diễn giải thực tế: Critic bảo "Này Actor, mày chỉnh action tăng lên 1 tí thì Q-value sẽ cao hơn đấy" (thể hiện qua gradient của Critic theo action). Dòng gradient này sẽ chảy ngược từ Critic xuyên qua Action, truyền thẳng vào trong Actor để nó tự điều chỉnh weights của mình. Đây là sự kỳ diệu của Backpropagation kết hợp Actor-Critic!
3. Soft Target Updates (Chiêu bài ổn định hệ thống): Thay vì đóng băng Target Network và update 1 cục lớn sau $C$ bước như DQN, DDPG dùng một hệ số $\tau \ll 1$ (thường $\tau = 0.001$) để "nhỏ giọt" weights từ Main Network sang Target Network ở mỗi step: $$ \theta^{Q'} \leftarrow \tau\theta^Q + (1-\tau)\theta^{Q'} $$ $$ \theta^{\mu'} \leftarrow \tau\theta^\mu + (1-\tau)\theta^{\mu'} $$ Kỹ thuật Polyak Averaging này làm cho Target Network biến đổi cực kỳ chậm và mượt, giúp quá trình học ổn định hơn rất nhiều.
4. Exploration bằng Noise: Vì Actor là Deterministic (cùng 1 state luôn đẻ ra 1 action giống hệt), DDPG cần cộng thêm Nhiễu (Noise - $\mathcal{N}$) vào quá trình chọn action khi train để ép Agent đi khám phá: $$ a_t = \mu(s_t | \theta^\mu) + \mathcal{N}_t $$
2.4 Pseudocode của DDPG
Khởi tạo mạng Critic Q(s,a|θ^Q) và Actor μ(s|θ^μ) với weights ngẫu nhiên.
Khởi tạo Target Networks Q' và μ' với weights copy từ mạng chính: θ^Q' = θ^Q, θ^μ' = θ^μ.
Khởi tạo Replay Buffer R.
Lặp cho mỗi episode:
Khởi tạo nhiễu ngẫu nhiên N để explore.
Nhận trạng thái ban đầu s_1.
Lặp cho mỗi step t = 1 tới T:
// Chọn hành động có cộng nhiễu
Chọn hành động a_t = μ(s_t|θ^μ) + N_t
Thực hiện a_t, nhận reward r_t và trạng thái mới s_{t+1}.
Lưu transition (s_t, a_t, r_t, s_{t+1}) vào Buffer R.
// Sample data
Sample 1 mini-batch N transitions (s_i, a_i, r_i, s_{i+1}) từ R.
// 1. Cập nhật Critic
y_i = r_i + γ * Q'(s_{i+1}, μ'(s_{i+1}|θ^μ') | θ^Q')
Update Critic bằng cách minimize Loss: L = 1/N * Σ(y_i - Q(s_i, a_i|θ^Q))^2
// 2. Cập nhật Actor (Dùng Chain Rule)
Update Actor policy bằng sampled policy gradient:
∇_θ^μ J ≈ 1/N * Σ [ ∇_a Q(s, a|θ^Q)|_{s=s_i, a=μ(s_i)} * ∇_θ^μ μ(s|θ^μ)|_{s_i} ]
// 3. Cập nhật Target Networks (Soft Update)
θ^Q' ← τ * θ^Q + (1 - τ) * θ^Q'
θ^μ' ← τ * θ^μ + (1 - τ) * θ^μ'
3. Tổng kết
Nhìn vào DQN và DDPG, ta thấy rõ sự khác biệt trong tư duy giải quyết 2 loại action space khi đối mặt với không gian lớn:
| Đặc điểm | DQN | DDPG |
|---|---|---|
| Action Space | Rời rạc (Discrete) | Liên tục (Continuous) |
| Bản chất | Value-based thuần túy | Actor-Critic (Deterministic Policy Gradient) |
| Hành vi Policy | $\epsilon$-greedy | Deterministic + Thêm Noise |
| Update Target | Hard Update (Đóng băng, copy 1 cục sau C steps) | Soft Update (Polyak Averaging, update từ từ) |
Sự ra đời của DDPG là một bước tiến vĩ đại đưa Deep RL vào mảng Robotics và điều khiển tự động. Tuy nhiên, nếu bạn đã từng code DDPG, bạn sẽ nhận ra nó cực kỳ "đỏng đảnh". Nó nổi tiếng là nhạy cảm với hyperparameters, dễ bị vỡ Gradient, và Q-values thường bị overestimation (đánh giá quá cao) dẫn tới sụp đổ hệ thống.
Đó là lý do các nhà nghiên cứu tiếp tục cải tiến để đẻ ra những con quái vật ổn định hơn và mạnh mẽ hơn nhiều lần. Ở tập sau, chúng ta sẽ chứng kiến sự thống trị của các thuật toán State-of-the-Art mạnh nhất hiện nay: PPO (Vua của sự Ổn định) và SAC (Vua của Continuous Control với Maximum Entropy).
Cảm ơn các bạn đã theo dõi!
References:
- Mnih et al. (2015). Human-level control through deep reinforcement learning (DQN)
- Lillicrap et al. (2016). Continuous control with deep reinforcement learning (DDPG)