Załóżmy, że tworzę histogram, używając scipy/numpy, więc mam dwie tablice: jedną dla licznika bin i jedną dla krawędzi pojemnika. Jeśli użyję histogramu do przedstawienia funkcji rozkładu prawdopodobieństwa, w jaki sposób mogę efektywnie generować liczby losowe z tej dystrybucji?Losowa liczba z histogramu
Odpowiedz
To pewnie co np.random.choice
robi w odpowiedzi @ Ophion, ale można skonstruować znormalizowanej funkcji gęstości zbiorczej, a następnie wybrać na podstawie jednolitej liczby losowej:
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()
Przypadku 2D można wykonać w następujący sposób:
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()
Tak, to na pewno zadziała! Czy można go uogólnić na histogramy o wyższych wymiarach? – xvtk
@xvtk Edytowałem swoją odpowiedź za pomocą histogramu 2D. Powinieneś być w stanie zastosować ten sam schemat dla większych dystrybucji wymiarowych. – Jaime
Jeśli używasz Pythona 2, musisz dodać import "od __future__" importu lub zmienić linię normalizacji cdf na cdf = cdf/float (cdf [-1]) –
Być może coś takiego. Wykorzystuje liczbę histogramów jako wagę i wybiera wartości wskaźników na podstawie tego ciężaru.
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]
rozwiązanie @Jaime jest wielki, ale należy rozważyć użycie KDE (oszacowanie gęstości jądra) histogramu. Wspaniałe wyjaśnienie, dlaczego tworzenie statystyk na histogramie jest problematyczne i dlaczego należy używać kde, można znaleźć pod here
Edytowałem kod @ Jaime, aby pokazać, jak używać kde z scipy. Wygląda prawie tak samo, ale lepiej przechwytuje generator histogramów.
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
Dlaczego robisz 'bw_method = bandwidth/x.std (ddof = 1)'? Myślę, że zamiast tego użyłbym 'bw_method = bandwidth * x.std (ddof = 1)'? – Fra
miałem ten sam problem jak PO i chciałbym podzielić się moje podejście do tego problemu.
Po Jaime answer i Noam Peled answer Zbudowałem rozwiązanie problemu 2D przy użyciu Kernel Density Estimation (KDE).
Frist, wygenerujmy losowe dane, a następnie obliczyć jego Probability Density Function (PDF) z KDE. Użyję do tego example available in SciPy.
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])
A fabuła jest:
Teraz otrzymujemy losowe dane z pliku PDF uzyskanych z KDE, który jest zmienny 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
Możemy obliczyć KDE z tych nowych danych i spisać je.
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. Losowa liczba całkowita z warunkami
- 2. JavaScript Liczba losowa?
- 3. PHP: Liczba losowa z rozkładu normalnego
- 4. Losowa liczba: 0 lub 1
- 5. Niepowtarzalna liczba losowa w numpy
- 6. Losowa liczba między 2 podwójnymi liczbami
- 7. Losowa liczba w roku 1991 Pascal
- 8. JavaScript Losowa liczba dodatnia lub ujemna
- 9. Próbka losowa liczba całkowita w Rcpp
- 10. Losowa liczba w pętli do-while z instrukcją if
- 11. Losowa liczba w normalnym rozkładzie skośnym (odpowiednik NORMINV())
- 12. ggplot2: histogramu z krzywą normalną
- 13. Tworzenie histogramu
- 14. Obliczanie histogramu danych transmisji strumieniowej - Obliczanie histogramu online
- 15. R - histogram wewnątrz histogramu
- 16. Jmeter dynamiczna zmienna losowa
- 17. Analiza histogramu 2-czynnikowego
- 18. AVAudioPlayer i Losowa Powolność
- 19. Losowa lista Pythona
- 20. liczba Liczba przedmiotów z nieruchomości
- 21. Paralilizacja funkcji histogramu
- 22. Sposób na uniknięcie histogramu?
- 23. Losowa ścieżka przez prostokąt
- 24. Zarys histogramu w Pythonie
- 25. Tworzenie histogramu w Ruby
- 26. Jak usunąć szum z wyrównanego obrazu histogramu?
- 27. Matplotlib: wykreślanie przezroczystego histogramu z nieprzezroczystą krawędzią
- 28. Haskell Losowa generacja
- 29. losowa linia w pliku
- 30. Losowa próbka z danego dwuwymiarowego dyskretnego rozkładu
można wyjaśnić niektóre? Czy chcesz mieć pewną liczbę losowych liczb na interwał histogramu, czy też chcesz liczb losowych opartych na funkcji ważenia, która opiera się na wielomianowej interpolacji wartości histogramu? – Daniel
Zwrócenie środka kosza jest w porządku. Interpolacja lub dopasowanie nie jest konieczne. – xvtk