我试图找到一个随机变量事件超过特定值的概率,即pr(x> a),其中a是某个常数,通常远高于x的平均值,而x不是任何标准的高斯分布。所以我想要拟合其他概率密度函数,并将x的pdf的积分从a到inf。由于这是对峰值进行建模的问题,我认为这是一个极值分析问题,并发现Weibull分布可能是合适的。
关于极值分布,Weibull分布有一个非常容易实现的"积分,因此我想我可以从Scipy获得pdf,并做一个Riemann-sum。我还认为我还可以简单地评估核密度,获得pdf,并对黎曼和进行相同的操作,以近似积分。
我在Stack上找到了一个Q,它提供了一种在Python中进行Riemann和的简洁方法,并且我调整了该代码以适应我的问题。但是当我评估积分时,我会得到奇怪的数字,表明KDE或者Riemann和函数有问题。
两个场景,第一个是Weibull,根据Scipy文档:
x = theData
x_grid = np.linspace(0,np.max(x),len(x))
p = ss.weibull_min.fit(x[x!=0], floc=0)
pd = ss.weibull_min.pdf(x_grid,p[0], p[1], p[2])
看起来像这样:
然后还尝试了如下的KDE方法
pd = ss.gaussian_kde(x).pdf(x_grid)
我随后通过以下函数运行:
def riemannSum(a, b, n):
dx = (b - a) / n
s = 0.0
x = a
for i in range(n):
s += pd[x]
x += dx
return s * dx
print(riemannSum(950.0, 1612.0, 10000))
print(riemannSum(0.0, 1612.0, 100000))
在Weibull的情况下,它给了我
>> 0.272502150549
>> 18.2860384829
在KDE的情况下,我得到了
>> 0.448450460469
>> 18.2796021034
这显然是错误的。拿整个东西的积分应该给我1,而18.2+是相当遥远的。
我对这些密度函数的假设是错误的吗?或者我在黎曼和函数中犯了一些错误
答案 0 :(得分:2)
Weibull分布具有非常“不易实现”的积分
咦?!
Weibull distribution定义了非常好的CDF,因此实现积分几乎是单行的(好的,为了清晰起见,请将其设为两个)
def WeibullCDF(x, lmbd, k):
q = pow(x/lmbd, k)
return 1.0 - exp(-q)
当然,如果您想从标准库中选择
,则有ss.weibull_min.cdf(x_grid,p[0], p[1], p[2])
答案 1 :(得分:1)
我知道有一个对您有用的答案,但是我偶然发现了这个问题,同时希望了解如何进行概率密度的黎曼和的求和,而其他人也是如此,所以我将尝试一下。
基本上,我认为您有(现在是)一个较旧的numpy版本,该版本允许浮点索引,并且您的pd
变量指向从pdf提取的值数组,该值对应于xgrid的值。如今,当尝试使用浮点索引时,您会在numpy中得到一个错误,但是由于您没有这样做,因此您正在使用与该索引相对应的网格值来访问pdf的值。您需要做的是使用您要在黎曼和中使用的新值来计算pdf。
我从问题中编辑了代码,以创建一种可用于计算pdf积分的方法。
def riemannSum(a, b, n):
dx = (b-a)/n
s = 0.0
x = 0
pd = weibull_min.pdf(np.linspace(a, b, n), p[0], p[1], p[2])
for i in range(n):
s += pd[x]
x += 1
return s*dx
答案 2 :(得分:0)
下面也可以使用Riemann实现(它使用Java而不是Python)。
import static java.lang.Math.exp;
import static java.lang.Math.pow;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.IntStream;
public class WeibullPDF
{
public interface Riemann extends BiFunction<Function<Double, Double>, Integer,
BinaryOperator<Double>> { }
public static void main(String args[])
{
int N=100000;
Riemann s = (f, n) -> (a, b) ->
IntStream.range(0, n).
.mapToDouble(i->f.apply(a+i*((b-a)/n))*((b-a)/n)).sum();
double k=1.5;
Optional<Double> weibull =
Optional.of(s.apply(x->k*pow(x,k-1)*exp(-pow(x,k)),N).apply(0.0,1612.0));
weibull.ifPresent(System.out::println); //prints 0.9993617886716168
}
}