SIR模型預測新冠病毒肺炎發病數據

大家還好嗎?
背景就不用多說了吧?本來我是初四上班的,現在延長到2月10日了。這是我工作以來時間最長的一個假期了。可惜哪也去不了。待在家裏,沒啥事,就用python模擬預測一下新冠病毒肺炎的數據吧。要聲明的是本文純屬個人自娛自樂,不代表真實情況。
採用SIR模型,S代表易感者,I表示感染者,R表示恢復者。染病人羣爲傳染源,通過一定機率把傳染病傳給易感人羣,ta自己也有一定的機率被治癒並免疫,或死亡。易感人羣一旦感染即成爲新的傳染源。
模型假設:
①不考慮人口出生、死亡、流動等情況,即人口數量保持常數。
②一個病人一旦與易感者接觸就必然具有一定的傳染力。假設 t 時刻單位時間內,一個病人能傳染的易感者數目與此環境內易感者總數s(t)成正比,比例係數爲β,從而在t時刻單位時間內被所有病人傳染的人數爲βs(t)i(t)。
③ t 時刻,單位時間內從染病者中移出的人數與病人數量成正比,比例係數爲γ,單位時間內移出者的數量爲γi(t)。
模型爲

其中,β爲感染係數,代表易感人羣與傳染源接觸被感染的概率。γ爲隔離(恢復)係數,我們對其倒數1/γ更感興趣,代表了平均感染時間(average infectious period)。S(0)爲初始易感人數,I(0)爲初始感染人數。
按照[1]裏面的代碼模型的感染人數是這樣的

現在的問題就是利用現有的數據找到新冠肺炎的β值,γ值等數據了。先把數據拔下來吧。從[3]上扒數據,由於數據不多,就手工完成吧。保存到csv文件裏。
然後把數據作圖

還有一個指標是再生數R0=β/γ,大於1時人羣中大部分才被感染[4]。世衛組織1月23日的估計是R0在1.4到2.5之間[5],最新的根據前425例發病數據的估計值爲2.2[6]。
文章[7]中的按一般病毒性肺炎恢復期25天計算得到的γ值爲0.04。
關於β值和初始易感人羣,[7]的作者採用的方法是先估計一個區間,然後用最小二乘法找到最佳參數,β≈3.57*10^-5。S[0]的範圍爲5000-30000人。[7]文章裏有matlab代碼,我用python改寫一下,由於對最小二乘法法的實現比較陌生,嘗試了半天,最後我決定用最笨的辦法——窮舉法。就是用兩個嵌套循環將範圍內所有β值和S0值都試一遍,計算每次嘗試結果與實際數據之間差值的平方和,平方和最小的一組β值和S0值用來做預測。代碼如下:
γ值設定爲0.04,即一般病程25天
用最小二乘法估計β值和初始易感人數

gamma = 0.04
S0 = [i for i in range(20000, 40000, 1000)]
beta = [f for f in np.arange(1e-7, 1e-4, 1e-7)]
# 定義偏差函數
def error(res):
    err = (data["感染者"] - res)**2
    errsum = sum(err)
    return errsum

# 窮舉法,找出與實際數據差的平方和最小的S0和beta值
minSum = 1e10
minS0 = 0.0
minBeta = 0.0
bestRes = None

for S in S0:
    for b in beta:
        # 模型的差分方程
        def diff_eqs_2(INP, t):
            Y = np.zeros((3))
            V = INP
            Y[0] = -b * V[0] * V[1]
            Y[1] = b * V[0] * V[1] - gamma * V[1]
            Y[2] = gamma * V[1]
            return Y

        # 數值解模型方程
        INPUT = [S, I0, 0.0]
        RES = spi.odeint(diff_eqs_2, INPUT, t_range)
        errsum = error(RES[:21, 1])
        if errsum < minSum:
            minSum = errsum
            minS0 = S
            minBeta = b
            bestRes = RES
            print("S0=%d beta=%f minErr=%f" % (S, b, errsum))
print("S0 = %d β = %f" % (minS0, minBeta))

結果 S0 = 39000, β = 8e-6
上述程序耗時較長,只在探索時執行,完了就註釋掉,用最優參數進行預測。

預測最大感染人數:23769 時間是在1月10日的33天后,也就是2月12日。
本文代碼:https://github.com/zwdnet/2019-nCov-SIRmodel
與[7]作者討論,我的算法是將S0與β作爲獨立的兩個變量用兩個循環嵌套分別遍歷,他的做法是用每個S0的值代入微分方程算出相應的β值。他的算法應該更好一些,我正在嘗試。另外在微信公衆號上看到一篇更系統的關於此次疫情的數學模型的文章:https://mp.weixin.qq.com/s/rgaJtA4jioLOCHs_oCauDg

再次聲明:本文只是我個人在家無聊的遊戲作品,不是正兒八經的預測。我也不是流行病學專業人士。祝疫情早日結束!武漢加油!中國加油!

參考文獻:
[1]SIR模型實現, https://blog.csdn.net/huozi07/article/details/50450433
[2]百度百科SIR模型詞條, https://baike.baidu.com/item/SIR%E6%A8%A1%E5%9E%8B
[3]疫情通報.http://www.nhc.gov.cn/xcs/yqtb/list_gzbd.shtml
[4]計算流行病學. https://www.csdn.net/article/1970-01-01/2816565
[5]關於新型冠狀病毒(2019-nCoV)疫情的《國際衛 生條例(2005)》突發事件委員會會議的聲明. https://www.who.int/zh/news-room/detail/23-01-2020-statement-on-the-meeting-of-the-international-health-regulations-(2005)-emergency-committee-regarding-the-outbreak-of-novel-coronavirus-(2019-ncov)
[6]Early Transmission Dynamics in Wuhan, China, of Novel Coronavirus–Infected Pneumonia. https://www.nejm.org/doi/full/10.1056/NEJMoa2001316?query=featured_home
[7]基於SIR模型對新型冠狀病毒疫情趨勢的簡單分析.https://zhuanlan.zhihu.com/p/104379096

我發文章的四個地方,歡迎大家在朋友圈等地方分享,歡迎點“在看”。
我的個人博客地址:https://zwdnet.github.io
我的知乎文章地址: https://www.zhihu.com/people/zhao-you-min/posts
我的博客園博客地址: https://www.cnblogs.com/zwdnet/
我的微信個人訂閱號:趙瑜敏的口腔醫學學習園地

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章