Мой первый вопрос: правильно ли построен мой график вероятности?
Нет.Это сделано по сравнению с нормальным распределением по умолчанию.Вы должны упаковать свою функцию f(x)
в класс, полученный из stats.rv_continuous, превратить ее в метод _pdf и передать ее в probplot
И второе, что находится в заголовке.Как оптимизировать этот метод?Можно ли сократить время и количество отклонений?
Конечно, у вас есть сила векторных способностей NumPy в ваших руках.Никогда не пишите явные циклы - векторизация, векторизация и векторизация!
Посмотрите на приведенный ниже модифицированный код, а не на один цикл, все делается через векторы NumPy.Время на моем компьютере сократилось на 100000 образцов (Xeon, Win10 x64, Anaconda Python 3.7) с 0,19 до 0,003.
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import time
a = 0. # xmin
b = 1. # xmax
m = 3.0/2.0 # ymax
def f(x):
return 1.5 * (1.0 - x*x) # probability density function
start = time.time()
N = 100000
u1 = np.random.uniform(a, b, N)
u2 = np.random.uniform(0.0, m, N)
negs = np.empty(N)
negs.fill(-1)
variables = np.where(u2 <= f(u1), u1, negs) # accepted samples are positive or 0, rejected are -1
end = time.time()
accept = np.extract(variables>=0.0, variables)
reject = N - len(accept)
print("Time: ", end-start)
print("Rejection: ", reject)
x = np.linspace(a, b, 1000)
plt.hist(accept, 50, density=True)
plt.plot(x, f(x))
plt.show()
ss.probplot(accept, plot=plt) # against normal distribution
plt.show()
Что касается уменьшения количества отклонений, вы можете выполнить выборку с 0 отклонениями, используя метод обратного анализа,является кубическим уравнением, поэтому он может работать с легкими
ОБНОВЛЕНИЕ
Вот код, который нужно использовать для probplot:
class my_pdf(ss.rv_continuous):
def _pdf(self, x):
return 1.5 * (1.0 - x*x)
ss.probplot(accept, dist=my_pdf(a=a, b=b, name='my_pdf'), plot=plt)
, и вы должны получить что-то вроде