Bỏ qua nội dung

Làm Việc Với Hành Động Liên Tục

Hãy bắt đầu với dự án từ hướng dẫn trước của chúng ta và thêm hành động liên tục vào nó. Bạn có thể theo dõi bằng cách sử dụng dự án khởi động hoặc kiểm tra dự án hoàn chỉnh nếu bạn thích.

Hành Động Rời Rạc và Liên Tục

Trong hướng dẫn trước, chúng ta đã làm việc với hành động rời rạc - tác nhân của chúng ta phải chọn giữa một tập hợp hữu hạn các tùy chọn (0 hoặc 1) để khớp với một mẫu. Trong các tình huống thực tế, chúng ta có thể nhận được nhiều dữ liệu cảm biến và đầu vào hình ảnh để quyết định nút nào cần nhấn.

Tuy nhiên, trong nhiều ứng dụng thế giới thực, điều này không phải lúc nào cũng khả thi. Để điều khiển những thứ như:

  • Góc lái trong phương tiện
  • Mô-men xoắn khớp nối trong cánh tay robot
  • Mức công suất trong động cơ

Tác nhân của chúng ta sẽ cần đưa ra hành động liên tục—giá trị dấu phẩy động chính xác thay vì lựa chọn phân loại.

Thêm Hành Động Liên Tục Vào Môi Trường Của Chúng Ta

Hãy sửa đổi môi trường của chúng ta để bao gồm cả hành động rời rạc và liên tục. Chúng ta sẽ giữ nguyên nhiệm vụ khớp mẫu ban đầu nhưng thêm một mẫu thứ hai, trong đó chúng ta mong đợi AI xuất ra căn bậc hai của giá trị mới này.

Lưu ý cách chúng ta không thay đổi gì ngoại trừ KỲ VỌNG của chúng ta—tác nhân sẽ cần tìm ra điều chúng ta muốn thông qua thử và sai, chỉ được hướng dẫn bởi tín hiệu phần thưởng!

Đầu tiên, thêm các trường mới để theo dõi mẫu thứ hai và hành động liên tục trong PatternMatchingEnvironment.cs:

PatternMatchingEnvironment.cs
private int pattern = 0;
private int pattern2 = 0;
private int aiChoice = 0;
private float aicontinuousChoice = 0f;
private bool roundFinished = false;

Tiếp theo, thêm phương thức quan sát thứ hai và phương thức hành động liên tục của chúng ta:

PatternMatchingEnvironment.cs
[RLMatrixObservation]
public float SeePattern() => pattern;
[RLMatrixObservation]
public float SeePattern2() => pattern2;
[RLMatrixActionContinuous]
public void MakeChoiceContinuous(float input)
{
aicontinuousChoice = input;
}

Bây giờ, hãy tạo các hàm phần thưởng của chúng ta:

PatternMatchingEnvironment.cs
[RLMatrixReward]
public float GiveReward() => aiChoice == pattern ? 1.0f : -1.0f;
// Thêm phần thưởng +2 khi đầu ra liên tục của AI gần với căn bậc hai
// của mẫu thứ hai
[RLMatrixReward]
public float ExtraRewards() => Math.Abs(aicontinuousChoice - Math.Sqrt(pattern2)) < 0.1f ? 2f : 0.0f;

Cuối cùng, chúng ta cần cập nhật phương thức StartNewRound để tạo ra cả hai mẫu:

PatternMatchingEnvironment.cs
[RLMatrixReset]
public void StartNewRound()
{
pattern = Random.Shared.Next(2);
pattern2 = Random.Shared.Next(10);
aiChoice = 0;
roundFinished = false;
}

Lưu ý rằng chúng ta đang sử dụng phạm vi 0-9 cho pattern2, điều này tạo ra một thử thách thú vị hơn cho tác nhân của chúng ta trong việc dự đoán các căn bậc hai khác nhau.

Sửa Lỗi Biên Dịch

Khi bạn cố gắng biên dịch giải pháp, bạn sẽ gặp phải một loạt lỗi. Điều này thực sự hữu ích—RLMatrix sử dụng kiểu dữ liệu mạnh để ngăn chặn lỗi runtime và hướng dẫn bạn đến cách triển khai chính xác cho hành động liên tục.

Lỗi 1: Không Khớp Loại Môi Trường

Argument 1: cannot convert from 'PatternMatchingExample.PatternMatchingEnvironment' to 'RLMatrix.IEnvironmentAsync<float[]>'

Điều này xảy ra vì RLMatrix có các giao diện khác nhau cho môi trường liên tục và rời rạc để đảm bảo tính an toàn kiểu. Hãy cập nhật mã của chúng ta trong Program.cs:

Program.cs - Environment Type
var env = new List<IEnvironmentAsync<float[]>> {
var env = new List<IContinuousEnvironmentAsync<float[]>> {
environment,
//new PatternMatchingEnvironment().RLInit() //you can add more than one to train in parallel
};

Lỗi 2: Không Khớp Loại Tác Nhân

Sau thay đổi này, chúng ta sẽ nhận được lỗi thứ hai:

Argument 2: cannot convert from 'System.Collections.Generic.List<RLMatrix.IContinuousEnvironmentAsync<float[]>>' to 'System.Collections.Generic.IEnumerable<RLMatrix.IEnvironmentAsync<float[]>>'

Điều này là do chúng ta đang cố gắng sử dụng một tác nhân rời rạc với một môi trường liên tục. Chúng ta cần thay đổi loại tác nhân:

Program.cs - Agent Type
var agent = new LocalDiscreteRolloutAgent<float[]>(learningSetup, env);
var agent = new LocalContinuousRolloutAgent<float[]>(learningSetup, env);

Lỗi 3: Không Khớp Tùy Chọn Thuật Toán

Điều này dẫn đến lỗi thứ ba của chúng ta:

Argument 1: cannot convert from 'RLMatrix.DQNAgentOptions' to 'RLMatrix.PPOAgentOptions'

Lỗi cuối cùng này cho thấy DQN không tương thích với hành động liên tục. Chúng ta cần chuyển sang PPO (Proximal Policy Optimization), có thể xử lý cả không gian hành động rời rạc và liên tục:

Program.cs - Algorithm Options
var learningSetup = new DQNAgentOptions(
batchSize: 32,
memorySize: 1000,
gamma: 0.99f,
epsStart: 1f,
epsEnd: 0.05f,
epsDecay: 150f
);
var learningSetup = new PPOAgentOptions(
batchSize: 128,
memorySize: 1000,
gamma: 0.99f,
width: 128,
lr: 1E-03f
);

Lần Đào Tạo Đầu Tiên Của Chúng Ta

Bây giờ hãy chạy đào tạo và xem điều gì xảy ra:

Training Output
Step 800/1000 - Last 50 steps accuracy: 42.0%
Press Enter to continue...
Step 850/1000 - Last 50 steps accuracy: 38.0%
Press Enter to continue...
Step 900/1000 - Last 50 steps accuracy: 40.0%
Press Enter to continue...
Step 950/1000 - Last 50 steps accuracy: 38.0%
Press Enter to continue...
Step 1000/1000 - Last 50 steps accuracy: 37.0%
Press Enter to continue...

Bất ngờ! AI hầu như không học được gì. Độ chính xác không vượt quá 50%, và nếu chúng ta kiểm tra bảng điều khiển, chúng ta thấy nó thường xuyên thu thập phần thưởng +1 cho hành động rời rạc (khớp mẫu) nhưng hiếm khi nhận được phần thưởng +2 cho hành động liên tục (dự đoán √pattern2).

Tại Sao Điều Này Xảy Ra?

Hãy tự hỏi: Tại sao AI học khớp hành động rời rạc dễ dàng hơn nhiều so với hành động liên tục?

Bản năng đầu tiên của bạn có thể là tốc độ học tập (lr)—có lẽ nó quá thấp? Hãy thử thay đổi nó thành 1E-02f và chạy lại đào tạo…

Điều đó có giúp ích không? Có lẽ là không. Trên thực tế, bạn có thể nhận thấy rằng mặc dù tác nhân học hành động rời rạc nhanh hơn, nó hầu như không khám phá không gian hành động liên tục, và độ chính xác thậm chí còn tệ hơn khi đào tạo tiến triển.

Vậy điều gì thực sự đang xảy ra?

Thêm Tín Hiệu Hướng Dẫn

Hãy thử khắc phục bằng cách cung cấp tín hiệu phần thưởng hữu ích hơn. Chúng ta sẽ thêm một phần thưởng tăng lên khi tác nhân tiến gần hơn đến căn bậc hai chính xác, thay vì chỉ thưởng cho khớp chính xác:

PatternMatchingEnvironment.cs
[RLMatrixReward]
public float ExtraSupportingReward() => 0.5f / (1 + Math.Abs(aicontinuousChoice - (float)Math.Sqrt(pattern2)));
//Đừng quên đặt lr của bạn trở lại 1E-03f!

Hàm phần thưởng này tạo ra một gradient—một tín hiệu liên tục trở nên mạnh hơn khi tác nhân tiếp cận giá trị chính xác. Ngay cả khi nó không chính xác, nó vẫn nhận được phản hồi về việc liệu nó có đang “ấm hơn” hay “lạnh hơn”.

Hãy chạy lại đào tạo với thay đổi này và xem điều gì xảy ra:

Training Output
Step 850/1000 - Last 50 steps accuracy: 35.0%
Press Enter to continue...
Step 900/1000 - Last 50 steps accuracy: 40.0%
Press Enter to continue...
Step 950/1000 - Last 50 steps accuracy: 47.0%
Press Enter to continue...
Step 1000/1000 - Last 50 steps accuracy: 36.0%
Press Enter to continue...

Chúng ta đang thấy một số cải thiện nhỏ, nhưng vẫn chưa tốt. Bảng điều khiển có thể cho thấy dấu hiệu rằng việc học đang tiến triển, nhưng rõ ràng, chúng ta cần thêm thời gian đào tạo cho nhiệm vụ phức tạp hơn này.

Kéo Dài Thời Gian Đào Tạo

Đối với những thách thức phức tạp hơn như dự đoán hành động liên tục, chúng ta thường cần nhiều bước đào tạo hơn. Hãy sửa đổi chương trình của chúng ta để đào tạo trong 10.000 bước thay vì 1.000:

Program.cs
for (int i = 0; i < 10000; i++)
{
await agent.Step();
if ((i + 1) % 500 == 0)
{
Console.WriteLine($"Step {i + 1}/10000 - Last 500 steps accuracy: {environment.RecentAccuracy:F1}%");
environment.ResetStats();
Console.WriteLine("\nPress Enter to continue...");
Console.ReadLine();
}
}

Thử Nghiệm: Tác Động Của Tốc Độ Học Tập

Khi bạn theo dõi tiến trình đào tạo dài hơn, hãy thử nghiệm với các tốc độ học tập khác nhau. Điều gì xảy ra nếu bạn hạ thấp nó hơn nữa? Điều gì xảy ra nếu bạn tăng nó đáng kể?

Trong các thử nghiệm của tôi, việc đặt tốc độ học tập rất cao khiến mô hình bị mắc kẹt chỉ thu thập phần thưởng +1 cho hành động rời rạc trong khi hoàn toàn không khám phá đầy đủ không gian liên tục.

Bài Học Chính

Thông qua bài tập này, chúng ta đã học được một số bài học quan trọng:

  1. Hành động liên tục vốn khó học hơn so với hành động rời rạc, do vấn đề phần thưởng thưa thớt. Khi có thể, hãy rời rạc hóa không gian hành động của bạn!

  2. Kỹ thuật phần thưởng cực kỳ quan trọng đối với các vấn đề kiểm soát liên tục. Cung cấp tín hiệu về việc “nóng lên” chuyển đổi một nhiệm vụ học tập không thể thành một nhiệm vụ có thể giải quyết được.

  3. Nhiệm vụ phức tạp đòi hỏi thời gian đào tạo nhiều hơn. Khi chúng ta thêm các chiều vào không gian hành động, chúng ta cần tăng thời gian đào tạo tương ứng.

  4. Việc lựa chọn thuật toán là quan trọng. DQN không thể xử lý hành động liên tục, trong khi PPO có thể xử lý không gian hành động rời rạc, liên tục hoặc hỗn hợp.

  5. Điều chỉnh tốc độ học tập là tinh tế, đặc biệt với PPO. Cao hơn không phải lúc nào cũng tốt hơn và đôi khi có thể tệ hơn cho việc khám phá.

Những nguyên tắc này sẽ giúp ích cho bạn khi giải quyết các thách thức học tăng cường phức tạp hơn với RLMatrix.

Kiểm Tra Sự Hiểu Biết Của Bạn

Hiểu Về Hành Động Liên Tục

Bước Tiếp Theo

Bây giờ bạn đã hiểu những thách thức của không gian hành động liên tục và cách giải quyết chúng, bạn đã sẵn sàng để thử một vấn đề học tăng cường cổ điển với các quan sát phức tạp hơn.