Giả sử tôi tạo biểu đồ bằng scipy/numpy, vì vậy tôi có hai mảng: một cho số lượng thùng và một cho các cạnh thùng. Nếu tôi sử dụng biểu đồ để biểu diễn hàm phân phối xác suất, làm cách nào tôi có thể tạo các số ngẫu nhiên một cách hiệu quả từ phân phối đó?Số ngẫu nhiên từ Biểu đồ
Trả lời
Đây có thể là những gì np.random.choice
làm trong câu trả lời @ Ophion, nhưng bạn có thể xây dựng một hàm mật độ tích lũy bình thường, sau đó chọn dựa trên một số ngẫu nhiên thống nhất:
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
data = np.random.normal(size=1000)
hist, bins = np.histogram(data, bins=50)
bin_midpoints = bins[:-1] + np.diff(bins)/2
cdf = np.cumsum(hist)
cdf = cdf/cdf[-1]
values = np.random.rand(10000)
value_bins = np.searchsorted(cdf, values)
random_from_cdf = bin_midpoints[value_bins]
plt.subplot(121)
plt.hist(data, 50)
plt.subplot(122)
plt.hist(random_from_cdf, 50)
plt.show()
Trường hợp 2D có thể được thực hiện như sau:
data = np.column_stack((np.random.normal(scale=10, size=1000),
np.random.normal(scale=20, size=1000)))
x, y = data.T
hist, x_bins, y_bins = np.histogram2d(x, y, bins=(50, 50))
x_bin_midpoints = x_bins[:-1] + np.diff(x_bins)/2
y_bin_midpoints = y_bins[:-1] + np.diff(y_bins)/2
cdf = np.cumsum(hist.ravel())
cdf = cdf/cdf[-1]
values = np.random.rand(10000)
value_bins = np.searchsorted(cdf, values)
x_idx, y_idx = np.unravel_index(value_bins,
(len(x_bin_midpoints),
len(y_bin_midpoints)))
random_from_cdf = np.column_stack((x_bin_midpoints[x_idx],
y_bin_midpoints[y_idx]))
new_x, new_y = random_from_cdf.T
plt.subplot(121, aspect='equal')
plt.hist2d(x, y, bins=(50, 50))
plt.subplot(122, aspect='equal')
plt.hist2d(new_x, new_y, bins=(50, 50))
plt.show()
Vâng, điều này chắc chắn sẽ hoạt động! Nó có thể được tổng quát hóa thành các biểu đồ chiều cao hơn không? – xvtk
@xvtk Tôi đã chỉnh sửa câu trả lời của mình bằng biểu đồ 2D. Bạn sẽ có thể áp dụng cùng một lược đồ cho các bản phân phối chiều cao hơn. – Jaime
Nếu bạn đang sử dụng python 2, bạn cần thêm nhập "từ __future__ nhập khẩu", hoặc thay đổi dòng chuẩn hóa cdf thành cdf = cdf/float (cdf [-1]) –
Có lẽ một cái gì đó như thế này. Sử dụng số lượng biểu đồ dưới dạng trọng số và chọn giá trị của các chỉ số dựa trên trọng số này.
import numpy as np
initial=np.random.rand(1000)
values,indices=np.histogram(initial,bins=20)
values=values.astype(np.float32)
weights=values/np.sum(values)
#Below, 5 is the dimension of the returned array.
new_random=np.random.choice(indices[1:],5,p=weights)
print new_random
#[ 0.55141614 0.30226256 0.25243184 0.90023117 0.55141614]
giải pháp @Jaime là rất tốt, nhưng bạn nên xem xét sử dụng kde (kernel ước lượng mật độ) của biểu đồ. Một giải thích tuyệt vời tại sao nó có vấn đề để làm số liệu thống kê trên biểu đồ, và tại sao bạn nên sử dụng kde thay thế có thể được tìm thấy here
Tôi đã chỉnh sửa mã của Jaime để chỉ cách sử dụng kde từ scipy. Nó trông gần như giống nhau, nhưng nắm bắt tốt hơn bộ tạo biểu đồ.
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
def run():
data = np.random.normal(size=1000)
hist, bins = np.histogram(data, bins=50)
x_grid = np.linspace(min(data), max(data), 1000)
kdepdf = kde(data, x_grid, bandwidth=0.1)
random_from_kde = generate_rand_from_pdf(kdepdf, x_grid)
bin_midpoints = bins[:-1] + np.diff(bins)/2
random_from_cdf = generate_rand_from_pdf(hist, bin_midpoints)
plt.subplot(121)
plt.hist(data, 50, normed=True, alpha=0.5, label='hist')
plt.plot(x_grid, kdepdf, color='r', alpha=0.5, lw=3, label='kde')
plt.legend()
plt.subplot(122)
plt.hist(random_from_cdf, 50, alpha=0.5, label='from hist')
plt.hist(random_from_kde, 50, alpha=0.5, label='from kde')
plt.legend()
plt.show()
def kde(x, x_grid, bandwidth=0.2, **kwargs):
"""Kernel Density Estimation with Scipy"""
kde = gaussian_kde(x, bw_method=bandwidth/x.std(ddof=1), **kwargs)
return kde.evaluate(x_grid)
def generate_rand_from_pdf(pdf, x_grid):
cdf = np.cumsum(pdf)
cdf = cdf/cdf[-1]
values = np.random.rand(1000)
value_bins = np.searchsorted(cdf, values)
random_from_cdf = x_grid[value_bins]
return random_from_cdf
Tại sao bạn làm 'bw_method = bandwidth/x.std (ddof = 1)'? Tôi sẽ nghĩ rằng 'bw_method = băng thông * x.std (ddof = 1)' thay thế? – Fra
tôi đã cùng một vấn đề như OP và tôi muốn chia sẻ cách tiếp cận của tôi cho vấn đề này.
Làm theo Jaime answer và Noam Peled answer Tôi đã tạo giải pháp cho sự cố 2D bằng cách sử dụng Kernel Density Estimation (KDE).
But, hãy tạo một số dữ liệu ngẫu nhiên và sau đó tính số Probability Density Function (PDF) từ KDE. Tôi sẽ sử dụng số example available in SciPy cho điều đó.
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
def measure(n):
"Measurement model, return two coupled measurements."
m1 = np.random.normal(size=n)
m2 = np.random.normal(scale=0.5, size=n)
return m1+m2, m1-m2
m1, m2 = measure(2000)
xmin = m1.min()
xmax = m1.max()
ymin = m2.min()
ymax = m2.max()
X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([X.ravel(), Y.ravel()])
values = np.vstack([m1, m2])
kernel = stats.gaussian_kde(values)
Z = np.reshape(kernel(positions).T, X.shape)
fig, ax = plt.subplots()
ax.imshow(np.rot90(Z), cmap=plt.cm.gist_earth_r,
extent=[xmin, xmax, ymin, ymax])
ax.plot(m1, m2, 'k.', markersize=2)
ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])
Và cốt truyện là:
Bây giờ, chúng tôi có được dữ liệu ngẫu nhiên từ PDF lấy từ KDE, mà là biến Z
.
# Generate the bins for each axis
x_bins = np.linspace(xmin, xmax, Z.shape[0]+1)
y_bins = np.linspace(ymin, ymax, Z.shape[1]+1)
# Find the middle point for each bin
x_bin_midpoints = x_bins[:-1] + np.diff(x_bins)/2
y_bin_midpoints = y_bins[:-1] + np.diff(y_bins)/2
# Calculate the Cumulative Distribution Function(CDF)from the PDF
cdf = np.cumsum(Z.ravel())
cdf = cdf/cdf[-1] # Normalização
# Create random data
values = np.random.rand(10000)
# Find the data position
value_bins = np.searchsorted(cdf, values)
x_idx, y_idx = np.unravel_index(value_bins,
(len(x_bin_midpoints),
len(y_bin_midpoints)))
# Create the new data
new_data = np.column_stack((x_bin_midpoints[x_idx],
y_bin_midpoints[y_idx]))
new_x, new_y = new_data.T
Và chúng tôi có thể tính KDE từ dữ liệu mới này và vẽ đồ thị.
kernel = stats.gaussian_kde(new_data.T)
new_Z = np.reshape(kernel(positions).T, X.shape)
fig, ax = plt.subplots()
ax.imshow(np.rot90(new_Z), cmap=plt.cm.gist_earth_r,
extent=[xmin, xmax, ymin, ymax])
ax.plot(new_x, new_y, 'k.', markersize=2)
ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])
- 1. số ngẫu nhiên không quá ngẫu nhiên
- 2. Số ngẫu nhiên hoặc số dương Javascript ngẫu nhiên
- 3. Số ngẫu nhiên từ hạt giống
- 4. Trình tạo số ngẫu nhiên phân phối ngẫu nhiên
- 5. Số nguyên ngẫu nhiên
- 6. Số ngẫu nhiên Javascript?
- 7. số C# ngẫu nhiên không là "ngẫu nhiên"
- 8. Tạo số ngẫu nhiên lognormal trong MATLAB?
- 9. Phần tử ngẫu nhiên trong bản đồ
- 10. C++ 11 số ngẫu nhiên
- 11. Tạo một số ngẫu nhiên từ một số khác
- 12. Số ngẫu nhiên xác suất
- 13. đặc biệt ngẫu nhiên số
- 14. Số ngẫu nhiên với jQuery?
- 15. Tạo số ngẫu nhiên lớn
- 16. Số ngẫu nhiên trong C
- 17. Phân tích số ngẫu nhiên
- 18. Tạo số ngẫu nhiên CUDA
- 19. Số ngẫu nhiên giữa 2 số đôi
- 20. Tại sao không ngẫu nhiên() ngẫu nhiên?
- 21. PHP: số ngẫu nhiên từ một phân phối chuẩn
- 22. số ngẫu nhiên từ -9 đến 9 trong C++
- 23. Android: Lấy số ngẫu nhiên từ phương thức JNI
- 24. Cập nhật MySQL với số ngẫu nhiên từ 1-3
- 25. Số ngẫu nhiên từ bản phân phối Beta, C++
- 26. c - trình tạo số ngẫu nhiên
- 27. Số ngẫu nhiên giữa hai phạm vi
- 28. Xác suất và số ngẫu nhiên C#
- 29. Tạo số ngẫu nhiên 2^30
- 30. Phân phối số ngẫu nhiên thế hệ
Bạn có thể làm rõ một số điều này? Bạn có muốn một số lượng số ngẫu nhiên nhất định cho mỗi khoảng biểu đồ hay bạn muốn các số ngẫu nhiên dựa trên một hàm trọng số dựa trên một phép nội suy đa thức của các giá trị biểu đồ? – Daniel
Trả lại trung tâm thùng rác là tốt. Nội suy hoặc khớp nối là không cần thiết. – xvtk