计算性能 scipy weibull min fit vs Matlab wblfit

Posted

技术标签:

【中文标题】计算性能 scipy weibull min fit vs Matlab wblfit【英文标题】:Calculation performance scipy weibull min fit vs Matlab wblfit 【发布时间】:2021-10-16 11:45:47 【问题描述】:

使用 Matlab wblrndwblfit 函数以及 Python scipy.stats.weibull_min.fit 函数将数据拟合到 Weibull 分布,我发现 Matlab 的性能比 Python 高出近 2 个数量级。我正在寻求一些帮助来提高 Python 代码的性能。

问题:

在将 Matlab 代码转换为 Python 时,我遇到了以下代码:

weibull_parameters = zeros(10000, 2)
for i = 1:10000
    data = sort(wblrnd(alpha, beta, 1, 24))
    [weibull_parameters(i, :), ~] = wblfit(data, confidence_interval, censoring_array)
end

此代码从 Weibull 分布生成 24 个随机数,然后将生成的数据向量再次拟合到 Weibull 分布。

在 Python 中,我将其翻译为:

from scipy.stats import weibull_min
import numpy as np


data = np.sort(alpha * np.random.default_rng().weibull(beta, (10000, 24)))

weibull_parameters = np.zeros((10000, 2))
for idx, row in enumerate(data):
    weibull_parameters[idx, :] = weibull_min.fit(row, floc=0)[2::-2]

在这里,我一次生成完整的随机数据,然后使用 weibull_min.fit 函数遍历行以获取相应的 Weibull 参数。最后的切片就是在输出中只选择尺度和形状参数,并按正确的顺序排列。

我遇到的主要问题是Python中的计算性能很糟糕。 Matlab 在几秒钟内运行此代码,但对于 Python,每 100 次迭代需要 1-1.5 秒(在我的笔记本电脑上),因此性能差异几乎是 2 个数量级。

有什么方法可以提高 Python 的性能吗?是否可以矢量化拟合计算?很遗憾,我在网上找不到关于此主题的任何内容。

注意 1:Matlab 允许用户在 wblfit 函数中指定置信区间,但是对于 Python,我找不到包含它的方法,所以我忽略了它。

注意 2:我能找到的唯一包含审查的选项是使用 surpyval package,但性能更加糟糕(每 100 次迭代大约需要 10 秒)

【问题讨论】:

【参考方案1】:

Python 并不是最快的语言。您可以采取一些措施来加快速度,但您会发现准确性和速度之间存在平衡。

至于适合 Weibull 分布的方法,有几个包可以做到这一点。包scipy、surpyval、lifelines 和reliability 都适合完整的数据。最后 3 个也将处理 scipy 不会处理的审查数据。

我是可靠性的作者,所以我将向您展示一个使用此包的示例:

from reliability.Distributions import Weibull_Distribution
from reliability.Fitters import Fit_Weibull_2P
import time
import numpy as np

rows=100
samples = 24
data_array = np.empty((rows,samples))
true_parameters = np.empty((rows,2))
for i in range(rows):
    alpha = np.random.randint(low=1,high=999) + np.random.rand() #alpha between 1 and 1000
    beta = np.random.randint(low=1,high=10) - np.random.rand()/2 #beta between 0.5 and 10
    true_parameters[i][0] = alpha
    true_parameters[i][1] = beta
    dist = Weibull_Distribution(alpha=alpha,beta=beta)
    data_array[i]=dist.random_samples(samples)

start_time = time.time()
parameters = np.empty((rows,2))
for i in range(rows):
    fit = Fit_Weibull_2P(failures=data_array[i],show_probability_plot=False,print_results=False)
    parameters[i][0] = fit.alpha
    parameters[i][1] = fit.beta

runtime = time.time()-start_time
# np.set_printoptions(suppress=True) #supresses the scientific notation used by numpy
# print('True parameters:')
# print(true_parameters)
# print('Fitted parameters:')
# print(parameters)
print('Runtime:',runtime,'seconds')
print('Runtime per iteration:',runtime/rows,'seconds')

当我运行它时,它会给出:

Runtime: 3.378781318664551 seconds
Runtime per iteration: 0.033787813186645504 seconds

根据您在问题中引用的时间,这大约是 scipy 的两倍,但只有 surpyval 所用时间的三分之一。

我希望这有助于向您展示一种不同的方式来做同样的事情,但我知道这可能不是您所寻求的性能改进。获得大幅性能提升的唯一方法是在纯 python 中使用最小二乘估计,也许使用 numba 加速。这种方法可能会给您带来不如 MLE 的结果,但正如我之前所说,速度和准确性之间以及速度和编码便利性之间存在平衡。

【讨论】:

感谢您向我展示可靠性包,我确实不知道。不幸的是,我不能放弃使用 MLE,因为这是行业标准。我仍然对 MATLAB 能够如此快速地执行拟合感到震惊。也许它在后台做了很多并行化/矢量化。现在,虽然您显示的结果表明至少有一种更有利的实施审查方法,但性能仍然太慢。因为我们需要在代码中运行拟合部分 4 次,所以这意味着人们要等待 20 分钟才能完成代码。也许 Numba 有帮助 如果您需要使用 MLE,那么 numba 将无法帮助您(除非您愿意深入研究 autograd 的源代码)。您的数据集是否包含大量重复值?如果是这样,那么您可能会更快地找到生命线。

以上是关于计算性能 scipy weibull min fit vs Matlab wblfit的主要内容,如果未能解决你的问题,请参考以下文章

Scipy Weibull CDF 计算

使用 scipy.stats 将 Weibull 分布拟合到数据是不是表现不佳?

Scipy Weibull 参数置信区间

使用 Scipy 拟合 Weibull 分布

尝试 MLE 拟合 Weibull 分布时 scipy.optimize.minimize 中的 RuntimeWarning

使用 stats.exponweib.fit 在 python 中拟合 Weibull 分布