Censored Weibull Distribution 最大似然估計 (結合牛頓法求解)
前言:寫這篇博客是因爲我前幾天偶然讀到一篇很有意思的文章, 然後想用自己的實驗數據測試一下其分佈情況,本以外是一個很簡單的工作,但再簡單的工作也需要不斷的更新學習。在學習過程中,我發現已經有很多博文詳述了Weibull分佈的應用和意義,然而對於如何進行參數估計的問題,卻缺乏更加詳細的記錄文檔。於是無聊而又不務正業的Shecan稍微探索了一下,並把筆記分享給大家。如有錯誤或者疑問,請給Shecan留言。
Weibull 分佈函數 CDF:
這裏 表示 Scale Parameter, 表示 Shape Parameter。
分佈密度 PDF:
其中
censored 似然函數的定義:
其中
把(1),(2)帶入(3)兩邊求對數,並簡化求得對數似然函數:
其中,, 可以通過最大化似然函數求得,對(4)求一階導數
(5),(6)是關於 的外生解,無法求出其解析解,因而需要求解以上兩個非線性方程組的數值解。求解非線性方程組數值解的方法有很多,比如非線性最小二乘法,Broyden方法等等,但是我們遵循簡單即有效的原則,嘗試最爲簡單的Newton-Rapson解的搜索方法。首先,簡化(5)得
因此,我們只需要通過(6)求解 , 假設
其中
and
這裏的 代表 failed number。
(9)和 (10)代入(8),即得
求導可得
因而,我們通過牛頓法迭代搜索非線性方程 的解。
求解出 後,通過 (7)即可求解 。
Weibull MLE 程序實現:
推導過程寫完了,怎麼用程序實現呢?從多年來失敗的研究經驗Shecan總結了一個道理:不要重複造輪子。(其實學習的時候重複造下輪子也有好處。) Shecan 發現Python有一個比較有意思的Package。 叫做Weibull,基本可以滿足你大部分的研究需求。具體怎麼使用,請參考下面的參考文獻。但是,有時候我們依舊需要對模型進行改進,比如說兩參數的Weibull分佈改成三參數的Weibull分佈。爲滿足這種需求,Shecan找出了Weibull Package MLE部分的源程序,並改寫成了面向過程的編程方式,具體如下:
你可以把下面的代碼複製到 Jupyter Notebook:
註明:程序來自於Weibull Package:
[https://weibull.readthedocs.io/en/latest/examples.html](Weibull Package Doc)
import numpy as np
import pandas as pd
測試數據:
fail_times = [ 9402.7, 6082.4, 13367.2, 10644.6, 8632.0, 3043.4, 1034.5, 2550.9, 2550.9, 3637.1]
suspended = [True, True, True, True, True,False, False, False, True, True]
data = pd.DataFrame({'data': fail_times, 'susp':suspended})
MLE Calibration: 通過以上的推導過程可以很容易的讀懂這段代碼。
# filter the failed samples and extract values
df_failed = data[data.susp == False].copy()
dtf_failed = df_failed["data"].values
df_failed["ln_x_div_r"] = df_failed.apply(lambda s: np.log(s['data'])/len(df_failed), axis=1)
# extract data of all the values
dtf_all = data['data'].values
# use Newton-Rhapson method for estimating the shape parameter
# give initial value for the shape paramter:
shape = (((6.0 / np.pi ** 2)
* (np.sum(np.log(dtf_all) ** 2)
- ((np.sum(np.log(dtf_all))) ** 2) / dtf_all.size))
/ (dtf_all.size - 1)) ** -0.5
# 10 iterations of the newton-rhapson method
for i in range(1, 11):
a = np.sum(np.log(dtf_failed) * 1.0) / dtf_failed.size
b = np.sum(dtf_all ** shape)
c = np.sum((dtf_all ** shape) * np.log(dtf_all))
h = np.sum((dtf_all ** shape) * (np.log(dtf_all)) ** 2)
shape = shape + (a + (1.0 / shape) - (c / b)) / ((1.0 / shape ** 2) + ((b * h) - c ** 2) / b ** 2)
shape = max(shape, 0.005)
scale = (np.sum((dtf_all ** shape) / len(df_failed))) ** (1 / shape)
# Print the results
print(shape,scale)
題外話:小時候老師教育我們如果要成爲一個成功的人,頭懸樑,錐刺骨,臥薪嚐膽,這些典故都很勵志。可是長大後發現了一個殘酷的真相,成功人士萬里挑一,而千千萬萬的普通人雖然沒有那麼成功,卻也在以一己之力改變世界。比如說戰疫前線的醫生和護士們,比如說用自己的才能爲這次疫情做貢獻的各路神仙。經歷了這些事,這些人,Shecan開始反思,與其教育自己的孩子成爲一個成功的人,不如教育他們盡一己之力做一個對社會有貢獻的人,或許這樣的人生會更自信,更快樂,並獲得更高的自我效能感。這也算是Shecan開始做筆記,並分享筆記的原因吧。