Banyak persoalan pemrograman tidak berjalan dengan angka yang pasti: berapa peluang pelanggan datang dalam satu menit, sampel mana yang diambil dari dataset, urutan soal mana yang tampil pada kuis, atau nilai awal apa yang diberikan pada bobot sebuah model machine learning. Modul numpy.random adalah bagian NumPy yang menyediakan pembangkit angka acak untuk kebutuhan semacam itu, lengkap dengan hasil berbentuk array yang cepat dihitung.
Penting dipahami sejak awal: angka yang dihasilkan modul ini sebenarnya pseudorandom. Nilainya ditentukan oleh algoritme yang deterministik, tetapi deretnya lulus uji statistik keacakan sehingga layak dipakai sebagai angka acak. Sifat deterministik ini justru menguntungkan: dengan menetapkan seed (titik awal urutan), kita dapat mengulang hasil yang sama persis — fondasi dari reproducibility.
Bab ini memetakan cakupan section Bilangan Acak:
- Dua API dalam
numpy.random: API lama berbasis fungsi global dan API modern berbasis objekGenerator. - Struktur dua lapis pembangkit angka:
BitGeneratordanGenerator. - Contoh pertama pemakaian
Generatorbeserta sifat urutannya.
Dua API dalam numpy.random #
Hingga NumPy 1.17, satu-satunya cara memakai numpy.random adalah fungsi global: program memanggil np.random.seed(42) untuk menyetel keadaan pembangkit, lalu menarik angka lewat np.random.rand(), np.random.randint(), dan kawan-kawannya. Semua fungsi tersebut berbagi satu keadaan global yang tersembunyi, sehingga bagian program yang berbeda saling memengaruhi urutan angka satu sama lain. NumPy 1.17 memperkenalkan API modern berbasis objek Generator yang dibuat melalui np.random.default_rng(). API lama tetap tersedia demi kompatibilitas, tetapi dokumentasi NumPy menyarankan API modern untuk kode baru.
Tabel berikut memetakan fungsi lama ke padanannya pada objek Generator:
| Kebutuhan | API lama (fungsi global) | API modern (Generator) |
|---|---|---|
| Menyetel sumber acak ber-seed | np.random.seed(42) | rng = np.random.default_rng(42) |
| Uniform pada [0, 1) | np.random.rand(3) | rng.random(3) |
| Uniform pada rentang a sampai b | np.random.uniform(a, b) | rng.uniform(a, b) |
| Bilangan bulat acak | np.random.randint(0, 10) | rng.integers(0, 10) |
| Distribusi normal | np.random.randn(3) | rng.normal(size=3) |
| Sampling anggota array | np.random.choice(data) | rng.choice(data) |
Perbedaan terpenting bukan pada nama method, melainkan pada pemilikan keadaan. Pada API lama, np.random.seed() menyetel keadaan global yang dipakai seluruh program; pada API modern, setiap objek Generator menyimpan keadaannya sendiri sehingga dapat diteruskan antar fungsi tanpa saling mengganggu.
Generator dan BitGenerator #
API modern bekerja dua lapis. Lapis bawah adalah BitGenerator: mesin yang menghasilkan deretan bit mentah yang acak secara statistik. Lapis atas adalah Generator: penerjemah yang mengubah bit mentah menjadi angka sesuai distribusi yang kita minta — integer, uniform, normal, dan lainnya. Alur pembuatan generator modern dapat dirangkum:
np.random.default_rng(seed)membuat objekGenerator.- Objek
Generatortersebut ditopang BitGenerator bawaan, yaituPCG64. - Setiap pemanggilan method (
integers,random,normal, …) meminta bit mentah dariBitGenerator, lalu mengubahnya menjadi angka berdistribusi yang diminta.
| Lapisan | Tugas | Contoh |
|---|---|---|
| BitGenerator | menghasilkan bit mentah | PCG64 (default), MT19937, Philox, SFC64 |
| Generator | mengubah bit menjadi angka berdistribusi tertentu | integers, random, normal, choice |
Pemisahan lapisan membuat kita dapat mengganti mesin pembangkit tanpa mengubah cara pemanggilan distribusi — detail yang jarang dibutuhkan pemula, tetapi berguna ketika hasil riset harus dicocokkan dengan mesin tertentu.
Contoh Pertama Generator #
Kita buat sebuah Generator ber-seed lalu menarik tiga jenis angka sekaligus:
import numpy as np
rng = np.random.default_rng(42)
print(rng.integers(0, 10, size=5))
print(rng.random(3))
print(rng.normal(loc=27.5, scale=2.0, size=3))Output yang Dihasilkan:
[0 7 6 4 4]
[0.69736803 0.09417735 0.97562235]
[27.75568081 26.86751482 27.46639768]Bedah baris demi baris:
- Baris 3 (
rng = np.random.default_rng(42)): fungsidefault_rngmembuat objekGeneratoryang ditopang BitGeneratorPCG64. Angka42adalah seed, yaitu titik awal urutan — pembahasannya lengkap pada Chapter Reproducibility dan Random Seed. - Baris 4 (
rng.integers(0, 10, size=5)): lima bilangan bulat acak pada rentang0sampai9. Batas atas bersifat eksklusif, aturan yang dibedah tuntas pada Chapter Random Integer dan Sampling. - Baris 5 (
rng.random(3)): tiga angka pecahan berdistribusi uniform pada interval[0, 1)— topik utama Chapter Uniform Distribution. - Baris 6 (
rng.normal(...)): tiga angka pecahan berdistribusi normal dengan rata-rata27.5dan simpangan baku2.0, layaknya fluktuasi suhu ruangan. Chapter Normal Distribution membahas distribusi ini lebih dalam.
Satu Generator, Satu Urutan #
Satu objek Generator memegang satu urutan angka. Setiap pemanggilan method melanjutkan urutan tersebut, bukan mengulangnya dari awal:
import numpy as np
rng = np.random.default_rng(0)
print(rng.integers(0, 10, size=4))
print(rng.integers(0, 10, size=4))
print(rng.integers(0, 10, size=4))Output yang Dihasilkan:
[8 6 5 2]
[3 0 0 0]
[1 8 6 9]Ketiga pemanggilan identik secara kode, tetapi ketiga hasilnya berbeda: generator sudah maju ke posisi berikutnya di dalam urutannya setiap kali angka ditarik. Konsekuensinya, urutan pemanggilan method ikut menentukan nilai yang keluar. Jika hasil yang sama persis dibutuhkan di setiap eksekusi program, alatnya adalah seed — bahasan utama Chapter Reproducibility dan Random Seed.