สร้างอาร์เรย์ numpy แบบสุ่มเดียวกันอย่างสม่ำเสมอ


91

ฉันกำลังรอให้นักพัฒนารายอื่นทำโค้ดให้เสร็จซึ่งจะคืนค่าอาร์เรย์ np ของรูปร่าง (100,2000) ด้วยค่า -1,0 หรือ 1

ในระหว่างนี้ฉันต้องการสร้างอาร์เรย์ที่มีลักษณะเดียวกันแบบสุ่มเพื่อที่ฉันจะได้เริ่มต้นพัฒนาและทดสอบได้ สิ่งนี้คือฉันต้องการให้อาร์เรย์ที่สร้างแบบสุ่มนี้เหมือนกันทุกครั้งเพื่อที่ฉันจะได้ไม่ทดสอบกับอาร์เรย์ที่เปลี่ยนค่าไปเรื่อย ๆ ทุกครั้งที่ฉันรันกระบวนการของฉันใหม่

ฉันสามารถสร้างอาร์เรย์ของฉันแบบนี้ได้ แต่มีวิธีสร้างอาร์เรย์ให้เหมือนกันทุกครั้งหรือไม่ ฉันสามารถดองวัตถุและปลดเปลื้องได้ แต่สงสัยว่ามีวิธีอื่นหรือไม่

r = np.random.randint(3, size=(100, 2000)) - 1

คำตอบ:


87

เพียงแค่เพาะเมล็ดตัวสร้างตัวเลขสุ่มด้วยค่าคงที่เช่น

numpy.random.seed(42)

ด้วยวิธีนี้คุณจะได้ลำดับหมายเลขสุ่มเหมือนกันเสมอ

ฟังก์ชันนี้จะเริ่มต้นตัวสร้างตัวเลขสุ่มเริ่มต้นทั่วโลกและการเรียกใช้ฟังก์ชันใด ๆ ในฟังก์ชันnumpy.randomจะใช้และเปลี่ยนแปลงสถานะ สิ่งนี้ใช้ได้ดีสำหรับกรณีการใช้งานทั่วไป แต่เป็นรูปแบบของสภาวะโลกที่มีปัญหาทั้งหมดที่รัฐโลกนำมาให้ สำหรับวิธีการแก้ปัญหาที่สะอาดขึ้นโปรดดูคำตอบของ Robert Kern ด้านล่าง


43
มีคนแอบเข้ามาในnumpy.random.seed()ฟังก์ชั่นเมื่อฉันไม่ได้ให้ความสนใจ :-) ฉันจงใจปล่อยมันออกจากโมดูลเดิม ฉันขอแนะนำให้ผู้คนใช้อินสแตนซ์ของตนเองRandomStateและส่งผ่านวัตถุเหล่านั้นไปรอบ ๆ
Robert Kern

6
โรเบิร์ตเป็นผู้สนับสนุนหลักในการทำให้มึนงง ฉันคิดว่าเราควรให้น้ำหนักความคิดเห็นของเขาบ้าง
เลิกใช้งาน

11
@deprecated: ฉันรู้สึกขอบคุณสำหรับงานของโรเบิร์ต แต่งานของเขาไม่ได้ทดแทนการให้เหตุผลสำหรับคำแนะนำ นอกจากนี้หากใช้numpy.random.seed()เป็นกำลังใจนี้ควรได้รับการกล่าวถึงในเอกสาร เห็นได้ชัดว่าผู้ร่วมให้ข้อมูลคนอื่น ๆ ใน NumPy ไม่เปิดเผยความคิดเห็นของ Robert ฉันแค่อยากรู้อยากเห็น
Sven Marnach

13
ซึ่งเหมือนกับการใช้random.seedกับการใช้random.Randomวัตถุในไลบรารีมาตรฐาน Python หากคุณใช้random.seedหรือnumpy.random.seedคุณกำลังเริ่มต้นอินสแตนซ์แบบสุ่มทั้งหมดทั้งในโค้ดของคุณและในโค้ดใด ๆ ที่คุณกำลังเรียกใช้หรือโค้ดใด ๆ ที่ทำงานในเซสชันเดียวกับของคุณ หากสิ่งเหล่านั้นขึ้นอยู่กับสิ่งเหล่านั้นเป็นแบบสุ่มจริงๆแสดงว่าคุณเริ่มประสบปัญหา หากคุณปรับใช้โค้ดที่ตั้งค่าเมล็ดพันธุ์แบบสุ่มคุณสามารถทำให้เกิดช่องโหว่ด้านความปลอดภัย
asmeurer

3
@asmeurer ใครก็ตามที่ใช้โปรแกรมสร้างหมายเลขหลอกเพื่อความปลอดภัยอาจไม่รู้ว่ากำลังทำอะไรอยู่
JAB

191

สร้างอินสแตนซ์ของคุณเองnumpy.random.RandomState()ด้วยเมล็ดพันธุ์ที่คุณเลือก อย่าใช้numpy.random.seed()ยกเว้นเพื่อหลีกเลี่ยงไลบรารีที่ไม่ยืดหยุ่นซึ่งไม่อนุญาตให้คุณผ่านRandomStateอินสแตนซ์ของคุณเอง

[~]
|1> from numpy.random import RandomState

[~]
|2> prng = RandomState(1234567890)

[~]
|3> prng.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])

[~]
|4> prng2 = RandomState(1234567890)

[~]
|5> prng2.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])

7
คุณมีเหตุผลสำหรับคำแนะนำของคุณหรือไม่? เกิดอะไรขึ้นnumpy.random.seed()? ฉันรู้ว่ามันไม่ปลอดภัยต่อด้าย แต่มันสะดวกมากถ้าคุณไม่ต้องการความปลอดภัยของด้าย
Sven Marnach

52
ส่วนใหญ่เป็นการสร้างนิสัยที่ดี คุณอาจไม่ต้องการสตรีมอิสระในตอนนี้ แต่ Sven-6-months-from-now อาจ หากคุณเขียนไลบรารีของคุณเพื่อใช้เมธอดโดยตรงnumpy.randomคุณจะไม่สามารถสร้างสตรีมอิสระในภายหลังได้ นอกจากนี้ยังง่ายกว่าในการเขียนไลบรารีโดยมีจุดประสงค์เพื่อควบคุมสตรีม PRNG มีหลายวิธีในการเข้าสู่ห้องสมุดของคุณและแต่ละวิธีควรมีวิธีควบคุมเมล็ดพันธุ์ ผ่านรอบวัตถุ PRNG numpy.random.seed()เป็นวิธีการทำความสะอาดในการทำว่ากว่าอาศัย ขออภัยช่องแสดงความคิดเห็นนี้สั้นเกินไปที่จะมีตัวอย่างเพิ่มเติม :-)
Robert Kern

25
อีกวิธีหนึ่งในการอธิบายเหตุผลของ Robert: การใช้ numpy.random.seed ใช้ตัวแปรส่วนกลางเพื่อรักษาสถานะ PRNG และเหตุผลมาตรฐานเดียวกันกับที่ตัวแปรส่วนกลางไม่ถูกต้องนำไปใช้ที่นี่
Robie Basak

9
หากคุณต้องการให้ PRNG เป็นอิสระอย่าเพาะเมล็ดด้วยสิ่งใด ๆ เพียงแค่ใช้numpy.random.RandomState()โดยไม่มีข้อโต้แย้ง สิ่งนี้จะเริ่มต้นสถานะด้วยค่าเฉพาะที่ดึงมาจากสิ่งอำนวยความสะดวกระบบปฏิบัติการของคุณสำหรับสิ่งต่างๆดังกล่าว ( /dev/urandomบนเครื่อง UNIX และเทียบเท่ากับ Windows ที่นั่น) หากnumpy.random.RandomState(1234567890)ไม่ได้ผลสำหรับคุณโปรดแสดงสิ่งที่คุณพิมพ์และข้อความแสดงข้อผิดพลาดที่คุณได้รับ
Robert Kern

5
ไม่ใช่ความคิดที่ดี ใช้numpy.random.RandomState()โดยไม่มีข้อโต้แย้งเพื่อผลลัพธ์ที่ดีที่สุด
Robert Kern

3

หากคุณกำลังใช้ฟังก์ชันอื่นโดยอาศัยสถานะสุ่มคุณไม่สามารถตั้งค่าและเมล็ดพันธุ์โดยรวมได้ แต่ควรสร้างฟังก์ชันเพื่อสร้างรายการตัวเลขแบบสุ่มของคุณและตั้งค่าเมล็ดพันธุ์เป็นพารามิเตอร์ของฟังก์ชัน สิ่งนี้จะไม่รบกวนเครื่องกำเนิดไฟฟ้าแบบสุ่มอื่น ๆ ในโค้ด:

# Random states
def get_states(random_state, low, high, size):
    rs = np.random.RandomState(random_state)
    states = rs.randint(low=low, high=high, size=size)
    return states

# Call function
states = get_states(random_state=42, low=2, high=28347, size=25)

3

สิ่งสำคัญคือต้องเข้าใจว่าเมล็ดพันธุ์ของเครื่องกำเนิดไฟฟ้าแบบสุ่มคืออะไรและเมื่อใด / อย่างไรในรหัสของคุณ (ตรวจสอบเช่นที่นี่เพื่อดูคำอธิบายที่ดีเกี่ยวกับความหมายทางคณิตศาสตร์ของเมล็ดพันธุ์)

เพื่อที่คุณจะต้องตั้งเมล็ดโดยทำ:

random_state = np.random.RandomState(seed=your_favorite_seed_value)

สิ่งสำคัญคือต้องสร้างตัวเลขสุ่มจาก random_state ไม่ใช่จาก np.random เช่นคุณควรทำ:

random_state.randint(...)

แทน

np.random.randint(...) 

ซึ่งจะสร้างอินสแตนซ์ใหม่ของ RandomState () และโดยพื้นฐานแล้วใช้นาฬิกาภายในคอมพิวเตอร์ของคุณเพื่อตั้งค่าเมล็ดพันธุ์


2

ฉันแค่อยากจะชี้แจงบางอย่างเกี่ยวกับคำตอบของ @Robert Kern ในกรณีที่ไม่ชัดเจน แม้ว่าคุณจะใช้วิธีนี้RandomStateคุณจะต้องเริ่มต้นทุกครั้งที่คุณเรียกวิธีการสุ่มที่เป็นตัวเลขเหมือนในตัวอย่างของ Robert มิฉะนั้นคุณจะได้ผลลัพธ์ดังต่อไปนี้

Python 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 19:07:31) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> prng = np.random.RandomState(2019)
>>> prng.randint(-1, 2, size=10)
array([-1,  1,  0, -1,  1,  1, -1,  0, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([-1, -1, -1,  0, -1, -1,  1,  0, -1, -1])
>>> prng.randint(-1, 2, size=10)
array([ 0, -1, -1,  0,  1,  1, -1,  1, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([ 1,  1,  0,  0,  0, -1,  1,  1,  0, -1])
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.