Thiết lập Gymnasium
Gymnasium cần các phiên bản cụ thể (không phải bản mới nhất) của nhiều chương trình phụ thuộc như NumPy và PyTorch. Vì vậy, khuyến nghị tạo một môi trường Conda hoặc venv mới, hoặc một notebook mới để cài đặt, sử dụng Gymnasium và chạy các chương trình RL.
Bạn có thể dùng sổ tay DataLab này để theo sát hướng dẫn.
Cài đặt Gymnasium
Để cài Gymnasium trên máy chủ hoặc máy cục bộ, chạy:
$ pip install gymnasium
Để cài bằng Notebook như Colab của Google hoặc DataLab của DataCamp, dùng:
!pip install gymnasium
Lệnh trên cài Gymnasium và các phiên bản phụ thuộc phù hợp.
Khám phá các môi trường Gymnasium
Tính đến tháng 11/2024, Gymnasium có hơn 60 môi trường tích hợp. Để duyệt các môi trường sẵn có, dùng hàm gym.envs.registry.all() như minh họa dưới đây:
import gymnasium as gym
for i in gym.envs.registry.keys():
print(i)
Bạn cũng có thể truy cập trang chủ Gymnasium. Cột bên trái có liên kết đến tất cả môi trường. Trang của mỗi môi trường gồm các chi tiết như hành động, trạng thái, v.v.
Các môi trường được phân loại thành các nhóm như Classic Control, Box2D, v.v. Dưới đây là một số môi trường phổ biến trong mỗi nhóm:
- Classic Control: Đây là các môi trường kinh điển dùng trong phát triển RL; là nền tảng cho nhiều ví dụ trong giáo trình. Chúng cân bằng tốt giữa độ phức tạp và đơn giản để kiểm thử, đo chuẩn các thuật toán RL mới. Classic Control trong Gymnasium gồm:
- Acrobot
- Cart Pole
- Mountain Car Discrete
- Mountain Car Continuous
- Pendulum
- Box2D: Box2D là engine vật lý 2D cho trò chơi. Các môi trường dựa trên engine này gồm các trò chơi đơn giản như:
- Lunar Lander
- Car Racing
- ToyText: Đây là các môi trường nhỏ, đơn giản, thường dùng để gỡ lỗi thuật toán RL. Nhiều môi trường dựa trên mô hình lưới nhỏ và các trò bài đơn giản. Ví dụ gồm:
- Blackjack
- Taxi
- Frozen Lake
- MuJoCo: Multi-Joint dynamics with Contact (MuJoCo) là engine vật lý mã nguồn mở mô phỏng môi trường cho robot, sinh cơ học, ML, v.v. Các môi trường MuJoCo trong Gymnasium gồm:
- Ant
- Hopper
- Humanoid
- Swimmer
- Và hơn thế
Ngoài các môi trường tích hợp, Gymnasium có thể dùng với nhiều môi trường bên ngoài với cùng API.
Chúng ta sẽ dùng một môi trường Classic Control kinh điển trong hướng dẫn này. Để nhập một môi trường cụ thể, dùng lệnh .make() và truyền tên môi trường làm đối số. Ví dụ, để tạo môi trường CartPole (phiên bản 1), dùng lệnh dưới đây:
import gymnasium as gym
env = gym.make("CartPole-v1")
Hiểu các khái niệm Reinforcement Learning trong Gymnasium
Tóm lại, Reinforcement Learning gồm một tác tử (như robot) tương tác với môi trường. Một chính sách quyết định hành động của tác tử. Tùy thuộc hành động của tác tử, môi trường cho phần thưởng (hoặc phạt) ở mỗi bước thời gian. Tác tử dùng RL để tìm chính sách tối ưu nhằm tối đa hóa tổng phần thưởng nhận được.
Các thành phần của một môi trường RL
Các thành phần chính của môi trường RL gồm:
- Môi trường: Hệ thống, thế giới, hay ngữ cảnh bên ngoài. Tác tử tương tác với môi trường qua chuỗi bước thời gian. Ở mỗi bước, dựa trên hành động của tác tử, môi trường:
- Đưa ra phần thưởng (hoặc phạt)
- Quyết định trạng thái tiếp theo
- Trạng thái: Biểu diễn toán học của cấu hình hiện tại của môi trường.
- Ví dụ, trạng thái của môi trường con lắc có thể gồm vị trí và vận tốc góc của con lắc tại mỗi bước.
- Trạng thái kết thúc: Trạng thái không dẫn đến trạng thái mới/khác.
- Tác tử: Thuật toán quan sát môi trường và thực hiện các hành động dựa trên quan sát. Mục tiêu của tác tử là tối đa hóa phần thưởng.
- Ví dụ, tác tử quyết định lực đẩy mạnh bao nhiêu và theo hướng nào cho con lắc.
- Quan sát: Biểu diễn toán học về góc nhìn của tác tử đối với môi trường, thu được, ví dụ, qua cảm biến.
- Hành động: Quyết định của tác tử trước khi chuyển sang bước tiếp theo. Hành động ảnh hưởng đến trạng thái tiếp theo của môi trường và mang lại phần thưởng cho tác tử.
- Phần thưởng: Phản hồi từ môi trường đến tác tử. Có thể dương hoặc âm, tùy thuộc hành động và trạng thái của môi trường.
- Lợi tức (Return): Tổng lợi tức kỳ vọng trong các bước thời gian tương lai. Phần thưởng ở tương lai có thể được chiết khấu bằng một hệ số chiết khấu.
- Chính sách (Policy): Chiến lược của tác tử về hành động nào cần thực hiện trong các trạng thái khác nhau. Thường được biểu diễn dưới dạng ma trận xác suất, P, ánh xạ trạng thái sang hành động.
- Với tập hữu hạn m trạng thái khả dĩ và n hành động khả dĩ, phần tử Pmn trong ma trận biểu thị xác suất thực hiện hành động an tại trạng thái sm.
- Tập (Episode): Chuỗi các bước thời gian từ trạng thái khởi tạo (ngẫu nhiên) đến khi tác tử đạt trạng thái kết thúc.
Không gian quan sát và không gian hành động
Quan sát là thông tin tác tử thu thập về môi trường. Ví dụ, một robot có thể thu thập thông tin môi trường bằng cảm biến. Lý tưởng là tác tử có thể quan sát đầy đủ trạng thái, mô tả mọi khía cạnh của môi trường. Trên thực tế, tác tử dùng quan sát như đại diện cho trạng thái. Vì vậy, các quan sát quyết định hành động của tác tử.
Một space tương tự một tập hợp toán học. Không gian của các phần tử X bao gồm mọi trường hợp có thể có của X. Không gian của X cũng định nghĩa cấu trúc (cú pháp và định dạng) của mọi phần tử kiểu X. Mỗi môi trường Gymnasium có hai không gian: không gian hành động, action_space, và không gian quan sát, observation_space. Cả hai kế thừa từ lớp cha gymnasium.spaces.Space.
Không gian quan sát
Không gian quan sát là tập hợp mọi quan sát có thể. Nó cũng định nghĩa định dạng lưu trữ quan sát. Không gian quan sát thường được biểu diễn bằng đối tượng kiểu Box. Đây là một ndarray mô tả các tham số của quan sát. Box chỉ định cận của mỗi chiều. Bạn có thể xem không gian quan sát của một môi trường bằng phương thức observation_space:
print("observation space: ", env.observation_space)
Với môi trường CartPole-v1, đầu ra trông như ví dụ dưới đây:
observation space: Box([-4.8 -inf -0.41887903 -inf], [4.8 inf 0.41887903 inf], (4,), float32)
Trong ví dụ này, không gian quan sát của CartPole-v1 có 4 chiều. Bốn phần tử của mảng quan sát là:
- Vị trí xe đẩy (Cart position) - biến thiên từ -4.8 đến +4.8
- Vận tốc xe đẩy (Cart velocity) - nằm trong khoảng - đến +
- Góc thanh (Pole angle) - biến thiên từ -0.4189 đến +0.4189
- Vận tốc góc của thanh (Pole angular velocity) - nằm trong khoảng - đến +
Để xem ví dụ một mảng quan sát riêng lẻ, dùng lệnh .reset().
observation, info = env.reset()
print("observation: ", observation)
Với môi trường CartPole-v1, đầu ra trông như ví dụ dưới đây:
[ 0.03481963 -0.0277232 0.01703267 -0.04870504]
Bốn phần tử của mảng này tương ứng với bốn đại lượng quan sát (vị trí xe đẩy, vận tốc xe đẩy, góc thanh, vận tốc góc của thanh) như đã giải thích ở trên.
Không gian hành động
Không gian hành động bao gồm tất cả các hành động tác tử có thể thực hiện. Nó cũng định nghĩa định dạng biểu diễn hành động. Bạn có thể xem không gian hành động của một môi trường bằng phương thức action_space:
print("action space: ", env.action_space)
Với môi trường CartPole-v1, đầu ra trông như ví dụ dưới đây:
action space: Discrete(2)
Với môi trường CartPole-v1, không gian hành động là rời rạc. Tổng cộng có hai hành động tác tử có thể thực hiện:
- 0: Đẩy xe sang trái
- 1: Đẩy xe sang phải
Xây dựng tác tử RL đầu tiên của bạn với Gymnasium
Ở các phần trước, chúng ta đã tìm hiểu các khái niệm cơ bản về RL và Gymnasium. Phần này cho bạn thấy cách dùng Gymnasium để xây dựng một tác tử RL.
Tạo và đặt lại môi trường
Bước đầu tiên là tạo một thể hiện của môi trường. Để tạo môi trường mới, dùng phương thức .make().
env = gym.make('CartPole-v1')
Tương tác của tác tử làm thay đổi trạng thái của môi trường. Phương thức .reset() đặt lại môi trường về trạng thái ban đầu. Mặc định, môi trường khởi tạo ở trạng thái ngẫu nhiên. Bạn có thể dùng tham số SEED với phương thức .reset() để khởi tạo môi trường cùng một trạng thái mỗi lần chạy chương trình. Mã dưới đây cho thấy cách làm:
SEED = 1111
env.reset(seed=SEED)
Việc lấy mẫu hành động cũng liên quan đến ngẫu nhiên. Để kiểm soát tính ngẫu nhiên này và có lộ trình huấn luyện tái lập hoàn toàn, ta có thể gieo hạt các bộ tạo số ngẫu nhiên của NumPy và PyTorch:
np.random.seed(SEED)
torch.manual_seed(SEED)
Hành động ngẫu nhiên so với thông minh
Ở mỗi bước trong một quá trình Markov, tác tử có thể chọn ngẫu nhiên một hành động và khám phá môi trường cho đến khi tới trạng thái kết thúc. Khi chọn hành động ngẫu nhiên:
- Có thể mất nhiều thời gian để đến trạng thái kết thúc.
- Phần thưởng tích lũy thấp hơn nhiều so với tiềm năng.
Huấn luyện tác tử tối ưu hóa việc chọn hành động dựa trên kinh nghiệm trước đó (khi tương tác với môi trường) hiệu quả hơn để tối đa hóa phần thưởng dài hạn.
Tác tử chưa huấn luyện bắt đầu với các hành động ngẫu nhiên dựa trên một chính sách khởi tạo ngẫu nhiên. Chính sách này thường được biểu diễn dưới dạng mạng nơ-ron. Trong quá trình huấn luyện, tác tử học chính sách tối ưu để tối đa hóa phần thưởng. Trong RL, quá trình huấn luyện còn gọi là tối ưu hóa chính sách (policy optimization).
Có nhiều phương pháp tối ưu hóa chính sách. Phương trình Bellman mô tả cách tính giá trị của các chính sách RL và xác định chính sách tối ưu. Trong hướng dẫn này, chúng ta sẽ dùng một kỹ thuật đơn giản gọi là policy gradients. Còn có các phương pháp khác, như Proximal Policy Optimization (PPO).
Triển khai một tác tử Policy Gradient đơn giản
Để xây dựng một tác tử RL dùng policy gradients, ta tạo một mạng nơ-ron để triển khai chính sách, viết các hàm tính lợi tức và hàm mất mát từ phần thưởng theo bước và xác suất hành động, rồi cập nhật lặp lại chính sách bằng các kỹ thuật lan truyền ngược tiêu chuẩn.
Thiết lập mạng chính sách
Ta dùng mạng nơ-ron để triển khai chính sách. Vì CartPole-v1 là môi trường đơn giản, ta dùng một mạng nơ-ron với:
- Kích thước đầu vào bằng số chiều của không gian quan sát của môi trường.
- Một tầng ẩn duy nhất với 64 nơ-ron.
- Kích thước đầu ra bằng số chiều của không gian hành động của môi trường.
Vì vậy, chức năng của mạng chính sách là ánh xạ trạng thái quan sát được sang hành động. Với một quan sát đầu vào, nó dự đoán hành động phù hợp. Đoạn mã dưới đây triển khai mạng chính sách:
class PolicyNetwork(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim, dropout):
super().__init__()
self.layer1 = nn.Linear(input_dim, hidden_dim)
self.layer2 = nn.Linear(hidden_dim, output_dim)
self.dropout = nn.Dropout(dropout)
def forward(self, x):
x = self.layer1(x)
x = self.dropout(x)
x = F.relu(x)
x = self.layer2(x)
return x
Thu thập phần thưởng và forward pass
Như đã đề cập, ở mỗi bước của quá trình Markov, môi trường cho phần thưởng dựa trên hành động và trạng thái của tác tử. Mục tiêu trong RL là tối đa hóa tổng lợi tức.
- Lợi tức tại mỗi bước là tổng tích lũy của các phần thưởng thu được từ đầu đến bước đó.
- Tổng lợi tức trong mỗi tập thu được bằng cách cộng tất cả phần thưởng theo bước của tập đó. Như vậy, tổng lợi tức là lợi tức tại bước cuối cùng (khi tác tử đạt trạng thái kết thúc).
Trong thực tế, khi cộng dồn phần thưởng, người ta thường:
- Điều chỉnh phần thưởng tương lai bằng hệ số chiết khấu.
- Chuẩn hóa mảng lợi tức theo bước để đảm bảo huấn luyện trơn tru, ổn định.
Đoạn mã dưới đây cho thấy cách thực hiện:
def calculate_stepwise_returns(rewards, discount_factor):
returns = []
R = 0
for r in reversed(rewards):
R = r + R * discount_factor
returns.insert(0, R)
returns = torch.tensor(returns)
normalized_returns = (returns - returns.mean()) / returns.std()
return normalized_returns
Forward pass gồm chạy tác tử dựa trên chính sách hiện tại cho đến khi đạt trạng thái kết thúc và thu thập phần thưởng theo bước cùng xác suất hành động. Các bước dưới đây giải thích cách triển khai forward pass:
- Đặt lại môi trường về trạng thái ban đầu.
- Khởi tạo bộ đệm để lưu xác suất hành động, phần thưởng và lợi tức tích lũy
- Dùng hàm
.step()để chạy lặp tác tử trong môi trường cho đến khi kết thúc: - Lấy quan sát về trạng thái của môi trường.
- Lấy hành động do chính sách dự đoán dựa trên quan sát.
- Dùng hàm
Softmaxđể ước lượng xác suất thực hiện hành động dự đoán. - Mô phỏng phân phối xác suất rời rạc (categorical) dựa trên các xác suất ước lượng.
- Lấy mẫu từ phân phối này để nhận hành động của tác tử.
- Ước lượng log xác suất của hành động đã lấy mẫu từ phân phối mô phỏng.
- Thêm log xác suất các hành động và phần thưởng của mỗi bước vào các bộ đệm tương ứng.
- Ước lượng các giá trị lợi tức theo bước đã chuẩn hóa và chiết khấu dựa trên phần thưởng.
def forward_pass(env, policy, discount_factor):
log_prob_actions = []
rewards = []
done = False
episode_return = 0
policy.train()
observation, info = env.reset()
while not done:
observation = torch.FloatTensor(observation).unsqueeze(0)
action_pred = policy(observation)
action_prob = F.softmax(action_pred, dim = -1)
dist = distributions.Categorical(action_prob)
action = dist.sample()
log_prob_action = dist.log_prob(action)
observation, reward, terminated, truncated, info = env.step(action.item())
done = terminated or truncated
log_prob_actions.append(log_prob_action)
rewards.append(reward)
episode_return += reward
log_prob_actions = torch.cat(log_prob_actions)
stepwise_returns = calculate_stepwise_returns(rewards, discount_factor)
return episode_return, stepwise_returns, log_prob_actions
Cập nhật chính sách dựa trên phần thưởng
Hàm mất mát biểu diễn đại lượng mà ta áp dụng gradient descent. Mục tiêu trong RL là tối đa hóa lợi tức. Do đó, ta dùng giá trị lợi tức kỳ vọng như một đại diện cho mất mát. Giá trị lợi tức kỳ vọng được tính bằng tích của lợi tức kỳ vọng theo bước và log xác suất của các hành động theo bước. Đoạn mã dưới đây tính mất mát:
def calculate_loss(stepwise_returns, log_prob_actions):
loss = -(stepwise_returns * log_prob_actions).sum()
return loss
Để cập nhật chính sách, bạn chạy lan truyền ngược theo hàm mất mát. Phương thức update_policy() dưới đây gọi phương thức calculate_loss(). Sau đó chạy lan truyền ngược trên mất mát này để cập nhật tham số của chính sách, tức trọng số mô hình của mạng chính sách.
def update_policy(stepwise_returns, log_prob_actions, optimizer):
stepwise_returns = stepwise_returns.detach()
loss = calculate_loss(stepwise_returns, log_prob_actions)
optimizer.zero_grad()
loss.backward()
optimizer.step()
return loss.item()
Cập nhật chính sách dựa trên gradient của lợi tức được gọi là phương pháp policy gradient.
Huấn luyện chính sách
Giờ chúng ta đã có đủ thành phần để huấn luyện và đánh giá chính sách. Ta triển khai vòng lặp huấn luyện như sau:
Trước khi bắt đầu, ta khai báo siêu tham số, khởi tạo một chính sách và tạo bộ tối ưu:
- Khai báo siêu tham số dưới dạng hằng Python:
MAX_EPOCHSlà số vòng lặp tối đa sẵn sàng chạy để huấn luyện chính sách.DISCOUNT_FACTORquyết định tầm quan trọng tương đối của phần thưởng ở các bước tương lai. Hệ số 1 nghĩa là mọi phần thưởng đều quan trọng như nhau, còn 0 nghĩa là chỉ phần thưởng ở bước hiện tại quan trọng.N_TRIALSlà số tập dùng để lấy trung bình lợi tức nhằm đánh giá hiệu năng của tác tử. Ta coi huấn luyện thành công nếu lợi tức trung bình trênN_TRIALStập vượt ngưỡng.REWARD_THRESHOLD: Nếu chính sách đạt lợi tức lớn hơn ngưỡng này thì được coi là thành công.DROPOUTquyết định tỷ lệ trọng số bị đặt về 0 ngẫu nhiên. Hàm dropout ngẫu nhiên đặt một phần trọng số của mô hình về 0. Điều này giảm phụ thuộc vào các nơ-ron cụ thể và ngăn quá khớp, giúp mạng vững vàng hơn.LEARNING_RATEquyết định mức độ điều chỉnh tham số chính sách ở mỗi bước. Cập nhật tham số trong mỗi vòng là tích của gradient và tốc độ học.- Định nghĩa chính sách là một thể hiện của lớp
PolicyNetwork(đã triển khai ở trên). - Tạo bộ tối ưu dùng thuật toán Adam và tốc độ học.
Để huấn luyện chính sách, ta chạy lặp các bước huấn luyện cho đến khi lợi tức trung bình (trên N_TRIALS) lớn hơn ngưỡng phần thưởng:
- Với mỗi tập, chạy forward pass một lần. Thu thập log xác suất hành động, lợi tức theo bước và tổng lợi tức của tập đó. Cộng dồn lợi tức theo tập vào một mảng.
- Tính mất mát bằng log xác suất và lợi tức theo bước. Chạy lan truyền ngược trên mất mát. Dùng bộ tối ưu để cập nhật tham số chính sách.
- Kiểm tra liệu lợi tức trung bình trên
N_TRIALScó vượt ngưỡng phần thưởng không.
Đoạn mã dưới đây triển khai các bước trên:
def main():
MAX_EPOCHS = 500
DISCOUNT_FACTOR = 0.99
N_TRIALS = 25
REWARD_THRESHOLD = 475
PRINT_INTERVAL = 10
INPUT_DIM = env.observation_space.shape[0]
HIDDEN_DIM = 128
OUTPUT_DIM = env.action_space.n
DROPOUT = 0.5
episode_returns = []
policy = PolicyNetwork(INPUT_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT)
LEARNING_RATE = 0.01
optimizer = optim.Adam(policy.parameters(), lr = LEARNING_RATE)
for episode in range(1, MAX_EPOCHS+1):
episode_return, stepwise_returns, log_prob_actions = forward_pass(env, policy, DISCOUNT_FACTOR)
_ = update_policy(stepwise_returns, log_prob_actions, optimizer)
episode_returns.append(episode_return)
mean_episode_return = np.mean(episode_returns[-N_TRIALS:])
if episode % PRINT_INTERVAL == 0:
print(f'| Episode: {episode:3} | Mean Rewards: {mean_episode_return:5.1f} |')
if mean_episode_return >= REWARD_THRESHOLD:
print(f'Reached reward threshold in {episode} episodes')
break
Cuối cùng, gọi hàm main() để huấn luyện chính sách:
main()
Hãy dùng sổ tay DataLab này để chạy trực tiếp thuật toán trên và giải môi trường CartPole bằng RL.
Kỹ thuật nâng cao trong Gymnasium
Sau khi minh họa cách triển khai một thuật toán RL, giờ chúng ta thảo luận một số kỹ thuật nâng cao thường dùng trong thực tế.
Dùng kiến trúc dựng sẵn
Tự triển khai thuật toán RL từ đầu là quá trình dài và khó, nhất là với các môi trường phức tạp và chính sách hiện đại.
Một lựa chọn thực tế hơn là dùng phần mềm như Stable Baselines3. Nó đi kèm các triển khai đã được kiểm chứng của thuật toán RL. Bao gồm tác tử huấn luyện sẵn, script huấn luyện, công cụ đánh giá, và mô-đun vẽ biểu đồ, ghi video.
Ray RLib là công cụ RL phổ biến khác. RLib được thiết kế để mở rộng, giúp dễ triển khai thuật toán RL trên hệ thống đa GPU. Nó cũng hỗ trợ RL đa tác tử, mở ra các khả năng như:
- Học đa tác tử độc lập: Mỗi tác tử coi các tác tử khác là một phần của môi trường.
- Huấn luyện đa tác tử hợp tác: Một nhóm tác tử chia sẻ cùng chính sách và hàm giá trị, học từ trải nghiệm của nhau song song.
- Huấn luyện đối kháng: Các tác tử (hoặc nhóm tác tử) thi đấu trong môi trường cạnh tranh giống trò chơi.
Với cả RLib và Stable Baselines3, bạn có thể nhập và dùng các môi trường từ OpenAI Gymnasium.
Môi trường tùy chỉnh
Các môi trường đóng gói cùng Gymnasium là lựa chọn phù hợp để thử nghiệm chiến lược RL mới và huấn luyện chính sách. Tuy nhiên, cho đa số ứng dụng thực tiễn, bạn cần tạo và dùng môi trường phản ánh chính xác bài toán cần giải. Bạn có thể dùng Gymnasium để tạo môi trường tùy chỉnh. Ưu điểm của môi trường tùy chỉnh Gymnasium là nhiều công cụ bên ngoài như RLib và Stable Baselines3 đã được cấu hình để làm việc với cấu trúc API của Gymnasium.
Để tạo môi trường tùy chỉnh trong Gymnasium, bạn cần định nghĩa:
- Không gian quan sát.
- Điều kiện kết thúc.
- Tập hành động mà tác tử có thể chọn.
- Cách khởi tạo môi trường (khi gọi hàm
reset()). - Cách môi trường quyết định trạng thái tiếp theo dựa trên hành động của tác tử (khi gọi hàm
step()).
Để tìm hiểu thêm, hãy theo dõi hướng dẫn tạo môi trường tùy chỉnh của Gymnasium.
Thực hành tốt khi dùng Gymnasium
Thử nghiệm với các môi trường khác nhau
Mã trong hướng dẫn này cho thấy cách triển khai thuật toán policy gradient trong môi trường CartPole. Đây là môi trường đơn giản với không gian hành động rời rạc. Để hiểu RL tốt hơn, chúng tôi khuyên bạn áp dụng cùng thuật toán policy gradient (và các thuật toán khác, như PPO) trong các môi trường khác.
Ví dụ, môi trường Pendulum có không gian hành động liên tục. Nó gồm một đầu vào được biểu diễn bằng biến liên tục - (độ lớn và hướng của) mô-men xoắn tác dụng lên con lắc ở trạng thái bất kỳ. Mô-men này có thể nhận giá trị trong khoảng -2 đến +2.
Thử nghiệm các thuật toán khác nhau trong nhiều môi trường giúp bạn hiểu rõ hơn các dạng lời giải RL và những thách thức của chúng.
Theo dõi tiến trình huấn luyện
Các môi trường RL thường gồm robot, con lắc, xe leo núi, trò chơi điện tử, v.v. Trực quan hóa hành động của tác tử trong môi trường giúp hiểu trực giác tốt hơn về hiệu năng của chính sách.
Trong Gymnasium, phương thức env.render() trực quan hóa tương tác của tác tử với môi trường. Nó hiển thị đồ họa trạng thái hiện tại của môi trường—màn hình trò chơi, vị trí của con lắc hoặc cột xe đẩy, v.v. Phản hồi trực quan về hành động của tác tử và phản ứng của môi trường giúp theo dõi hiệu năng và tiến trình huấn luyện của tác tử.
Có bốn chế độ render: “human”, “rgb_array”, “ansi”, và “rgb_array_list”. Để trực quan hóa hiệu năng của tác tử, dùng chế độ “human”. Chế độ render được chỉ định khi khởi tạo môi trường. Ví dụ:
env = gym.make(‘CartPole-v1’, render_mode=’human’)
Để thực hiện render, gọi phương thức .render() sau mỗi hành động của tác tử (thông qua lời gọi .step()). Mã giả dưới đây minh họa cách làm:
while not done:
…
step, reward, terminated, truncated, info = env.step(action.item())
env.render()
…
Khắc phục lỗi thường gặp
Gymnasium giúp dễ dàng giao tiếp với các môi trường RL phức tạp. Tuy nhiên, đây là phần mềm được cập nhật liên tục với nhiều phụ thuộc. Vì vậy, cần lưu ý một số loại lỗi phổ biến.
Không khớp phiên bản
- Không khớp phiên bản Gymnasium: Gói Gymnasium của Farama được fork từ OpenAI Gym ở phiên bản 0.26.2. Có một vài thay đổi phá vỡ tương thích giữa các bản Gym cũ và các bản Gymnasium mới. Nhiều triển khai công khai dựa trên các bản Gym cũ có thể không chạy trực tiếp với bản mới nhất. Khi đó, cần hoặc quay lại cài bản cũ, hoặc điều chỉnh mã để hoạt động với bản mới.
- Không khớp phiên bản môi trường: Nhiều môi trường Gymnasium có các phiên bản khác nhau. Ví dụ, có hai môi trường CartPole -
CartPole-v1vàCartPole-v0. Dù hành vi môi trường giống nhau ở cả hai phiên bản, một số tham số như độ dài tập, ngưỡng phần thưởng, v.v., có thể khác. Một chính sách huấn luyện trên một phiên bản có thể không hoạt động tốt ở phiên bản khác của cùng môi trường. Bạn cần cập nhật tham số huấn luyện và huấn luyện lại chính sách cho mỗi phiên bản môi trường. - Không khớp phiên bản phụ thuộc: Gymnasium phụ thuộc vào các thư viện như NumPy và PyTorch. Tính đến tháng 12/2024, các phiên bản mới nhất của các phụ thuộc này là
numpy 2.1.3vàtorch 2.5.1. Tuy nhiên, Gymnasium hoạt động tốt nhất vớitorch 1.13.0vànumpy 1.23.3. Bạn có thể gặp vấn đề nếu cài Gymnasium vào môi trường đã có sẵn các phụ thuộc này. Chúng tôi khuyến nghị cài và làm việc với Gymnasium trong một môi trường Conda mới.
Vấn đề hội tụ
- Siêu tham số: Giống các thuật toán học máy khác, chính sách RL nhạy với các siêu tham số như tốc độ học, hệ số chiết khấu, v.v. Khuyến nghị thử nghiệm và tinh chỉnh thủ công hoặc dùng kỹ thuật tự động như grid search, random search.
- Khám phá so với khai thác: Với một số lớp chính sách (như PPO), tác tử áp dụng chiến lược hai hướng: khám phá môi trường để tìm đường mới và áp dụng cách tiếp cận tham lam để tối đa hóa phần thưởng dựa trên các đường đã biết. Nếu khám phá quá nhiều, chính sách không hội tụ. Ngược lại, nếu khám phá không đủ, nó có thể không thử đường tối ưu. Vì vậy, cần cân bằng giữa khám phá và khai thác. Cũng phổ biến là ưu tiên khám phá ở các tập đầu và khai thác ở các tập sau trong quá trình huấn luyện.
Bất ổn trong huấn luyện
- Tốc độ học lớn: Nếu tốc độ học quá cao, tham số chính sách bị cập nhật với biên độ lớn ở mỗi bước. Điều này có thể khiến bỏ lỡ bộ giá trị tối ưu. Giải pháp thường dùng là giảm dần tốc độ học, đảm bảo cập nhật nhỏ hơn và ổn định hơn khi huấn luyện hội tụ.
- Khám phá quá mức: Quá nhiều ngẫu nhiên (entropy) trong chọn hành động ngăn cản hội tụ và dẫn đến biến thiên lớn trong hàm mất mát giữa các bước liên tiếp. Để huấn luyện ổn định và hội tụ, hãy cân bằng khám phá với khai thác.
- Chọn sai thuật toán: Các thuật toán đơn giản như policy gradient có thể dẫn đến huấn luyện bất ổn trong môi trường phức tạp với không gian hành động và trạng thái lớn. Khi đó, nên dùng các thuật toán vững hơn như PPO và Trust Region Policy Optimization (TRPO). Các thuật toán này tránh cập nhật chính sách quá lớn ở mỗi bước và có thể ổn định hơn.
- Tính ngẫu nhiên: Thuật toán RL rất nhạy với trạng thái ban đầu và tính ngẫu nhiên vốn có trong chọn hành động. Khi một lần huấn luyện không ổn định, đôi khi có thể ổn định bằng cách dùng hạt giống ngẫu nhiên khác hoặc khởi tạo lại chính sách.
Kết luận
Trong hướng dẫn này, chúng ta đã khám phá các nguyên lý cơ bản của RL, thảo luận về Gymnasium như một gói phần mềm có API gọn gàng để giao tiếp với nhiều môi trường RL, và cho thấy cách viết chương trình Python để triển khai một thuật toán RL đơn giản và áp dụng trong một môi trường Gymnasium.
Sau khi nắm vững kiến thức cơ bản trong hướng dẫn này, tôi khuyến nghị dùng các môi trường Gymnasium để áp dụng khái niệm RL giải các bài toán thực tế như tối ưu lộ trình taxi và mô phỏng giao dịch cổ phiếu.
FAQs
Vai trò của Gymnasium trong học tăng cường là gì?
Gymnasium đi kèm nhiều môi trường dựng sẵn để kiểm thử và phát triển các thuật toán RL. Nó tiêu chuẩn hóa giao diện cho các môi trường này và cả môi trường tùy chỉnh mới. Điều này giúp việc triển khai và đánh giá thuật toán RL trở nên dễ dàng hơn.
Khi dùng OpenAI Gymnasium, bạn có bị giới hạn ở các môi trường tích hợp sẵn không?
Không. Bên cạnh hơn 60 môi trường dựng sẵn, Gymnasium cho phép bạn tạo môi trường mới bằng cách khai báo không gian trạng thái và hành động, và định nghĩa cách môi trường phản hồi với các hành động khác nhau.
Sự khác biệt giữa Gym và Gymnasium là gì?
Tóm lại, Gymnasium do Quỹ Farama duy trì là phiên bản mới và nâng cấp của Gym, vốn không còn được OpenAI duy trì. Gymnasium được kỳ vọng hoạt động như một bản thay thế trực tiếp cho Gym 0.26.2.
Khác biệt giữa phương pháp RL dựa trên chính sách và dựa trên giá trị là gì?
Trong các phương pháp dựa trên chính sách, như policy gradients, tác tử trực tiếp điều chỉnh tham số của chính sách để tìm chính sách mang lại lợi tức kỳ vọng lớn nhất.
Trong các phương pháp dựa trên giá trị, tác tử được huấn luyện với hàm giá trị. Học được hàm giá trị tối ưu giúp suy ra chính sách tối ưu.
Tự viết thuật toán có phải là cách tốt nhất và duy nhất để giải bài toán RL không?
Tự viết mã từ đầu là cách tốt nhất để hiểu các thuật toán RL khác nhau. Cho mục đích triển khai thực tế, có các công cụ như Stable Baselines3, RLib và CleanRL. Các công cụ này bao gồm các triển khai sẵn của những thuật toán RL phổ biến, bạn chỉ cần cấu hình và tinh chỉnh theo môi trường.

Arun là cựu nhà sáng lập startup, yêu thích xây dựng những điều mới mẻ. Hiện tại, anh đang khám phá các nền tảng kỹ thuật và toán học của Trí tuệ Nhân tạo. Anh thích chia sẻ những gì mình học được, vì thế anh viết về chúng.
Bên cạnh DataCamp, bạn có thể đọc các bài viết của anh trên Medium, Airbyte và Vultr.
Reinforcement Learning (RL) là một trong ba mô hình học máy chính, hai mô hình còn lại là học có giám sát và không giám sát. Trong RL, một tác tử học cách tương tác với môi trường để tối đa hóa phần thưởng tích lũy. Nó học hành động tối ưu dưới các điều kiện môi trường khác nhau thông qua thử và sai. Reinforcement Learning with Human Feedback (RLHF) cho phép tác tử điều chỉnh hành vi dựa trên đầu vào của con người ở mỗi bước.
RL giải các bài toán như xe tự lái, giao dịch tự động, người chơi máy tính trong trò chơi điện tử, huấn luyện robot, v.v. Khi dùng mạng nơ-ron sâu để áp dụng các thuật toán RL, ta gọi là Deep Reinforcement Learning.
Trong hướng dẫn này, tôi sẽ chỉ bạn cách bắt đầu với Gymnasium, một thư viện Python mã nguồn mở để phát triển và so sánh các thuật toán học tăng cường. Tôi sẽ minh họa cách cài đặt, khám phá các môi trường RL khác nhau, và dùng Python để xây dựng một tác tử đơn giản triển khai một thuật toán RL.
Gymnasium là gì?
Gymnasium là một thư viện Python mã nguồn mở được thiết kế để hỗ trợ phát triển các thuật toán RL. Để thúc đẩy nghiên cứu và phát triển trong RL, Gymnasium cung cấp:
Nhà phát triển có thể xây dựng thuật toán RL và dùng các lời gọi API cho các tác vụ như:
OpenAI Gym so với Gymnasium của Farama
OpenAI không dành nhiều nguồn lực để phát triển Gym vì đó không phải là ưu tiên kinh doanh của công ty. Quỹ Farama được lập ra để tiêu chuẩn hóa và duy trì các thư viện RL lâu dài. Gymnasium là bản fork của Gym (OpenAI) do Farama phát triển. Gymnasium 0.26.2 có thể thay thế trực tiếp Gym 0.26.2. Với bản fork này, Farama đặt mục tiêu bổ sung các phương thức dạng hàm (bên cạnh dạng lớp) cho mọi lời gọi API, hỗ trợ môi trường vector và cải thiện các wrapper. Mục tiêu chung là làm cho khung làm việc gọn gàng và hiệu quả hơn.