提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
前言
1 问题一
1.1 问题重述
1.2 问题分析
1.3 解决方法描述
1.4 结果
2 问题二
2.1 问题重述
2.2 问题分析
2.3 解决方法描述
总结
近日参加了校内的建模比赛,小组的选题为COVID-19相关的题目,笔者将此次主要参与解题的两小问做个记录(虽然解题方法很辣鸡,但还是厚颜无耻的贴上来了),有兴趣友友可以继续研究~
实际中核酸检测并不是完全准确的,一个阴性样本,检测出来是阴性的概率是q,阳性的概率是1-q(假阳);一个阳性样本,检测出来是阳性的概率是p,阴性的概率是1-p(假阴);一般对阳性的结果都会对该样本进行二次复检,所以假阳基本会被排除,而对阴性的结果不会进行二次检测,所以假阴无法得知,一般情况q∈[0.95,0.99],p∈[0.5,07]。如果有一个学生在核酸检测的后一天外出时感染了新冠病毒,且无任何症状,请问现在核酸检测有效期是72小时,那么通过学校的核酸检测,能够发现这个学生是阳性平均所需要的时间是多少天?(核酸检测当天出结果)
我们假设:①当连续两次核酸检测结果都为阳性时,才可判定为确诊病例;②当检测结果为假阴的累计概率小于 0.05 时予以排除。
该学生在第1次核酸检测的后一天外出时感染了新冠病毒,按照常规72小时核酸检测制,那么下次核酸检测时间为 2 天后。2 天后进行第2次核酸检测时,有阴性和阳性两种核酸结果。如果是阳性,那么 24 小时后再进行第3次核酸检测,若核酸检测结果依然是阳性,则确定为感染者;如果是阴性,则 72 小时后再进行第3次核酸检测.......依此循环,并在每次循环时当检测结果为阴性时计算其概率和总检验天数。
针对这个问题,笔者设计了一个循环判断方法,具体流程描述如下:
Step1:该阳性病例在核酸检测后的第二天感染,因此会在两天之后进行 72 小时制的常规核酸检测,由此定义初始筛查天数为 2 天。
Step:2:定义一个 0-1 变量 Xi , i 表示为该阳性样本第 i 次进行核酸检测,变量 Xi 表示第 i 次核酸检测结果,若 Xi = 1,表示此次核酸检测呈阳性,否则为阴性
Step3:在每一次的核酸检测中,该阳性病例,检测出来是阳性的概率为p ,阴性的概率为1- p(假阴),且p ∈ [0.5,0.7]。利用随机函数在区间 [0.5,0.7] 中随机生成概率 p,再根据概率 p 随机生成Xi = 0 或 1。
Step4:若Xi = 1,则进入阳性判断循环,将此次的核酸检测次序 i 输入列表(列表记录了所有检测结果为阳性的检测次序 i),计算本次输入的次序 i 值与列表中上一个相邻元素的差值,若差值为 1,表示本次阳性的核酸检测与上一次阳性的核酸检测为连续采样,即连续两次核酸检测结果为阳性,该病例确诊,停止循环,计算当前累加的筛查天数并输出结果,若判断为否,则令筛查天数加 1,表示下一次进行核酸检测为 24 小时后;若Xi = 0,则进入阴性判断循环,计算累乘假阴性的概率P = (1 − p)n,并判断 P 是否小于 0.05,若判断为是,停止循环,计算当前累加的筛查天数,并输出结果,若判断为否,则令筛查天数加 3,表示下一次进行核酸检测为 72 小时后。
Step5:分别进行小、中、大三个规模实例的随机实验,对每次输出的筛查天数求均值,得到最终的平均筛查天数。
上述思路的流程图如图所示
代码如下:
import numpy as np
import random
sum_days = 0# 定义每次随机实验筛查耗费天数之和
for j in range(0,5000):
print("随机实验次数:【",j+1,"】")
days=2# 定义初始天数
sum_results = 0# 定义初始天数
probability = 1# 定义事件发生概率
r1_list = []# 定义核酸检测结果为阳性次序的列表
for i in range(1,20):
p = random.uniform(0.5, 0.7)# 概率p的取值范围
p = float(format(p, '.3f'))# 按照区间随机生成三位小数
r = np.random.binomial(1,p)# 按照概率p生成每次检测结果
if r == 1:
results = "阳性"
else:
results = "阴性"
print("第",i,"次随机生成概率p,p值为",p,",本次检测结果为",results)
# 检测结果为阳性,进入阳性的判断条件
if r == 1:
r1_list.append(i)
sum_results += 1
# 根据相邻两次检测结果为阳性的次序,判断是否为间隔24小时的采样
if r1_list[sum_results-1]- r1_list[sum_results-2] != 1:
# 一次检测结果为阳性,第二天继续采样检测
days += 1
else:
# 连续两天检测结果为阳性,确诊
print("连续两次检测结果为阳,确定为阳性,确诊耗费",days,"天\n")
break
# 检测结果为阴性,进入阴性的判断条件
else:
# 根据事件发生的累计概率,作为判断条件
probability = probability * (1-p)
if probability < 0.05:
print("确诊假阴的事件概率小于0.05,确定为阳性,确诊耗费",days,"天\n")
break
else:
# 未达到约束概率约束条件,则于72小时后进行下一次核酸检测
days += 3
sum_days += days
mean_days = sum_days//j
print("生成【",j+1,"】个随机实例,查找该阳性病例的平均耗费时间为",mean_days,"天")
通过实例规模为 1000 个、5000 个、10000 个的三次随机实验,实验结果如下图所示,得到平均筛查时间均为 7 天。
以部分确诊数据(题目提供)为依据,建立合适的传染病模型。
根据数据绘制散点图,大致观察确诊数量的变化情况。
可以发现规模呈现s型变化,即初期感染群体个体数很少,密度增长缓慢;中期随着感染群体中个体数增加,密度增长加快;中后期感染群体呈现爆发式扩大,密度增长最快;后期在防疫措施的加持下,感染群体的增长速度得到遏制,增长变慢。
查阅资料,发现Logistic回归模型的增长曲线与确诊数量增长线非常相似,
Logistic方程表达式如下,通过拟合数据,求解方程中的参数K、P0、r
运用 Logistic模型,并进行数据拟合求解参数,代码如下:
import numpy as np #导入数值计算模块
import pandas as pd #导入数据处理模块
import matplotlib.pyplot as plt #导入绘图模块
from scipy.optimize import curve_fit #导入拟合模块
plt.rcParams["font.sans-serif"]="SimHei" #黑体中文
plt.rcParams["axes.unicode_minus"]=False #显示负号
data=pd.read_csv("C:/Users/TR/Desktop/数据分析/data.csv", encoding="gb18030") #读取数据
date=data['time'] #日期
confirm=data['infecter'] #确诊数
t=range(len(confirm)) #构造横轴
#散点图
fig=plt.figure(figsize=(16,8)) #建立画布
ax=fig.add_subplot(1, 1, 1)
ax.scatter(t,confirm, color="red", label="确诊人数") #真实数据散点图
ax.set_xlabel("日期", fontsize='15') #横坐标
ax.set_ylabel("累计确诊人数", fontsize='15') #纵坐标
plt.title('3月1日-5月26日每日累计确诊病例变化图', fontsize='25',fontweight='bold', color='black')#标题
ax.set_xticklabels(['','3月1号', '3月21号', '4月11号', '5月1号','5月22号'], rotation=30, fontsize=10) #自定义横坐标标签
plt.savefig('真实数据散点图.png', dpi = 500)
#拟合
def logistic(t,K,P0,r): #定义logistic函数
exp_value=np.exp(r*(t))
return (K*exp_value*1)/(K+(exp_value-1)*1)
coef, pcov = curve_fit(logistic, t, confirm) #拟合
print(coef) #logistic函数参数
y_values = logistic(t,coef[0], coef[1], coef[2]) #拟合y值
print(coef[0], coef[1], coef[2]) #打印参数K,P0,r
ax.plot(t,y_values,color="blue", label="拟合曲线") #画出拟合曲线
plt.savefig('拟合结果图.png', dpi = 500)
运用了比较简单的方法对问题进行了分析与处理。第二题的解决方法,最开始考虑的是传染病模型,如SI、SEIR等,奈何笔者基础太差,短时间内无法全部实现,所以转变思想改用Logistic模型。同样的,在翻阅Logistic模型相关的博客时,也发现有的博主利用网格调参的方法使参数更优,后续有空笔者会继续进行学习的!
参考资料:
python实现logistic增长模型拟合2019-nCov确诊人数
Logistic模型拟合COVID-19疫情以及Python实现