Ứng dụng Machine Learning vào chơi game Flappy Bird.pdf

aicandy 16 views 18 slides Nov 29, 2024
Slide 1
Slide 1 of 18
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18

About This Presentation

Ứng dụng Machine Learning vào chơi
game Flappy Bird
Nội dung
1. Giới thiệu
2. Cấu trúc project và môi trường huấn luyện
2.1. Cấu trúc dự án
2.2. Cài đặt môi trường
3. Xây dựng môi trường game Flappy bird
3.1. Giới thiệu
3.2. Xây dựng môi trường...


Slide Content

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
1

Ứng dụng Machine Learning vào chơi
game Flappy Bird
Nội dung
 1. Giới thiệu
 2. Cấu trúc project và môi trường huấn luyện
o 2.1. Cấu trúc dự án
o 2.2. Cài đặt môi trường
 3. Xây dựng môi trường game Flappy bird
o 3.1. Giới thiệu
o 3.2. Xây dựng môi trường game khi huấn luyện
o 3.3. Xây dựng môi trường game khi thử nghiệm
 4. Xây dựng model
 5. Chương trình huấn luyện
 6. Chương trình thử nghiệm
 7. Demo và source code
1. Giới thiệu
Flappy Bird là một trò chơi đơn giản nhưng đầy thách thức, yêu cầu người
chơi điều khiển một chú chim vượt qua các chướng ngại vật. Tuy nhiên, việc
điều khiển này có thể được tự động hóa và tối ưu hóa nhờ ứng dụng Machine
Learning. Bằng cách sử dụng các thuật toán học máy, chúng ta có thể huấn
luyện một bot để chơi trò chơi này mà không cần can thiệp của con người.
Bot sẽ học cách xử lý các tình huống trong game thông qua dữ liệu, tự động
điều chỉnh chiến thuật nhằm đạt điểm số cao hơn. Việc áp dụng Machine
Learning không chỉ giúp hiểu sâu hơn về quá trình học hỏi của các hệ thống
tự động mà còn mở ra những tiềm năng phát triển trong ngành game và trí
tuệ nhân tạo.
Mục tiêu là bot tự chơi và đạt được điểm số cao.

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
2


2. Cấu trúc project và môi trường huấn luyện
2.1. Cấu trúc dự án
root@aicandy:/aicandy/projects/aicandy_flappybird_lolmygca# tree
.
├── aicandy_core
│ ├── env_FlappyBird_test_vhnldpii.py
│ ├── env_FlappyBird_train_gsbdrvvp.py
│ ├── model_xpuihdim.py
│ └── utils_dylhxpln.py
├── aicandy_data
│ ├── background-black.png
│ ├── base.png
│ ├── pipe-green.png
│ ├── redbird-downflap.png
│ ├── redbird-midflap.png
│ └── redbird-upflap.png
├── aicandy_flappyBird_test_romddkvc.py
├── aicandy_flappyBird_train_otnlcisl.py
├── requirements.txt
└── aicandy_models

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
3

└── flappy_bird

3 directories, 13 files
root@aicandy:/aicandy/projects/aicandy_flappybird_lolmygca#
Trong đó:
 Thư mục aicandy_core chứa các file mã nguồn tạo môi trường và
model.
 Thư mục aicandy_data chứa dữ liệu để tạo giao diện đồ họa cho game.
 Thư mục aicandy_models chứa các model đã được huấn luyện.
 Tệp aicandy_flappyBird_test_romddkvc.py chứa mã nguồn chương
trình để thử nghiệm.
 Tệp aicandy_flappyBird_train_otnlcisl.py chứa mã nguồn chương
trình để huấn luyện.
 Tệp requirements.txt chứa tên các thư viện cần cài đặt để thực hiện
huấn luyện.
2.2. Cài đặt môi trường
Sử dụng pygame – một thư viện phổ biến trong Python được thiết kế để phát
triển trò chơi 2D và các ứng dụng đa phương tiện.
Cài đặt một số thư viện thông qua pip:
pip install -r .\requirements.txt
3. Xây dựng môi trường game Flappy bird
3.1. Giới thiệu
Môi trường game Flappy Bird được xây dựng dựa trên các thành phần chính
như màn hình hiển thị, các đối tượng di chuyển và tương tác, cũng như các
quy tắc vật lý. Game sử dụng thư viện pygame để tạo giao diện đồ họa 2D
với các thành phần như nền, các ống cản trở, và chú chim.

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
4

Kích thước màn hình:
Trò chơi được đặt trong một khung hiển thị có kích thước 288×512, tạo nên
không gian giới hạn cho các vật thể di chuyển.
Chuyển động của người chơi (Chim):
Chim di chuyển dọc theo trục y, chịu tác động của trọng lực và có thể nhảy
lên khi người chơi “flap” (chạm vào màn hình). Tốc độ dọc của chim được
điều chỉnh bằng trọng lực và lực đẩy khi flap.
Chướng ngại vật (Ống):
Các cột ống di chuyển ngang với tốc độ cố định từ phải sang trái. Khoảng
cách giữa các cột ống được tạo ngẫu nhiên, tạo ra thách thức cho người chơi
hoặc AI khi cần vượt qua.
Điểm số:
Người chơi hoặc AI kiếm điểm mỗi khi vượt qua một cột ống. Điểm số được
hiển thị trên màn hình.
Môi trường này tương tác theo từng khung hình, và mỗi lần cập nhật, các
vật thể trong game như chim, ống và mặt đất đều thay đổi vị trí dựa trên các
yếu tố vật lý như vận tốc, trọng lực, và sự điều khiển của người chơi. Môi
trường game Flappy Bird được thiết kế để có thể dễ dàng tương thích với
các mô hình Machine Learning, tạo điều kiện cho AI có thể học cách điều
khiển chú chim vượt qua các chướng ngại vật bằng cách quan sát trạng thái
và hành động.
Về cơ bản, môi trường khi train và khi thử nghiệm tương đối giống nhau,
chỉ khác ở chỗ, để tăng hiệu năng khi train thì không cần cập nhật điểm số
hiện tại hoặc không cần lưu ảnh, nếu “chim” bị va chạm và kết thúc game
thì chương trình tự động reset và tự chơi lại, còn với môi trường khi thử
nghiệm, chúng ta có thể chèn thêm nhạc, lưu ảnh, thêm hiển thị điểm số ….
3.2. Xây dựng môi trường game khi huấn luyện

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
5

Bước 1: Tạo các hình ảnh chú chim đang bay, đang rơi, cột ống và hình nền
Sử dụng các ảnh đơn như chú chim đang bay lên, chú chim đang rơi xuống,
các cột ống và ảnh nền sau đó ghép với nhau để tạo giao diện game
flappybird


display.set_caption('AIcandy.vn Flappy Bird')
ground_img = load('aicandy_data/base.png').convert_alpha()
bg_img = load('aicandy_data/background-black.png').convert()

obstacle_imgs = [rotate(load('aicandy_data/pipe-
green.png').convert_alpha(), 180),
load('aicandy_data/pipe-
green.png').convert_alpha()]
player_imgs = [load('aicandy_data/redbird-
upflap.png').convert_alpha(),
load('aicandy_data/redbird-
midflap.png').convert_alpha(),
load('aicandy_data/redbird-
downflap.png').convert_alpha()]

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
6

Bước 2: Tạo cột ống chuyển động
Tạo phương thức create_obstacle để sinh ra một cặp ống cản trở mới với vị
trí và khoảng cách ngẫu nhiên giữa chúng. Đây là một phần quan trọng trong
gameplay của Flappy Bird, nơi người chơi phải điều khiển chú chim để tránh
va chạm với các ống.
def create_obstacle(self):
x = self.display_width + 10
gap_y = randint(2, 10) * 10 + int(self.ground_y / 5)
return {"x_top": x, "y_top": gap_y - self.obstacle_height,
"x_bottom": x, "y_bottom": gap_y + self.obstacle_gap}
Trong đó:
x = self.display_width + 10
Đoạn mã này xác định vị trí x của ống mới. Nó được đặt bên ngoài màn hình
(vượt ra ngoài chiều rộng của màn hình một chút) để ống có thể di chuyển
vào màn hình từ bên phải.
gap_y = randint(2, 10) * 10 + int(self.ground_y / 5)
Dòng này tạo ra một giá trị y ngẫu nhiên cho khoảng cách giữa hai ống, nhằm
tạo ra độ khó khác nhau cho người chơi. Sử dụng self.ground_y / 5 để điều
chỉnh giá trị ngẫu nhiên dựa trên vị trí của mặt đất, đảm bảo rằng khoảng
cách giữa ống không quá thấp, tránh tình trạng tạo ra khoảng trống quá nhỏ
cho người chơi.
Bước 3: Kiểm tra va chạm giữa người chơi “chim” và các chướng ngại vật.
if self.player_height + self.player_y + 1 >= self.ground_y:
return True
overlap_rect = player_rect.clip(obstacle_rects[i])
x1 = overlap_rect.x - player_rect.x
y1 = overlap_rect.y - player_rect.y
x2 = overlap_rect.x - obstacle_rects[i].x

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
7

y2 = overlap_rect.y - obstacle_rects[i].y
if np.any(self.player_mask[self.player_frame][x1:x1 +
overlap_rect.width,
y1:y1 + overlap_rect.height] * self.obstacle_mask[i][x2:x2 +
overlap_rect.width,
y2:y2
+ overlap_rect.height]):
return True
Trong đó:
if self.player_height + self.player_y + 1 >= self.ground_y
Dòng này kiểm tra xem chim có va chạm với mặt đất hay không. Nếu vị trí
dọc của chim cộng với chiều cao chim (cộng thêm 1 để đảm bảo an toàn) lớn
hơn hoặc bằng vị trí y của mặt đất (ground_y), phương thức sẽ trả về True,
tức là chim đã va chạm với mặt đất.
if np.any(self.player_mask ….
Sử dụng mặt nạ (mask) để xác định xem có bất kỳ pixel nào từ hình ảnh chim
và hình ảnh chướng ngại vật đang chồng lên nhau trong khu vực chồng lấp
không. Nếu có pixel chồng chéo, phương thức sẽ trả về True, tức là có va
chạm.
Bước 4: Update trạng thái game
Tạo phương thức update_game để cập nhật trạng thái của trò chơi sau mỗi
khung hình, xử lý các hành động của người chơi, và quản lý điểm số, các
chướng ngại vật và việc kiểm tra va ch ạm.
Bằng cách tính toán vị trí của chim và duyệt qua các chướng ngại vật để kiểm
tra xem chim có vượt qua chướng ngại vật nào không. Nếu chim vượt qua,
tăng điểm số và thiết lập phần thưởng thành 1.
player_center_x = self.player_x + self.player_width / 2
for obstacle in self.obstacles:

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
8

obstacle_center_x = obstacle["x_top"] +
self.obstacle_width / 2
if obstacle_center_x < player_center_x <
obstacle_center_x + 5:
self.points += 1
Tiếp theo là cập nhật vị trí của mặt đất để tạo hiệu ứng di chuyển. Đồng thời
điều chỉnh tốc độ thẳng đứng bằng cách nếu tốc độ thẳng đứng của chim
nhỏ hơn tốc độ tối đa và chim không đang nhảy, tăng tốc độ thẳng đứng
theo trọng lực.
self.ground_x = -((-self.ground_x + 100) % self.ground_shift)

if self.vert_speed < self.max_vert_speed and not
self.flapped:
self.vert_speed += self.gravity
if self.flapped:
self.flapped = False
self.player_y += min(self.vert_speed, self.player_y -
self.vert_speed - self.player_height)
if self.player_y < 0:
self.player_y = 0
3.3. Xây dựng môi trường game khi thử nghiệm
Môi trường game khi thử nghiệm cũng tương tự với môi trường game khi
train, chúng ta chỉ cần bổ sung hàm display_score với mục đích để hiển thị
điểm số lên màn hình.
font_size = 30
font = pygame.font.SysFont('Tahoma', font_size)
score_text = str(int(self.points))
score_surface = font.render(score_text, True, (255,0,0))
text_x = int(self.bg_img.get_width() - 5*len(score_text))/2 - 20
text_y = int(self.bg_img.get_height() - 60)
self.game_display.blit(score_surface, dest=(text_x, text_y))

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
9

4. Xây dựng model
Sử dụng thuật toán Deep Q-Network (DQN) – một thuật toán học tăng
cường (reinforcement learning) tiên tiến, kết hợp mạng nơ-ron sâu với Q-
learning truyền thống. DQN hoạt động bằng cách sử dụng mạng nơ-ron sâu
để ước tính hàm Q, thay vì sử dụng bảng Q truyền thống. Điều này cho phép
nó xử lý không gian trạng thái và hành động lớn hơn nhiều so với các
phương pháp Q-learning cổ điển.
Phần khởi tạo mạng sử dụng 3 lớp tích chập. Mỗi lớp tích chập được kết hợp
với một hàm kích hoạt ReLU để tạo ra tính phi tuyến. Tham
số inplace=True trong ReLU giúp tiết kiệm bộ nhớ bằng cách thực hiện
phép biến đổi trực tiếp trên dữ liệu đầu vào.
Cấu trúc này được sử dụng để trích xuất các đặc trưng từ hình ảnh đầu vào,
giảm kích thước dữ liệu và tăng số lượng kênh (tức là số lượng đặc trưng)
qua mỗi lớp.
self.conv1 = nn.Sequential(nn.Conv2d(4, 32, kernel_size=8,
stride=4), nn.ReLU(inplace=True))
self.conv2 = nn.Sequential(nn.Conv2d(32, 64, kernel_size=4,
stride=2), nn.ReLU(inplace=True))
self.conv3 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=3,
stride=1), nn.ReLU(inplace=True))
Trong đó :
nn.Conv2d(4, 32, kernel_size=8, stride=4)
Lớp tích chập thứ nhất với 4 kênh đầu vào (4 frame liên tiếp của game), tạo
32 kênh đầu ra, sử dụng với kích thước kernel là 8 và bước nhảy là 4.
nn.Sequential(nn.Conv2d(32, 64, kernel_size=4, stride=2)
Lớp tích chập thứ hai với 32 kênh đầu vào (là 32 kênh đầu ra của lớp thứ
nhất), tạo 64 kênh đầu ra, sử dụng với kích thước kernel là 4 và bước nhảy
là 2.

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
10

nn.Sequential(nn.Conv2d(64, 64, kernel_size=3, stride=1)
Lớp tích chập thứ hai với 64 kênh đầu vào (là 64 kênh đầu ra của lớp thứ
hai), tạo 64 kênh đầu ra, sử dụng với kích thước kernel là 3 và bước nhảy là
1.
Bướ tiếp theo là định nghĩa phương thức _create_weights để khởi tạo
trọng số cho mạng neural. Đây là một bước quan trọng trong việc thiết lập
mạng trước khi bắt đầu quá trình huấn luyện.
if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
Chỉ áp dụng khởi tạo cho các lớp tích chập (Conv2d) và các lớp fully
connected (Linear). Bởi vì Conv2d và Linear là các lớp chính có chứa tham
số học được (learnable parameters) trong mạng neural.
nn.init.uniform_(m.weight, –0.01, 0.01)
Sử dụng phân phối đều (uniform distribution) để khởi tạo trọng số. Giá trị
trọng số sẽ nằm trong khoảng [-0.01, 0.01].
Việc sử dụng phân phối đều với giá trị nhỏ giúp tránh vấn đề gradient
exploding/vanishing trong quá trình huấn luyện ban đầu. Đặt bias về 0 là
một lựa chọn phổ biến, cho phép mạng học các bias cần thiết trong quá trình
huấn luyện.
Bước tiếp theo là định nghĩa phương thức forward để mô tả cách dữ liệu đi
qua mạng từ đầu vào đến đầu ra.
output = self.conv1(input)
output = self.conv2(output)
output = self.conv3(output)
output = output.view(output.size(0), -1)
output = self.fc1(output)
output = self.fc2(output)

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
11

return output
Dữ liệu đi qua ba lớp tích chập (conv1, conv2, conv3) đã được định nghĩa
trước đó. Mỗi lớp trích xuất và biến đổi các đặc trưng của đầu vào. Sau đó
chuyển đổi tensor đa chiều thành vector 2D, tự động tính toán kích thước
còn lại để làm phẳng tensor. Sau khi dữ liệu đã làm phẳng, dữ liệu tiếp tục
đi qua hai lớp fully connected (fc1 và fc2). Và cuối cùng là trả về giá trị Q
cho mỗi hành động.
5. Chương trình huấn luyện
Mục tiêu của chương trình này là sau quá trình huấn luyện sẽ tạo ra model
để sau đó bot tự chơi flappy bird và đạt được điểm số cao.
Bước 1: Cấu hình các tham số cơ bản về batch, learning_rate, optimizer_type
Để tăng tính linh hoạt khi train và tùy chỉnh các tham số này, sử dụng
parse_arguments() cùng với các tham số default.
parser = argparse.ArgumentParser(
"""AIcandy.vn Flappy Bird""")
parser.add_argument("--img_size", type=int, default=84,
help="The common width and height for all images ")
parser.add_argument("--batch_count", type=int, default=32,
help="The number of images per batch")
parser.add_argument("--optimizer_type", type=str,
choices=["sgd", "adam"], default="adam")
parser.add_argument("--learning_rate", type=float, default=1e-6)
parser.add_argument("--discount_factor", type=float,
default=0.99)
parser.add_argument("--start_epsilon", type=float, default=0.1)
parser.add_argument("--end_epsilon", type=float, default=1e-4)
parser.add_argument("--total_iterations", type=int,
default=2000000)
parser.add_argument("--memory_size", type=int, default=50000,

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
12

help="Number of epoches between testing
phases")
parser.add_argument("--model_dir", type=str, default="models")
Bước 2: Khởi tạo mạng, lựa chọn optimizer, loss function và khởi tạo môi trường
game
environment = FlappyBird()
khởi tạo một đối tượng của lớp FlappyBird, đại diện cho môi trường trò chơi
Flappy Bird. Môi trường này có thể tương tác với mạng neural để huấn luyện
agent (tác nhân).
frame, reward, done = environment.update_game(0)
Phương thức update_game(0) cập nhật trạng thái của trò chơi dựa trên hành
động được thực hiện, ở đây 0 có thể đại diện cho hành động không bấm
(không nhảy) trong trò chơi.
network = DeepQNetwork()
optimizer = torch.optim.Adam(network.parameters(),
lr=config.learning_rate)
loss_function = nn.MSELoss()
environment = FlappyBird()
frame, reward, done = environment.update_game(0)
frame = torch.from_numpy(frame)
Chuyển đổi khung hình từ định dạng numpy array sang tensor của PyTorch
để có thể dùng trong mạng neural.
current_state = torch.cat(tuple(frame for _ in range(4)))[None, :, :, :]
Tạo ra trạng thái hiện tại (current_state) bằng cách lặp lại tensor frame 4 lần,
rồi nối chúng lại với nhau theo chiều sâu (stack). None thêm một chiều mới
vào đầu tensor, thường là chiều batch để tensor có dạng (1, channels, height,
width).

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
13

Bước 3: Tính toán để đưa ra quyết định “flap” hay “không flap”
Sử dụng cơ chế epsilon-greedy, một chiến lược phổ biến trong học tăng
cường (reinforcement learning) để cân bằng giữa khám phá (exploration)
và khai thác (exploitation).
Giá trị epsilon điều khiển xác suất để agent thực hiện khám phá (chọn một
hành động ngẫu nhiên) thay vì khai thác (chọn hành động tốt nhất từ mô
hình hiện tại). Khi iteration tăng lên (gần với config.total_iterations), giá trị
epsilon giảm dần từ start_epsilon đến end_epsilon, có nghĩa là agent sẽ dần
dần thực hiện ít khám phá hơn và bắt đầu khai thác nhiều hơn.
epsilon = config.end_epsilon + ((config.total_iterations -
iteration) * (config.start_epsilon - config.end_epsilon) /
config.total_iterations)
action = torch.argmax(prediction).item( )
Hàm torch.argmax(prediction) tìm chỉ số của giá trị lớn nhất trong
prediction, tức là hành động có khả năng nhận phần thưởng cao nhất dựa
trên mô hình hiện tại.
Bước 4: Bước tiếp theo là xử lý trạng thái tiếp theo của môi trường sau khi đưa ra
“action”
next_frame, reward, done = environment.update_game(action)
Cập nhật trạng thái của trò chơi bằng cách thực hiện hành động action trong
môi trường environment. Với next_frame: Khung hình mới sau khi hành
động được thực hiện (tức là trạng thái hiện tại của trò chơi sau hành
động). reward là phần thưởng nhận được từ hành động đó (ví dụ: cộng điểm
nếu vượt qua chướng ngại vật). done là Biến cờ cho biết trò chơi đã kết thúc
chưa (True nếu trò chơi kết thúc, False nếu còn tiếp tục).
Mục tiêu là lấy 4 frame mới nhất để đưa các frame này vào trong mạng. Để
thực hiện điều này, chúng ta nối (concatenate) tensor next_frame với
tensor current_state để tạo ra trạng thái tiếp theo (next_state), sau đó cắt
bớt trạng thái cũ (bỏ khung hình đầu tiên trong current_state), chỉ lấy các
khung hình thứ 2 đến 4 trong dãy trạng thái hiện tại. Sau khi nối lại, trạng

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
14

thái mới next_state sẽ chứa 4 khung hình: 3 khung hình trước đó
(từ current_state) và khung hình mới nhất (next_frame).
next_state = torch.cat((current_state[0, 1:, :, :],
next_frame))[None, :, :, :];
Bước 5: Chuẩn bị dữ liệu đầu vào cho việc huấn luyện
Ở bước này chúng ta xử lý các batch (lô) dữ liệu của hành động
(action_batch), phần thưởng (reward_batch), và trạng thái tiếp theo
(next_state_batch).
[1, 0] if action == 0 else [0, 1] for action in action_batch
Sử dụng kỹ thuật one-hot vector: Duyệt qua từng action trong action_batch
và chuyển đổi mỗi action thành một vector one-hot: Hành động 0 được biểu
diễn là [1, 0] (ví dụ: không nhảy), Hành động 1 được biểu diễn là [0, 1] (ví
dụ: nhảy).
Sử dụng generator expression dùng để tạo ra một tuple gồm các trạng thái
(state) từ next_state_batch. next_state_batch chứa các trạng thái tiếp theo
sau khi agent thực hiện hành động tại mỗi bước trong batch. Sau đó dùng
torch.cat để nối (concatenate) tất cả các trạng thái trong tuple lại với nhau
dọc theo trục 0. Điều này tạo ra một tensor có chứa tất cả các trạng thái trong
batch, hợp thành một tensor duy nhất với chiều batch là số lượng trạng thái.
next_state_batch = torch.cat(tuple(state for state in
next_state_batch))
Bước 6: Tính toán giá trị Q mục tiêu
Quá trình tính toán giá trị Q mục tiêu (target Q-values) và cập nhật mạng
neural theo thuật toán Q-learning trong học tăng cường (reinforcement
learning). Nó sử dụng cơ chế hồi quy Q-learning để điều chỉnh các tham số
của mạng sao cho giá trị Q dự đoán từ mô hình tiệm cận với giá trị mục tiêu
tính toán từ phần thưởng nhận được và trạng thái tiếp theo.
target_q_values = torch.cat(
tuple(reward if done else reward + config.discount_factor *
torch.max(q_value) for reward, done, q_value in

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
15

zip(reward_batch, done_batch, next_q_values)))

q_value = torch.sum(current_q_values * action_batch, dim=1)
optimizer.zero_grad()
loss = loss_function(q_value, target_q_values)
loss.backward()
optimizer.step()
Tính toán giá trị Q mục tiêu: Dựa trên phần thưởng hiện tại và giá trị Q dự
đoán cho trạng thái tiếp theo. Nếu trò chơi đã kết thúc (done=True), giá trị
Q mục tiêu chỉ là phần thưởng nhận được. Tính toán giá trị Q hiện tại: Chọn
giá trị Q dự đoán tương ứng với hành động đã thực hiện bằng cách sử dụng
one-hot vector. Lan truyền ngược và cập nhật mô hình: Tính toán mất mát
giữa giá trị Q dự đoán và Q mục tiêu, sau đó sử dụng lan truyền ngược để
cập nhật mô hình nhằm giảm sự khác biệt giữa chúng trong các vòng huấn
luyện tiếp theo.
6. Chương trình thử nghiệm
Mục tiêu của chương trình này là sử dụng model đã được huấn luyện để
chạy thử nghiệm.
Bước 1: Cấu hình tham số và load model
Để tăng tính linh hoạt cho chương trình, sử dụng để có thể thay đổi đường
dẫn khi chạy chương trình.
parser = argparse.ArgumentParser("""AIcandy.vn Flappy Bird""")
parser.add_argument("--img_dim", type=int, default=84, help="The
common width and height for all images")
parser.add_argument("--model_dir", type=str,
default="aicandy_models")
Tiếp theo là tải model và đưa model vào chế độ đánh giá. Sử dụng GPU nếu
có GPU hoặc dùng CPU nếu thiết bị GPU để tăng hiệu năng.

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
16

device = torch.device("cuda" if torch.cuda.is_available() else
"cpu")
model = torch.load(f"{config.model_dir}/flappy_bird" if
torch.cuda.is_available() else f"{config.model_dir}/flappy_bird",
map_location=device)
model.eval()
Bước 2: Khởi tạo mạng, lựa chọn optimizer, loss function và khởi tạo môi trường
game
environment = FlappyBird()
khởi tạo một đối tượng của lớp FlappyBird, đại diện cho môi trường trò chơi
Flappy Bird. Môi trường này có thể tương tác với mạng neural để huấn luyện
agent (tác nhân).
frame, reward, done = environment.update_game(0)
Phương thức update_game(0) cập nhật trạng thái của trò chơi dựa trên hành
động được thực hiện, ở đây 0 có thể đại diện cho hành động không bấm
(không nhảy) trong trò chơi.
network = DeepQNetwork()
optimizer = torch.optim.Adam(network.parameters(),
lr=config.learning_rate)
loss_function = nn.MSELoss()
environment = FlappyBird()
frame, reward, done = environment.update_game(0)
frame = torch.from_numpy(frame)
Chuyển đổi khung hình từ định dạng numpy array sang tensor của PyTorch
để có thể dùng trong mạng neural.
current_state = torch.cat(tuple(frame for _ in range(4)))[None, :, :, :]
Tạo ra trạng thái hiện tại (current_state) bằng cách lặp lại tensor frame 4 lần,
rồi nối chúng lại với nhau theo chiều sâu (stack). None thêm một chiều mới

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
17

vào đầu tensor, thường là chiều batch để tensor có dạng (1, channels, height,
width).
Bước 3: Tính toán để đưa ra quyết định “flap” hay “không flap”
Trong chế độ đánh giá, các hành động “flap” hoặc “không flap” được quyết
định bằng việc tìm chỉ số của giá trị lớn nhất trong prediction, tức là hành
động có khả năng nhận phần thưởng cao nhất dựa trên mô hình hiện tại.
action = torch.argmax(prediction).item()
Bước 4: Xử lý trạng thái tiếp theo của môi trường sau khi đưa ra “action”
Bước này cập nhật trò chơi dựa trên hành động đã thực hiện (action), như
một bước trong quá trình học tăng cường. Cần lưu ý là chúng ta chỉ cần lấy
phần hình ảnh tương ứng với màn hình hiển thị của trò chơi, từ độ rộng của
trò chơi (game.display_width) đến độ cao của mặt đất (game.ground_y).
Điều này loại bỏ các phần không liên quan của khung hình, chẳng hạn như
phần phía dưới mặt đất hoặc phần ngoài màn hình hiển thị.
state là tensor đại diện cho trạng thái hiện tại của trò chơi (bao gồm nhiều
khung hình). state[0, 1:, :, :] lấy các khung hình từ vị trí 1 trở đi, tức là loại bỏ
khung hình đầu tiên (cũ nhất). Việc loại bỏ khung hình cũ nhất giúp agent
luôn có thông tin cập nhật về trò chơi mà không bị “quá khứ quá xa” ảnh
hưởng.
Nối (concatenate) khung hình mới next_frame với chuỗi khung hình hiện tại
(đã loại bỏ khung hình cũ nhất). Việc nối này tạo ra một trạng thái mới với
các khung hình liên tiếp gần nhất, bao gồm khung hình vừa nhận được từ
môi trường. Điều này giúp mô hình có thông tin về sự thay đổi trạng thái
(các khung hình liên tiếp) để đưa ra quyết định tốt hơn trong bước tiếp theo.
next_frame, reward, done = game.update_game(action)
next_frame =
process_image(next_frame[:game.display_width, :int(game.ground_y)],
config.img_dim, config.img_dim)
next_frame = torch.from_numpy(next_frame).to(device)
next_state = torch.cat((state[0, 1:, :, :],
next_frame))[None, :, :, :]

https://aicandy.vn/cach-du-doan-gia-co-phieu-hieu-qua-bang-mo-hinh-lstm/
Bản quyền thuộc về: https://aicandy.vn


Học tập toàn diện: Kết nối lý thuyết, thực hành và dữ liệu thực tế
https://aicandy.vn
18

Thực hiện liên tục bước 4 cho tới khi kết thúc trò chơi (chú chim bị va chạm
vào ống).
7. Demo và source code
Xem video demo bot chơi Flappy bird tại đây
Tải miễn phí source code tại đây
Bài trước
Danh mục
Bài sau

Chúc bạn thành công trong hành trình khám phá và ứng dụng trí tuệ nhân tạo
vào học tập và công việc. Đừng quên truy cập thường xuyên để cập nhật thêm
kiến thức mới tại AIcandy