BeeLab

Thursday, December 16, 2021

[RL series] Thuật toán Q-Learning

11:08:00 PM 0
[RL series] Thuật toán Q-Learning

Bài trước tôi đã giới thiệu về RL và bây giờ tôi sẽ nói về phương pháp đơn giản để chúng ta dễ dàng tiếp cập với RL.



Q-learning là gì?

Q-learning là một thuật toán học tăng cường không có mô hình (Model-free). Nó học tập dựa trên các giá trị (values-based). Các thuật toán dựa trên giá trị cập nhật hàm giá trị dựa trên một phương trình (đặc biệt là phương trình Bellman). Trong khi loại còn lại, dựa trên chính sách (policy-based) ước tính hàm giá trị với một chính sách tham lam có được từ lần cải tiến chính sách cuối cùng.

Q-learning is an off-policy learner 

Có nghĩa là nó học được giá trị của chính sách (policy) tối ưu một cách độc lập với các hành động của chủ thể (agent). Mặt khác, on-policy learner tìm hiểu giá trị của chính sách đang được thực hiện bởi chủ thể, bao gồm các bước thăm dò và họ sẽ tìm ra một chính sách tối ưu, có tính đến việc khám phá (exploration) vốn có trong chính sách.


"Q" ở đây là gì?

Chữ ‘Q’ trong Q-learning là viết tắt của "quality" chất lượng. Chất lượng ở đây thể hiện mức độ hữu ích của một hành động (action) nhất định trong việc đạt được một số phần thưởng (reward) trong tương lai.


Yếu tố chính của Q-learning

  • Q*(s, a) là giá trị kỳ vọng (phần thưởng chiết khấu tích lũy) của việc thực hiện hành động (action) a ở trạng thái (state) s và sau đó tuân theo chính sách tối ưu (optimal policy).
  • Q-learning sử dụng "Sự khác biệt theo thời gian" Temporal Differences (TD) để ước tính giá trị của Q*(s, a). TD là một chủ thể (agent) có khả năng học hỏi từ môi trường thông qua các giai đoạn (episodes) mà không có kiến ​​thức trước về môi trường.
  • Chủ thể (agent) duy trì một bảng Q[S, A], trong đó S là tập các trạng thái và A là tập các hành động.
  • Q[ssđại diện cho ước tính hiện tại của nó là Q*(s, a).


Ví dụ

Giả sử một nhân viên phải di chuyển từ điểm bắt đầu đến điểm kết thúc dọc theo một con đường có chướng ngại vật. Nhiệm vụ cần đạt được tìm đường ngắn nhất có thể mà không va vào chướng ngại vật và anh ta cần đi theo ranh giới được che bởi chướng ngại vật. 


Để tiến hành thực hiện, trước hết ta cần định nghĩa thêm các khái niệm sau:
Q-table là bảng cấu trúc dữ liệu được sử dụng để tính toán phần thưởng (reward) dự kiến ​​tối đa trong tương lai cho hành động (action) ở mỗi trạng thái (each state). Về cơ bản, bảng này sẽ hướng dẫn chúng ta hành động tốt nhất ở mỗi trạng thái. Để tìm hiểu từng giá trị của Q-table, thuật toán Q-Learning được sử dụng.
Hàm Q: sử dụng phương trình Bellman và nhận hai đầu vào: trạng thái (s) và hành động (a).

Bellman Equation. Source: link


Quy trình xử lý của thuật toán Q-learning

Q-learning Algorithm

Bước 1: Khởi tạo Q-Table 

Có n cột, trong đó n = số hành động (action). Có m hàng, trong đó m = số trạng thái (state).

Trong ví dụ của chúng ta, n = Đi trái, Đi phải, Đi lên và Đi xuống và m = "Bắt đầu, Không hoạt động, Đường đúng, Đường sai và Kết thúc". Đầu tiên, hãy khởi tạo các giá trị bằng các giá trị 0.

Initial Q-table

Bước 2: Chọn một hành động

Bước 3: Thực hiện một hành động

Sự kết hợp của bước 2 và bước 3 được thực hiện trong một khoảng thời gian không xác định. Các bước này chạy cho đến khi quá trình huấn luyện thời gian bị dừng lại hoặc khi vòng lặp huấn luyện dừng lại như được xác định trong mã.

Đầu tiên, một action (a) hành động trong trạng thái state (s)  được chọn dựa trên Q-Table. Lưu ý rằng, như đã đề cập trước đó, khi tập ban đầu bắt đầu, mọi giá trị Q phải bằng 0.

Sau đó, cập nhật các giá trị Q để ở đầu và di chuyển sang phải bằng cách sử dụng phương trình Bellman được nêu ở trên.

Khái niệm Epsilon greedy strategy xuất hiện ở đây. Trong thời gian đầu, tỷ lệ epsilon sẽ cao hơn. Chủ thể (agent) sẽ khám phá môi trường và lựa chọn ngẫu nhiên các hành động (action). Điều này xảy ra như thế này một cách hợp lý, vì agent không biết gì về môi trường. Khi agent tham dò môi trường, tỷ lệ epsilon giảm và agent bắt đầu khám phá môi trường.Trong quá trình thăm dò (exploration), agent dần dần tự tin hơn trong việc ước tính các giá trị Q.

Trong ví dụ, khi bắt đầu đào tạo agent của chúng taagent hoàn toàn không biết về môi trường. Vì vậy, giả sử nó thực hiện một hành động ngẫu nhiên theo hướng "phải" của nó.

Giờ đây, chúng tôi có thể cập nhật các giá trị Q ở thời điểm bắt đầu và chuyển động sang phải bằng cách sử dụng phương trình Bellman.

Updated Q-table

Bước 4: Đo phn thưởng
Bây gi chúng tôi đã thc hin mt hành động và quan sát mt kết qu và phn thưởng.
Bước 5: Đánh giá
Chúng ta cn cp nht hàm Q(s, a).
Quá trình này được lp đi lp li nhiu ln cho đến khi ngng hc. Bng cách này, Q-Table được cp nht và hàm giá tr Q được ti đa hóa. đây Q (trng thái, hành động) tr v phn thưởng d kiến ​​trong tương lai ca hành động đó ti trng thái đó.
Bellman Equation Explanation for the episodes

Trong ví d, tôi đã nhp sơ đồ khen thưởng như sau.
  • Phn thưởng khi tiến gn hơđến mc tiêu = +1
  • Phn thưởng khi đạt chướng ngi vt = -1
  • Phn thưởng khi nhàn ri = 0

Ban đầu, chúng ta khám phá môi trường ca chủ thể (agent) và cp nht Q-Table. Khi Q-Table đã sn sàng, agent bt đầu khám phá môi trường và bt đầu thc hin các hành động tt hơn. Q-Table cui cùng có th ging như sau (ví d).

Example final Q-table

Sau đây là những kết quả dẫn đến con đường ngắn nhất của nhân viên hướng tới mục tiêu sau khi đào tạo.

Giao dịch đầu tiên của Bitcoin - "Cha đẻ của Bitcoin là ai?"

7:10:00 AM 0
Giao dịch đầu tiên của Bitcoin - "Cha đẻ của Bitcoin là ai?"

Hôm nay là kỷ niệm giao dịch đầu tiên của Bitcoin (BTC) 13 năm trước (Jan-12-2009), và người đầu tiên nhận Bitcoin từ SatoshiHal Finney... Không ai biết Satoshi là ai nhưng khả năng cao là Hal Finney và người này đã viết lại cảm nhận của mình về BTC trước khi ra đi.


[1] “Tôi nghĩ tôi sẽ viết về những gì đã xảy ra trong bốn năm qua, một thời gian sôi động cho Bitcoin và tôi.
Đối với những người không biết tôi, tôi là Hal Finney. Tôi bắt đầu làm việc cho crypto trong phiên bản đầu tiên của PGP, làm việc chặt chẽ với Phil Zimmermann. Khi Phil quyết định bắt đầu Tổng công ty PGP, tôi là một trong những người được thuê đầu tiên. Tôi đã làm việc trên PGP cho đến khi nghỉ hưu. Đồng thời, tôi đã tham gia đội Cypherpunks. Tôi đã chạy lập trình chuyển đổi ẩn danh dựa trên thuật toán mật mã đầu tiên, và một số các hoạt động khác.
    Đến cuối năm 2008, tôi đã nhận được thông báo về Bitcoin. Tôi đã nhận thấy rằng những người có tổi như tôi (tôi đã ở tuổi 50 lúc đó) thì hay hoài nghi. Nhưng tôi là một người rất có lý tưởng; tôi luôn yêu crypto, sự bí ẩn và các nghịch lý của nó.
Khi Satoshi công bố Bitcoin trên các danh sách người đam mê công nghệ kỹ thuật số, nhiều người đã rất hoài nghi. Các nhà mật mã hóa đã nhìn thấy quá nhiều kế hoạch lớn bởi những người không hiểu biết.
    Tôi đã tích cực hơn. Tôi đã rất quan tâm đến các kế hoạch thanh toán bằng mật mã. Thêm vào đó, tôi đã may mắn gặp được và liên hệ với Wei DaiNick Szabo, những người được thừa nhận đã tạo ra những ý tưởng ban đầu và đã dẫn tới sự ra đời của Bitcoin. Tôi đã tạo ra một loại tiền mã hóa kỹ thuật số trước đó gọi là RPOW, vì vậy, tôi rất hứng thú với Bitcoin.
    Khi Satoshi công bố phiên bản phần mềm đầu tiên, tôi đã thử nó ngay lập tức. Tôi nghĩ rằng tôi là người đầu tiên bên cạnh Satoshi để chạy Bitcoin. Tôi đào khối 70 và tôi là người nhận giao dịch Bitcoin đầu tiên trên thế giới khi Satoshi gửi 10 Bitcoin cho tôi để kiểm tra. Tôi tiếp tục nói chuyện qua email với Satoshi trong vài ngày tới, hầu hết là tôi đã báo cáo lỗi và anh ta đã khắc phục chúng.
    Ngày nay, ai là Satoshi đã trở thành một bí ẩn. Nhưng vào thời điểm đó, tôi nghĩ tôi đang làm việc với một người đàn ông trẻ tuổi gốc Nhật, một người rất thông minh và chân thành. Tôi đã may mắn để biết nhiều người như vậy trong suốt quãng đời của mình, vì vậy tôi nhận ra Satoshi là một người như vậy.
    Sau vài ngày, Bitcoin đã chạy ổn định, vì vậy tôi cứ để nó chạy. Đó là những ngày mà độ khó đào Bitcoin là 1, và bạn có thể đào Bitcoin thành công với mấy vi tính cá nhân, thậm chí không cần card đồ họa. Tôi đã đào vài khối Bitcoin trong những ngày tiếp theo. Nhưng tôi đã tắt máy sau đó vì nó làm cho máy tính của tôi nóng, và tiếng ồn của quạt làm phiền tôi. Nhìn lại, tôi ước gì mình tiếp tục cho nó chạy, nhưng mặt khác tôi đã rất may mắn được chứng kíến ngay từ đầu.
Tiếp theo, tôi nghe nói về Bitcoin vào cuối năm 2010, khi tôi ngạc nhiên khi thấy rằng nó không những không dừng lại mà Bitcoins thực sự có giá trị tiền tệ. Tôi đã dọn dẹp cái ví điện tử cũ của mình, và nhẹ nhõm khi phát hiện ra rằng những Bitcoin của tôi vẫn còn đó. Khi giá tiếp tục đi lên, tôi chuyển Bitcoin vào ví cá nhân và hy vọng họ sẽ có giá trị cho người thừa hưởng gia tài của tôi.
    Nói về thừa hưởng gia tài, tôi đã nhận được một tin bất ngờ trong năm 2009, khi tôi đã được chẩn đoán đột ngột với một căn bệnh chết người. Tôi đã có sức khoẻ rất tốt, có thể là tốt nhất từ trước tới giờ vào đầu năm đó, tôi đã giảm cân vì bắt đầu tập chạy dường dài. Tôi muốn chạy nhiều marathon nhỏ, và tôi đã bắt đầu để đào tạo để chạy một marathon lớn. Tôi nghĩ tôi đã có thể chạy 20 dặm đường, đó là khi mọi thứ sụp đỗ.
    Cơ thể tôi bắt đầu suy giảm. Lời nói của tôi bị lẩm bẩm, tay bị mất sức, và đôi chân của tôi đã phục hồi rất chậm. Vào tháng tám năm 2009, tôi đã được chẩn đoán ALS, còn được gọi là bệnh của Lou Gehrig, tên được biết tới sau khi cầu thủ bóng chày nổi tiếng đã bị bệnh này. ALS là một căn bệnh giết chết các tế bào thần kinh vận động, mang tín hiệu từ não đến các cơ. Nó bắt đầu làm cho các cơ bắp yếu đi, sau đó dần dần gia tăng tê liệt. Nó thường gây tử vong trong vòng 2 đến 5 năm. Các triệu chứng của tôi lúc đầu nhẹ và tôi tiếp tục làm việc, nhưng các vấn đề về mệt mỏi và giọng nói buộc tôi phải nghỉ hưu vào đầu năm 2011. Kể từ đó, căn bệnh đã tiếp tục tiến triển.
    Hôm nay, tôi cơ bản là bị tê liệt. Tôi được cho ăn ống qua ống thực phẩm, và hơi thở của tôi được trợ giúp thông qua một ống khác. Tôi vận hành máy tính bằng cách sử dụng một hệ thống eyetracker (di chuyển bằng mắt). Nó cũng được hỗ trợ bằng tiếng nói nhân tạo, vì vậy đây là tiếng nói của tôi bây giờ. Tôi dành cả ngày trong xe lăn điện của tôi. Tôi đã làm việc lên một giao diện để có thể điều chỉnh vị trí xe lăn của tôi bằng cách sử dụng mắt của tôi.
    Tôi đã phải thích nghi với cuộc sống này, nhưng cuộc sống của tôi không phải là quá xấu. Tôi vẫn có thể đọc, nghe nhạc, xem TV và xem phim. Gần đây tôi đã phát hiện ra rằng tôi thậm chí có thể viết mã vi tính tuy là rất chậm, có lẽ chậm hơn 50 lần so với trước đây. Nhưng tôi vẫn thích lập trình và nó mang lại cho tôi mục tiêu đời sống. Hiện tại, tôi đang nghiên cứu cái mà Mike Hearn đề xuất, sử dụng các tính năng bảo mật của hệ thống xử lý hiện đại, được thiết kế để hỗ trợ "Máy tính tin cậy", để làm chặt các ví tiền Bitcoin. Tôi đã gần như đã sẵn sàng để phát hành phần này. Tôi chỉ cần làm các tài liệu hướng dẫn.
    Và dĩ nhiên, sự xoay vòng giá của Bitcoin đang là giải trí cho tôi. Tôi nhận được Bitcoin của tôi thông qua may mắn. Tôi đã trải qua vụ sụp giá năm 2011. Vì vậy, tôi đã đã hiểu được, tiền đến thì tiền lại đi.
    Đây là câu chuyện của tôi, tôi khá may mắn. Ngay cả với bệnh ALS, cuộc sống của tôi rất thỏa mãn nhưng tuổi thọ của tôi đã bị hạn chế. Bitcoin của tôi được lưu trữ trong một két an toàn, và con trai tôi và con gái của tôi am hiểu công nghệ cao. Tôi nghĩ rằng chúng sẽ giữ an toàn và tôi cảm thấy thoải mái với di sản của mình.”


[2] Sau khi ông mất, não cũng như cơ thể của ông vẫn được bảo quản với nhiệt độ -320 F (-195,6 C) tại Alcor Life Extension Foundation chờ ngày hồi sinh. Hy vọng khoa học có thể làm hồi sinh não của ông và cho chúng ta câu trả lời "cha đẻ của Bitcoin là ai!"

Ref.

Sunday, November 21, 2021

[RL series] Dạo quanh Reinforcement Learning

1:10:00 PM 0
[RL series] Dạo quanh Reinforcement Learning

Reinforcement Learning là gì?

Illustration of a reinforcement learning problem

Fig. 1. An agent interacts with the environment, trying to take smart actions to maximize cumulative rewards.

Giả sử, chúng tôi có một đại lý trong một môi trường không xác định và đại lý này có thể nhận được một số phần thưởng bằng cách tương tác với môi trường. Người đại diện phải thực hiện các hành động để tối đa hóa phần thưởng tích lũy. Trong thực tế, kịch bản có thể là một bot chơi trò chơi để đạt được điểm số cao, hoặc một robot cố gắng hoàn thành các nhiệm vụ vật lý với các vật phẩm vật lý; và không chỉ giới hạn ở những thứ này.

Bạn đã bao giờ trách móc hoặc đánh đập con chó của mình một cách nghiêm khắc vì những hành động sai trái sau khi nó làm chưa? Hay bạn đã bao giờ huấn luyện một con vật cưng và thưởng nó cho mỗi lệnh đúng mà bạn yêu cầu chưa? Nếu bạn là chủ sở hữu vật nuôi, có lẽ câu trả lời của bạn sẽ là ‘Có’. Bạn có thể nhận thấy một khi bạn làm như vậy thường xuyên từ khi nó còn nhỏ, những việc làm sai trái của nó giảm dần từng ngày. Và cũng giống như nó sẽ học hỏi từ những sai lầm và rèn luyện bản thân thật tốt.

Là con người, chúng ta cũng đã từng trải qua điều tương tự. Bạn có nhớ không, ở trường tiểu học của chúng tôi, các giáo viên của trường chúng tôi đã thưởng cho chúng tôi những ngôi sao khi chúng tôi đã hoàn thành tốt các công việc của trường. Đây chính xác là những gì đang xảy ra trong "Học tăng cường" (RL).

Reinforcement Learning is one of the most beautiful branches in Artificial Intelligence

Mục tiêu của RL là tìm kiếm một chiến lược tốt cho "chủ thể" từ các "trải nghiệm" và nhận được phản hồi từ những tương tác với môi trường. Với chiến lược tối ưu, chủ thể có khả năng chủ động thích ứng với môi trường để tối đa hóa phần thưởng trong tương lai.

Các khái niệm chính trong RL

Chủ thể (agent) đang hoạt động trong môi trường (environment). Cách môi trường phản ứng với các hành động nhất định được xác định bởi một mô hình (model) mà chúng ta có thể biết hoặc có thể không biết. Chủ thể (agent) là người đưa ra quyết định (make a decision), có thể ở một trong nhiều trạng thái (states) (sS) của môi trường, và chọn thực hiện một trong nhiều hành động (actions) (a ∈ A) để chuyển từ trạng thái này sang trạng thái khác. Trạng thái nào mà chủ thể sẽ có được quyết định bởi xác suất (probabilities) chuyển đổi giữa các trạng thái (P). Khi một hành động được thực hiện, môi trường mang lại phần thưởng (reward) (r ∈ R) dưới dạng phản hồi.


RL là khoa học về việc đưa ra các quyết định tối ưu bằng cách sử dụng kinh nghiệm. Chi tiết hơn, quá trình RL bao gồm các bước đơn giản sau:

1. Quan sát môi trường (Observation)
2. Quyết định cách hành động bằng một số chiến lược (Decision)
3. Hành động phù hợp (Action)
4. Nhận phần thưởng hoặc hình phạt (reward/penalty)
5. Học hỏi kinh nghiệm và hoàn thiện chiến lược của chúng tôi (Learn)
6. Lặp lại cho đến khi tìm được chiến lược tối ưu
Source: link

Mô hình hóa toán học của RL

1. Đây là một ví dụ trực quan về Agent:

2. Enviroment xung quang của Agent, nơi mà agent tồn tại và tương tác:

3. Dựa trên State S(t) của enviroment hiện tại mà agent sẽ đưa ra action a(t):

4. Sau khi nhận được sự tương tác từ agent thì enviroment có sự chuyển đổi trạng thái đối với agent:

5. State lúc này của enviroment là S(t+1), tức ở thời điểm t+1:

6. Lúc này, agent nhận được reward r(t)Reward này phụ thuộc vào action a(t) của agent và State S(t) của enviroment ở thời điểm trước đó, tức là ở thời điểm t:

7. Vì ta không biết thời điểm kết thúc của sự lặp đi lặp lại này nên tổng reward sẽ là một chuỗi vô hạn của các reward thành phần tại các thời điểm khác nhau kể từ thời điểm t (lúc đầu):

8. Chúng ta có thể khai triển chuỗi vô hạn này như sau:

9. Vì chuỗi này không thể nào hội tụ (convergence) được nên trên thực tế các nhà nghiên cứu có thể dùng một cái trick để chuỗi này có thể hội tụ được. Như hình dưới đây, họ đưa vào thêm một term thường được gọi là discount factor (discount rate) để làm cho chuỗi này hội tụ.

*Lưu ý việc hội tụ là bắt buộc nếu bạn muốn train thành công một agent nói riêng hay một mạng Neural Network nào đó nói chung.

Tất cả những thứ trên nó dựa trên một framework được gọi là Markov Decision Processes (MDPs). Về cơ bản thì một MDP cung cấp một framework toán học cho việc modelling các tình huống decision-making. Ở đây, các kết quả (outcomes) xảy ra một cách ngẫu nhiên một phần và phần còn lại thì phụ thuộc trên các action của agent (hoặc decision maker) đã tạo ra trước đó. reward thu được bởi decision maker phụ thuộc trên action mà decision maker chọn và dựa trên cả hai State mới (S(t+1)) và cũ (S(t)) của enviroment.

Để có thể train được agent thì mục tiêu của chúng ta là phải tìm được policy \pi sao cho:

 là discount factor và  < 1
Về cơ bản thì chúng ta đang cố gắng để maximize tổng của tất cả các reward (có tính đến discount factor như đã đề cập ở trên) ở mỗi state cụ thể từ lúc bắt đầu đến khi kết thúc (dẫu cho T tiến về vô cùng, vì chúng ta chưa biết khi nào thì quá trình này kết thúc nên nó vẫn luôn là một chuỗi vô hạn), và đương nhiên là phải dựa trên policy   agent của chúng ta base trên nó để chọn reward tốt nhất mà. Bản chất thì đây là một bài toán tối ưu (optimazation problem).

Ở trên là một tiêu chí mà chúng ta có thể dùng để optimize cho việc tìm ra nghiệm (optimal policy). Cụ thể chúng ta gọi tiêu chí này là infinite horizon sum reward criteriaPhụ thuộc vào các criteria khác nhau mà chúng ta sẽ có các algorithm khác nhau để tìm ra optimal policy. Với infinite horizon sum reward criteria thì chúng ta có thể sử dụng một thuật toán RL cũng khá kinh điển đó là Q-Learning để giải quyết, tôi sẽ giới thiệu trong bài viết tiếp theo.

Phân loại các phương án trên RL

Để phân loại rõ ràng các thuật toán trên RL khá phức tạp, chúng ta có thể nhìn hình bên dưới và tạm thời chia theo vài trường hợp chính: 


Categorization of RL Algorithms

Fig. 2. Summary of approaches in RL based on whether we want to model the value, policy, or the environment. (Image source: reproduced from David Silver’s RL course lecture 1.)

  • Model-free: thuật toán ước tính chính sách tối ưu mà không cần sử dụng hoặc ước tính động lực học (chức năng chuyển đổi và phần thưởng) của môi trường. 
  • Model-based là một thuật toán sử dụng hàm chuyển tiếp (và hàm phần thưởng) để ước tính chính sách tối ưu.
  • On-policy: Sử dụng kết quả xác định hoặc mẫu từ chính sách mục tiêu (target policy) để đào tạo (train) thuật toán.
  • Off-policy: Đào tạo về cách phân phối các chuyển đổi (transitions) hoặc các tập (episodes) được tạo ra bởi một chính sách (policy) hành vi khác chứ không phải do chính sách mục tiêu tạo ra.
Ngoài ra, nếu nhìn tổng quát hơn ta có thể phân loại Rl thành những nhóm như hình bên dưới

Tiếp theo, để tạo nền tảng kiến thức vững vàng trước khi đi vào phân tích cũng như phát triển thuật toán trên RL các bạn nên tìm đọc và hiểu về cách khái niệm như Trasition, Reward, Policy, Value Function,... đặc biệt là 
Markov Decision ProcessesBellman Equations (có thời gian mình sẽ phân tích thêm về phần này) từ sách. 

Ví dụ

Reinforcement Learning: An introduction (link) 

Hoặc tổng hợp khác của tôi ở đây


P/s: từ tài liệu tiếng anh có nhiều từ rất khó để dịch sát nghĩa sang tiếng việt nên khó tránh khỏi sai sót, nhưng vì mong muốn các bạn ở VN có nhiều nguồn tài liệu để tiếp cận hơn. Các bạn có khả năng đọc hiểu tiếng anh thì nên đọc sách góc sẽ tốt hơn. Các phần tiếp theo mình đã xử lý dưới xong rồi, mình có thời gian sẽ tiếp tục, kết hợp với code mô phỏng. Hy vọng các bạn tìm thấy được sự thú vị từ đây! have fun :)