Perbedaan antara numpy.random dan random.random dengan Python


100

Saya memiliki skrip besar dengan Python. Saya menginspirasi diri saya sendiri dalam kode orang lain jadi saya akhirnya menggunakan numpy.randommodul untuk beberapa hal (misalnya untuk membuat larik angka acak yang diambil dari distribusi binomial) dan di tempat lain saya menggunakan modul random.random.

Bisakah seseorang memberi tahu saya perbedaan utama antara keduanya? Melihat halaman web dokumen untuk masing-masing dari keduanya, menurut saya numpy.randomhanya memiliki lebih banyak metode, tetapi saya tidak jelas tentang bagaimana generasi nomor acak berbeda.

Alasan mengapa saya bertanya adalah karena saya perlu melakukan seed program utama saya untuk keperluan debugging. Tetapi itu tidak berfungsi kecuali saya menggunakan generator nomor acak yang sama di semua modul yang saya impor, apakah ini benar?

Juga, saya membaca di sini, di posting lain, sebuah diskusi tentang TIDAK menggunakan numpy.random.seed(), tetapi saya tidak benar-benar mengerti mengapa ini adalah ide yang buruk. Saya akan sangat menghargai jika seseorang menjelaskan kepada saya mengapa ini terjadi.

Jawaban:


120

Anda sudah melakukan banyak pengamatan yang benar!

Kecuali Anda ingin melakukan seed pada kedua generator acak, mungkin akan lebih mudah dalam jangka panjang untuk memilih satu generator atau yang lain. Tetapi jika Anda memang perlu menggunakan keduanya, maka ya, Anda juga harus menyemai keduanya, karena keduanya menghasilkan nomor acak secara terpisah.

Karena numpy.random.seed(), kesulitan utamanya adalah ini tidak aman untuk thread - yaitu, tidak aman digunakan jika Anda memiliki banyak thread eksekusi yang berbeda , karena tidak dijamin akan berfungsi jika dua thread berbeda menjalankan fungsi pada saat yang sama. Jika Anda tidak menggunakan utas, dan jika Anda dapat berharap bahwa Anda tidak perlu menulis ulang program Anda dengan cara ini di masa mendatang, numpy.random.seed()seharusnya baik-baik saja. Jika ada alasan untuk mencurigai bahwa Anda mungkin memerlukan utas di masa mendatang, akan jauh lebih aman dalam jangka panjang untuk melakukan seperti yang disarankan, dan membuat instance lokal numpy.random.Randomkelas . Sejauh yang saya tahu, random.random.seed()apakah thread-safe (atau setidaknya, saya belum menemukan bukti yang sebaliknya).

The numpy.randomperpustakaan berisi distribusi probabilitas beberapa tambahan yang biasa digunakan dalam penelitian ilmiah, serta beberapa fungsi kenyamanan untuk menghasilkan array dari data acak. The random.randomPerpustakaan sedikit lebih ringan, dan harus baik-baik jika Anda tidak melakukan penelitian ilmiah atau jenis lain dari pekerjaan dalam statistik.

Jika tidak, keduanya menggunakan urutan twister Mersenne untuk menghasilkan nomor acak mereka, dan keduanya sepenuhnya deterministik - yaitu, jika Anda mengetahui beberapa informasi penting, Anda dapat memprediksi dengan pasti pasti nomor apa yang akan datang berikutnya . Untuk alasan ini, baik numpy.random maupun random.random tidak cocok untuk penggunaan kriptografi yang serius . Tetapi karena urutannya sangat panjang, keduanya baik-baik saja untuk menghasilkan angka acak jika Anda tidak khawatir tentang orang yang mencoba merekayasa balik data Anda. Ini juga merupakan alasan perlunya menyemai nilai acak - jika Anda memulai di tempat yang sama setiap kali, Anda akan selalu mendapatkan urutan angka acak yang sama!

Sebagai catatan tambahan, jika Anda memang membutuhkan keacakan tingkat kriptografi, Anda harus menggunakan modul rahasia , atau sesuatu seperti Crypto.Random jika Anda menggunakan versi Python sebelum Python 3.6.


14
Sebagai catatan terkait jauh, terkadang tidak perlu menggunakan keduanya , karena twister Mersenne tidak menghasilkan urutan entropi acak yang cukup untuk tujuan kriptografi (dan beberapa ilmiah yang tidak biasa). Dalam kasus yang jarang terjadi tersebut, Anda sering membutuhkan Crypto.Random , yang dapat menggunakan sumber entropi khusus OS untuk menghasilkan urutan acak non-deterministik dengan kualitas yang jauh lebih tinggi daripada yang tersedia random.randomsendirian. Anda biasanya tidak membutuhkan ini.
SingleNegationElimination

Terima kasih Hannnele. Wawasan Anda sangat berguna! Ternyata saya tidak bisa lolos dengan HANYA menggunakan generator nomor acak tunggal, (yang perlu numpy karena acak tidak menghasilkan distribusi binomial) karena bagian dari program saya memanggil program lain yang menggunakan acak. Saya harus melakukan seed pada dua generator.
Laura

2
"Jika Anda tahu nomor mana yang Anda miliki sekarang, Anda dapat memprediksi dengan pasti nomor apa yang akan datang berikutnya." Saya pikir pernyataan ini mungkin membutuhkan klarifikasi. Yang dimaksud adalah bahwa jika Anda mengetahui keadaan internal generator, Anda dapat mereproduksi urutannya - yang Anda lakukan saat melakukan seed pada generator. Diberikan satu nomor keluaran dari generator Anda tidak dapat memprediksi nomor berikutnya. Periode ini sangat besar sehingga Anda mungkin memerlukan urutan angka yang panjang sebelum Anda dapat menghitung posisi Anda pada urutan pseudo-random dan dengan demikian memprediksi urutan berikutnya.
Kaushik Ghose

12

Dari Python untuk Analisis Data , modul numpy.randommelengkapi Python randomdengan fungsi untuk menghasilkan seluruh array nilai sampel secara efisien dari berbagai jenis distribusi probabilitas.

Sebaliknya, randommodul bawaan Python hanya mengambil sampel satu nilai pada satu waktu, sementara numpy.randomdapat menghasilkan sampel yang sangat besar lebih cepat. Menggunakan fungsi ajaib IPython, %timeitseseorang dapat melihat modul mana yang bekerja lebih cepat:

In [1]: from random import normalvariate
In [2]: N = 1000000

In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
1 loop, best of 3: 963 ms per loop

In [4]: %timeit np.random.normal(size=N)
10 loops, best of 3: 38.5 ms per loop

1
Tidak demikian halnya dengan metode lain. dibandingkan np.random.randint(2)dengan random.randrange(2)dan NumPy lebih lambat . NumPy: 1,25 us dan Random: 891 ns. Dan juga hubungan yang sama untuk np.random.rand()dan random.random().
Shayan Amani

3

Sumber seed dan profil distribusi yang digunakan akan memengaruhi output - jika Anda mencari keacakan cryptgraphic, seeding dari os.urandom () akan mendapatkan byte acak yang hampir nyata dari obrolan perangkat (mis. Ethernet atau disk) (mis. / dev / random di BSD)

ini akan menghindari Anda memberikan benih dan dengan demikian menghasilkan angka acak determinisit. Namun panggilan acak kemudian memungkinkan Anda untuk menyesuaikan nomor ke distribusi (apa yang saya sebut acak ilmiah ness - akhirnya yang Anda inginkan adalah distribusi kurva lonceng dari nomor acak, numpy adalah yang terbaik dalam menyampaikan ini.

JADI ya, tetap dengan satu generator, tetapi putuskan acak apa yang Anda inginkan - acak, tetapi pasti dari kurva distrubtuion, atau seacak mungkin tanpa perangkat kuantum.


Terima kasih banyak Paul, jawaban Anda sangat berguna! Saya tidak mencari keacakan kriptografi, saya melakukan pemodelan matematika dan angka pseudo-random sudah cukup bagi saya. Ternyata saya tidak bisa menggunakan satu generator seperti yang saya inginkan karena saya perlu numpy untuk distribusi binomial dan program saya memanggil program lain yang menggunakan acak :(
Laura
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.