Số ngẫu nhiên không lặp lại trong numpy


88

Làm cách nào để tạo các số ngẫu nhiên không lặp lại ở dạng số?

list = np.random.random_integers(20,size=(10))

Ý bạn là gì khi nói "không lặp lại"? Rằng dãy số ngẫu nhiên không bao giờ lặp lại? Điều này là không thể, vì trạng thái của bộ tạo số ngẫu nhiên cần phải vừa với bộ nhớ hữu hạn của máy tính. Hay bạn có nghĩa là không có số nào xảy ra hai lần?
Sven Marnach

5
Không lặp lại có nghĩa là bạn có một danh sách không có bản sao.
Đa thức

2
Có lẽ bạn cần một hoán vị ngẫu nhiên? docs.scipy.org/doc/numpy/reference/generated/…
cyborg

Câu trả lời:


106

numpy.random.Generator.choiceđưa ra một replaceđối số để lấy mẫu mà không cần thay thế:

from numpy.random import default_rng

rng = default_rng()
numbers = rng.choice(20, size=10, replace=False)

Nếu bạn đang Generatorsử dụng NumPy trước 1.17, không có API, bạn có thể sử dụng random.sample()từ thư viện chuẩn:

print(random.sample(range(20), 10))

Bạn cũng có thể sử dụng numpy.random.shuffle()và cắt lát, nhưng cách này sẽ kém hiệu quả hơn:

a = numpy.arange(20)
numpy.random.shuffle(a)
print a[:10]

Cũng có một replaceđối số trong numpy.random.choicehàm kế thừa , nhưng đối số này được triển khai không hiệu quả và sau đó không hiệu quả do đảm bảo tính ổn định của dòng số ngẫu nhiên, vì vậy việc sử dụng nó không được khuyến khích. (Về cơ bản, nó thực hiện việc xáo trộn và cắt lát nội bộ.)


1
print random.sample (range (20), 10) không hoạt động với python 2.6 ?!
Academia

Bạn đã làm import random?
Sven Marnach

Sự cố là do cấu hình Pydev không hợp lệ. Thks
Academia

1
Điều gì sẽ xảy ra nếu n của tôi không phải là 20, mà giống như 1000000, nhưng tôi chỉ cần 10 số duy nhất từ ​​nó, thì có cách tiếp cận hiệu quả hơn về bộ nhớ không?
mrgloom

2
@mrgloom Trong Python 3, random.sample(range(n), 10))sẽ hiệu quả ngay cả đối với rất lớn n, vì một rangeđối tượng chỉ là một trình bao bọc nhỏ lưu trữ các giá trị bắt đầu, dừng và bước, nhưng không tạo danh sách đầy đủ các số nguyên. Trong Python 2, bạn có thể thay thế rangebằng xrangeđể có được một hành vi tương tự.
Sven Marnach

108

Tôi nghĩ numpy.random.samplebây giờ không hoạt động. Đây là cách của tôi:

import numpy as np
np.random.choice(range(20), 10, replace=False)

25
Thay vì range(n)(hoặc arange(n)) như đối số đầu tiên của choice, nó tương đương với chỉ truyền n, ví dụ choice(20, 10, replace=False).
Josh Bode

1
Lưu ý rằng np.random.choice(a, size, replace=False)tốc độ này rất chậm đối với dung lượng lớn a- trên máy tính của tôi, khoảng 30 ms cho a = 1 triệu.
Matthew Rahtz

3
Để tránh thời gian và các vấn đề bộ nhớ cho rất lớn nsử dụng numpy.random.Generator.choice(bắt đầu với v1.17 NumPy)
benbo

1
Nhược điểm chính mà tôi thấy là np.random.choice không có tham số trục -> nó chỉ dành cho mảng 1d.
Moosefeather

3

Nhiều năm sau, một số thời gian để chọn 40000 trong số 10000 ^ 2 (Numpy 1.8.1, imac 2.7 GHz):

import random
import numpy as np

n = 10000
k = 4
np.random.seed( 0 )

%timeit np.random.choice( n**2, k * n, replace=True )  # 536 µs ± 1.58 µs
%timeit np.random.choice( n**2, k * n, replace=False ) # 6.1 s ± 9.91 ms

# https://docs.scipy.org/doc/numpy/reference/random/index.html
randomstate = np.random.default_rng( 0 )
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=False )  # 766 µs ± 2.18 µs
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=True )   # 1.05 ms ± 1.41 µs

%timeit random.sample( range( n**2 ), k * n )          # 47.3 ms ± 134 µs

(Tại sao lại chọn 40000 trong số 10000 ^ 2? Để tạo ma trận scipy.sparse.random lớn - sử dụng scipy 1.4.1 np.random.choice( replace=False ), slooooow.)

Lời khuyên dành cho những người numpy.random.


1

Bạn cũng có thể nhận được điều này bằng cách sắp xếp:

random_numbers = np.random.random([num_samples, max_int])
samples = np.argsort(random_numbers, axis=1)

-3

Chỉ cần tạo một mảng có chứa phạm vi số được yêu cầu, sau đó trộn chúng bằng cách hoán đổi liên tục một dãy ngẫu nhiên với phần tử thứ 0 trong mảng. Điều này tạo ra một chuỗi ngẫu nhiên không chứa các giá trị trùng lặp.


2
Một thuộc tính khác của chuỗi ngẫu nhiên kết quả là nó không đặc biệt ngẫu nhiên .
Sven Marnach

@SvenMarnach - Tuy nhiên, đối với hầu hết các mục đích, nó đủ ngẫu nhiên. Anh ta có thể sử dụng cách tiếp cận ngẫu nhiên kép nếu anh ta muốn nó ngẫu nhiên hơn.
Đa thức

Điều này là vô nghĩa. OP có thể sử dụng các lệnh gọi thư viện để thực hiện đúng. Chúng dễ sử dụng hơn, chạy nhanh hơn và dễ đọc hơn phiên bản tùy chỉnh. Tôi không thể nghĩ ra bất kỳ lý do nào tại sao tôi nên sử dụng một thuật toán sai ở đây chỉ vì nó có thể là "đủ ngẫu nhiên", khi sử dụng thuật toán đúng không có bất lợi nào.
Sven Marnach

@SvenMarnach - Đủ công bằng. Tôi không biết numpy, vì vậy tôi chỉ đưa ra một giải pháp tiềm năng.
Đa thức
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.