FundaML 3: Làm việc với các mảng ngẫu nhiên

Toàn bộ những bài tập trong nội dung bài viết này sở hữu thể được tiến hành trực tiếp trên trình duyện qua website FundaML

Những số trùng hợp đóng một vài ba trò hết sức rất cần thiết trong lập trình chung chung và lập trình Machine Learning nói riêng.

Trong bài học tập này, chúng ta cùng làm thân quen với những hàm tạo những số trùng hợp cơ phiên bản.

3.1. Mảng trùng hợp những số tuân theo phân chia đều

Một trong mỗi điều rất cần thiết nhất lúc lập trình một tiếng nói ngẫu nhiên là phương pháp dùng những hàm trùng hợp. Trong bài này, chúng ta sẽ làm thân quen tới những hàm trùng hợp trong Numpy và những phương pháp dùng chúng trong những vấn đề Machine Learning.

3.1.1. Hàm numpy.random.rand

Hàm numpy.random.rand trả về một mảng những số trùng hợp nhưng mỗi phần tử là một vài trùng hợp sở hữu phân chia đều (uniform distribution) trong nửa đoạn [0, 1):

  • Nếu số lượng input là 0, hàm trả về một số vô hướng.

  • Nếu có inputs (là các số nguyên dương), hàm này trả về một mảng ngẫu nhiên có số chiều bằng với số inputs, kích thước mỗi chiều bằng với giá trị của các inputs.

3.1.2. Hàm np.random.seed

Các ngôn ngữ lập trình nói chung không tạo ra các giá trị ‘thực sự ngẫu nhiên’. Thật vậy, nếu bạn mở python và bắt đầu với:

thì kết quả luôn là các số giống nhau ở mỗi lần thử (bạn hãy thoát python và thử lại nhiều lần xem). Như trên máy tính của tôi, kết quả lúc nào cũng là 0.38919680466308004. Như vậy, hàm ngẫu nhiên không thực sự sinh ra các giá trị ngẫu nhiên. Tuy nhiên, nếu thực hiện hàm này rất nhiều lần, chúng ta sẽ thu được các các số nằm trong khoảng [0, 1) mà xác suất để một điểm nằm trong đoạn [a, b] với 0 <= a < b < 1 bằng b – a.

Hàm np.random.seed() là một trong những hàm được xem như hỗ trợ khởi tạo những bộ sinh số trùng hợp (random generator). Trở thành số trong seed thường xuyên là một vài nguyên ko âm 32 bit. Với những trị giá của phát triển thành số không giống nhau thì sẽ cho ra những số trùng hợp không giống nhau.

Hàm số này được sử dụng để đối chiều hậu quả trong những lần chạy không giống nhau trong những vấn đề Machine Learning. Rất nhiều những thuật toán Machine Learning chạy dựa trên việc tính toán trùng hợp (ví dụ, Stochastic Gradient Descent được dùng rất nhiều trong những thuật toán tối ưu Neural Networks). Để phân tích hậu quả trong nhiều lần chạy trên, người ta thường xuyên khởi tạo những random generator với những seed như nhau.

Những khách du lịch sở hữu thể quan tâm thấy rằng trong những bài trước tôi thường xuyên sử dụng np.random.seed(). Việc đấy để đảm nói rằng hậu quả khách du lịch tìm được tương tự với hậu quả trong code mẫu.

Bài tập: Cho những số a, b, m, n trong đấy a < b là nhì số thực ngẫu nhiên; m, n là những số nguyên dương. Viết lách hàm số tạo một mảng nhì chiều sở hữu shape = (m, n), những phần tử là những số trùng hợp phân chia đều trong nửa đoạn [a, b).

Chú ý:

  1. Để kiểm tra mảng trả về có đúng là mảng ngẫu nhiên các phần tử trong nửa đoạn ([a, b)) hay không, tôi sẽ tính kỳ vọng (mean) và phương sai (variance) của các phần tử trong mảng đó. Tôi biết rằng nếu (X) là một biến ngẫu nhiên tuân theo phân phối chuẩn trong nửa đoạn ([a, b)) thì nó sẽ có kỳ vọng và phương sai lần lượt là: [ frac{b+a}{2}; quad frac{(b-a)^2}{12} ]

Xem xét rằng đây chỉ là điều khiếu nại cần, ko phải điều khiếu nại đầy đủ.

  1. Nếu X là một trong những phát triển thành trùng hợp tuân theo phân phối chuẩn chỉnh trong nửa đoạn [0, 1) thì Y = aX + b là một biến ngẫu nhiên tuân theo phân phối chuẩn trong nửa đoạn [b, a + b) nếu a là một số dương, hoặc [a+b, b) nếu a là một số âm.

3.2. Mảng ngẫu nhiên các số tuân theo phân phối chuẩn

Phân phối chuẩn (normal distribution) hay phân bố Gassian (Gassian distribution) rất quan trọng trong thực tế và các bài toán kỹ thuật.

Hàm numpy.random.randn() (chữ n ở cuối là viết tắt của normal) có chức năng tương tự như hàm np.random.rand nhưng kết quả trả về là mảng có các phần tử phân bố theo phân phối chuẩn có kỳ vọng bằng 0 và phương sai bằng 1.

Bài tập: Cho các số a, s, m, n với:

  • a là một số thực bất kỳ.
  • s là một số thực dương.
  • m, n là các số nguyên dương.

Xây dựng một mảng ngẫu nhiên hai chiều có shape = (m, n) mà các phần tử của nó tuần theo phân phối chuẩn có kỳ vọng bằng a và phương sai là s.

Chú ý: Ký hiệu (mathcal{N}(mu, sigma^2)) để chỉ một phân phối chuẩn có kỳ vọng (mu) và phương sai (sigma^2). Một biến ngẫu nhiên (X) tuân theo phân phối chuẩn có kỳ vọng (mu), phương sai (sigma^2) sẽ được ký hiệu là (X sim mathcal{N}(mu, sigma^2)).

Nếu (X sim mathcal{N}(mu, sigma^2)) thì:

  • (X+a sim mathcal{N}( mu+a, sigma^2)) với (a) là một số thực bất kỳ.
  • (kX sim mathcal{N}(kmu, k^2sigma^2)) với (k) là một số thực bất kỳ.

3.3. Mảng ngẫu nhiên các số nguyên

Hàm tạo mảng các số tự nhiên ngẫu nhiên. Bạn đọc có thể tham khảo trực tiếp cách sử dụng trong numpy document:

Chú ý cụm “discrete uniform” distribution. Điều này tức là mỗi số nguyên trong nửa đoạn [low, high) sẽ xuất hiện với xác suất bằng nhau. Ví dụ:

Phần này không có bài tập.

3.4. Hoán vị

Ví dụ trên đây có mục đích là tạo ra một mảng có 10 phần tử bao gồm các số tự nhiên từ 0 đến 9 sắp xếp theo thứ tự ngẫu nhiên. Mảng này còn được gọi là một hoán vị của các số từ 0 đến 9.

Hoán vị ngẫu nhiên được sử dụng rất nhiều khi xử lý dữ liệu trong Machine Learning. Dưới đây là hai ví dụ điển hình.

3.4.1. Stochastic Gradient Descent.

Trong Stochastic Gradient Descent, việc quan trọng nhất là ở mỗi epoch, chúng ta cần trộn lẫn thứ tự của dữ liệu và lấy ra từng mini-batch trong đó. Cụ thể, nếu coi toàn bộ dữ liệu là một ma trận, mỗi hàng là một điểm dữ liệu và có tổng cộng (N) điểm. Tại mỗi iteration, ta sẽ lấy ra một tập con (k) điểm dữ liệu, với (k ll N) để cập nhật nghiệm. Trong một epoch, ta cần đảm bảo rằng tất cả các điểm dữ liệu đều được lấy ra tại một minibatch nào đó và không có điểm nào được lấy quá một lần (giả sử rằng (N) chia hết cho (k)). Và hơn nữa, việc lấy ra các minibatch ở mỗi epoch là khác nhau.

Việc này có thể được thực hiện bằng cách tạo ra một hoán vị ngẫu nhiên của các số từ (0)( đến (N-1) và coi chúng như chỉ số của các điểm dữ liệu. Tại minibatch thứ nhất, ta lấy ra các hàng có chỉ số tương ứng với (k) số đầu tiên trong hoán vị tìm được. Lần lượt như vậy cho tới khi minibatch cuối cùng được lấy ra. Sau đó ta lại trộn lẫn dữ liệu bằng một hoán vị ngẫu nhiên khác.

3.4.2. Chia dữ liệu training và test

(Bạn đọc có thể tham khảo cách trực tiếp sử dụng thư viện tại đây)

Khi kiểm tra một thuật toán Machine Learning, người ta thường chia tập dữ liệu thu được thành hai phần: training và test (có thể có thêm validation). Một điều quan trọng là phần phân chia này phải được tạo một cách ngẫu nhiên để tránh việc dữ liệu được phân chia một cách quá thiên lệch (biased). Và đây là lúc chúng ta có thể sử dụng các hoán vị ngẫu nhiên.

Giả sử có 100 điểm dữ liệu, ta cần lấy ngẫu nhiên ra 70 điểm làm training test, 30 điểm còn lại làm test set. Cách đơn giản nhất là tạo một hoán vị ngẫu nhiên của các số từ 0 đến 99. Sau đó 70 điểm có chỉ số là 70 phần tử đầu tiên của mảng hoán vị được dùng làm training set, 30 điểm còn lại được dùng làm test set.

Bài tập: Cho hai số tự nhiên N > k > 0 viết hàm số sample_no_replace(N, k) trả về ngẫu nhiên k số tự nhiên nằm trong tập {0, 1, …, N-1} sao cho không có hai số nào trùng nhau.

Việc ngẫu nhiên ở đây sẽ được kiểm chứng bằng cách gọi hàm sample_no_replace(N, k) nhiều lần. Trong toàn bộ các kết quả trả về, tần suất xuất hiện của mỗi số trong tập {0, 1, …, N-1} phải gần bằng nhau.

Giả sử X là ma trận chứa N điểm dữ liệu theo hàng. Nếu idx =sample_no_replace(N, k) là kết quả trả về của hàm bạn đã viết, k điểm ngẫu nhiên của X có thể được lấy ra bằng X[idx, :].

(còn nữa)