Создание наилучшего экспоненциального распределения с ограничениями на процентили - PullRequest
1 голос
/ 09 мая 2020

Я пытаюсь сгенерировать наилучшее экспоненциальное распределение (подходящее), которое будет иметь следующие характеристики:

1. Диапазон результатов находится в [0,500]

2. CDF процентили как можно ближе к следующему соотношению (процентиль, значение) 0,3-50,0,5-100, 0,8: 200,0,9-300, 0,95-400, 1-500

Сначала я попытался получить лямбду коэффициент с помощью медианного ограничения 100: лямбда = 100 / ln (2) = 0,006931, а затем отрисовка распределения:

data = np.random.exponential((1/0.006931), size=1000)
plt.hist(data,bins=30)
plt.show()

enter image description here

re масштабирование до [0,500]

data=(data-min(data))/(max(data)-min(data))*500    
plt.hist(data,bins=30)
plt.show()

enter image description here

Затем я пытаюсь масштабировать результаты до 500 и строить гистограмму и CDF, но я довольно далеко из красных точек, которые напоминают процентиль, к которой я тоже хочу приблизиться с распределением.

x = np.sort(data)
y = np.arange(1, len(x) +1) /len(x)
_ = plt.plot(x,y, marker ='.', linestyle='none')
x_percentile = np.array([0,50, 100, 200, 350, 400, 500])
y_percentile = np.array([0,30, 50, 80, 90, 95, 100])
plt.scatter(x_percentile, y_percentile/100,color='r')
plt.xlabel('results')
plt.ylabel('ECDF')
plt.show()

enter image description here

Как мне найти ближайшее распределение функция для моей проблемы?

1 Ответ

0 голосов
/ 09 мая 2020

Вы можете использовать scipy.optimize.curve_fit, чтобы найти «лучшую» экспоненту. Предполагая, что у вас есть ограничение, что CDF должен быть 0 в 0, т.е. сдвиг равен 0, таким образом, loc = 0, нам нужно только подобрать параметр масштаба (лямбда):

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import expon
from scipy.optimize import curve_fit

def fitfun(x, *a):
    ex = expon(loc=0, scale=a[0])
    return ex.cdf(x)

y = 0, 0.3, 0.5, 0.8, 0.9, 0.95, 1
x = 0, 50, 100, 200, 300, 400, 500
p, _ = curve_fit(fitfun, x, y, 100/np.log(2))
print(p[0]) # 133.99106748543082
solution = expon(loc=0, scale=p[0])

X = arange(600)
plt.plot(X, solution.cdf(X))
plt.plot(x, y, marker='o', ls='')
plt.show()

exponental distribution fit

Используя curve_fit, вы можете добавить неопределенности к подгонке, чтобы сделать ограничение 0-0 и 1-500 в CDF более сильным, чем другие ограничения, или использовать другую процедуру оптимизации. curve_fit по умолчанию будет использовать метод наименьших квадратов и метод Левенберга-Марквардта для подбора. Это просто идея, а не идеальное решение.

...