如何使用Python获取Weibull分布的置信区间?

时间:2019-08-21 11:31:34

标签: python statsmodels confidence-interval weibull

我想通过Python进行置信区间为0.95%的概率威布尔拟合。作为测试数据,我使用了测量的失败周期,并针对可靠性R(t)进行了绘制。

到目前为止,我找到了一种进行威布尔拟合的方法,但是,我仍然无法获得置信区间。带有相同测试数据集的Weibull图已经用原点进行过,因此我知道我将“期望”哪种形状作为置信区间。但是我不知道如何到达那里。

example for confidence interval

我在reliawiki上找到了关于Weibull置信区间的信息(请参阅基于Fisher矩阵置信区间的可靠性边界),并使用那里的描述来计算方差以及置信区间的上限和下限(R_U和R_L)

这是一个适用于我的Weibull拟合的工作代码示例,其可信度与测试数据集的关系基于reliawiki的描述(请参阅可靠性界限)。为了进行拟合,我使用了OLS模型拟合。

import os, sys
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from scipy.optimize import curve_fit
import math
import statsmodels.api as sm

def weibull_ticks(y, pos):
    return "{:.0f}%".format(100 * (1 - np.exp(-np.exp(y))))

def loglog(x):
    return np.log(-np.log(1 - np.asarray(x)))

class weibull_example(object):

    def __init__(self, dat):
        self.fits = {}
        dat.index = np.arange(1, len(dat) + 1)
        dat.sort_values('data', inplace=True)
        #define yaxis-values
        dat['percentile'] = dat.index*1/len(dat)
        self.data = dat

        self.fit()
        self.plot_data()

    def fit(self):
        #fit the data points with a the OLS model
        self.data=self.data[:-1]
        x0 = np.log(self.data.dropna()['data'].values)
        Y = loglog(self.data.dropna()['percentile'])
        Yx = sm.add_constant(Y)
        model = sm.OLS(x0, Yx)
        results = model.fit()
        yy = loglog(np.linspace(.001, .999, 100))
        YY = sm.add_constant(yy)
        XX = np.exp(results.predict(YY))
        self.eta = np.exp(results.params[0])
        self.beta = 1 / results.params[1]
        self.fits['syx'] = {'results': results, 'model': model,
                            'line': np.row_stack([XX, yy]),
                            'beta': self.beta,
                            'eta': self.eta}

        cov = results.cov_params()
        #get variance and covariance
        self.beta_var = cov[1, 1]
        self.eta_var = cov[0, 0]
        self.cov = cov[1, 0]

    def plot_data(self, fit='yx'):
        dat = self.data
        #plot data points
        plt.semilogx(dat['data'], loglog(dat['percentile']), 'o')
        fit = 's' + fit
        self.plot_fit(fit)

        ax = plt.gca()
        formatter = mpl.ticker.FuncFormatter(weibull_ticks)
        ax.yaxis.set_major_formatter(formatter)
        yt_F = np.array([0.001, 0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5,
                         0.6, 0.7, 0.8, 0.9, 0.95, 0.99])
        yt_lnF = loglog(yt_F)
        plt.yticks(yt_lnF)

        plt.ylim(loglog([.01, .99]))

    def plot_fit(self, fit='syx'):
        dat = self.fits[fit]['line']
        plt.plot(dat[0], dat[1])

        #calculate variance to get confidence bound
        def variance(x):
            return (math.log(x) - math.log(self.eta)) ** 2 * self.beta_var + \
                   (self.beta/self.eta) ** 2 * self.eta_var - \
                   2 * (math.log(x) - math.log(self.eta)) * (-self.beta/self.eta) * self.cov

        #calculate confidence bounds
        def confidence_upper(x):
            return 1-np.exp(-np.exp(self.beta*(math.log(x)-math.log(self.eta)) - 0.95*np.sqrt(variance(x))))
        def confidence_lower(x):
            return 1-np.exp(-np.exp(self.beta*(math.log(x)-math.log(self.eta)) + 0.95*np.sqrt(variance(x))))

        yvals_1 = list(map(confidence_upper, dat[0]))
        yvals_2 = list(map(confidence_lower, dat[0]))

        #plot confidence bounds
        plt.semilogx(dat[0], loglog(yvals_1), linestyle="solid", color="black", linewidth=2,
                 label="fit_u_1", alpha=0.8)
        plt.semilogx(dat[0], loglog(yvals_2), linestyle="solid", color="green", linewidth=2,
                 label="fit_u_1", alpha=0.8)

def main():
    fig, ax1 = plt.subplots()
    ax1.set_xlabel("$Cycles\ til\ Failure$")
    ax1.set_ylabel("$Weibull\ Percentile$")

    #my data points
    data = pd.DataFrame({'data': [1556, 2595, 11531, 38079, 46046, 57357]})
    weibull_example(data)

    plt.savefig("Weibull.png")
    plt.close(fig)

if __name__ == "__main__":
    main()

我的情节中的置信范围看起来不像我预期的那样。我尝试了许多不同的“方差”,只是为了了解功能并检查问题是否只是键入错误。同时,我确信该问题更为普遍,并且我从reliawiki的描述中了解到一些错误。不幸的是,我确实没有遇到什么问题,而且我不认识其他任何人。在互联网和不同的论坛上,我找不到合适的答案。

这就是为什么我决定在这里问这个问题的原因。这是我第一次在论坛中提问。因此,我希望我能充分解释所有内容,并且该代码示例对您有所帮助。 非常感谢:)

1 个答案:

答案 0 :(得分:0)

对于迟到的答案深表歉意,但我会为任何未来的读者提供它。 与其尝试自己实现这一点,不如考虑使用专为此设计的包,称为可靠性。 这是您的用例的 example

如果这个答案对你有帮助,记得点赞 :)