19 案例学习
本章回顾到目前为止我们看到的计算模式,并介绍可以应用它们的练习。
19.1 计算工具
在第11章我们看到了一种更新函数(update function),它使用多个赋值来解压一个State对象,并将状态变量赋值给局部变量。
def update_func(state, t, system):
s, i, r = state
infected = system.beta * i * s
recovered = system.gamma * i
s -= infected
i += infected - recovered
r += recovered
return State(S=s, I=i, R=r)
在run_simulation
中,我们再次使用多个赋值将状态变量赋值给TimeFrame
中的一行:
def run_simulation(system, update_func):
frame = TimeFrame(columns=system.init.index)
frame.row[system.t_0] = system.init
for t in linrange(system.t_0, system.t_end):
frame.row[t+1] = update_func(frame.row[t], system)
return frame
在第12章中,我们用了max
和idxmax
函数来计算度量指标:
largest_value = S.max()
time_of_largest_value = S.idxmax()
然后我们看到了logistic函数,是一种用来模拟变量之间关系的通用函数,比如作为支出函数的干预有效性。
在第13章中,我们用SweepFrame
对象来扫描两个参数:
def sweep_parameters(beta_array, gamma_array):
frame = SweepFrame(columns=gamma_array)
for gamma in gamma_array:
frame[gamma] = sweep_beta(beta_array, gamma)
return frame
然后我们用contour
生成一个二维扫描的等高线图。
在第15章中,我们用linrange
来创建一个等间距值的数组。linrange
和linspace
是很相似的:区别在于linrange
允许指定值之间的间距,并计算值的数量;linspace
允许指定值的数量,并计算它们之间的间距。
下面是一个使用linrange
的run_simulation
版本:
def run_simulation(system, update_func):
init = system.init
t_0, t_end, dt = system.t_0, system.t_end, system.dt
frame = TimeFrame(columns=init.index)
frame.row[t_0] = init
ts = linrange(t_0, t_end, dt)
for t in ts:
frame.row[t+dt] = update_func(frame.row[t], t, system)
return frame
在第16章中,我们用root_bisect
来求生成一个特定结果的参数的值,首先定义一个误差函数(error function):
system = make_system(T_init=90, r=r, volume=300, t_end=30)
results = run_simulation(system, update_func)
T_final = get_last_value(results.T)
return T_final - 70
然后将返回的值传递给root_bisect
并给定初始区间,如下所示:
res = root_bisect(error_func1, [0.01, 0.02])
r_coffee = res.root
在第17章中,我们用了interpolate
,返回的结果是一个函数:
I = interpolate(data.insulin)
我们可以像其他函数一样调用I
,将单个值或NumPy数组作为传递的参数:
I(18)
ts = linrange(t_0, t_end)
I(ts)
在第18章中,我们用了Params
对象,它是参数的集合。
params = Params(G0 = 290,
k1 = 0.03,
k2 = 0.02,
k3 = 1e-05)
第18章还介绍了run_ode_solver
,用来计算微分方程的数值解。
run_ode_solver
使用一个斜率函数(slope function),类似于更新函数:
G, X = state
k1, k2, k3 = system.k1, system.k2, system.k3
I, Ib, Gb = system.I, system.Ib, system.Gb
dGdt = -k1 * (G - Gb) - X*G
dXdt = k3 * (I(t) - Ib) - k2 * X
return dGdt, dXdt
然后我们这样调用它:
results, details = run_ode_solver(system, slope_func)
本章的其余部分将介绍可以用来练习这些工具的实例研究。
19.2 胰岛素最小模型
除了第17章的葡萄糖最小模型外,Berman等人还开发了胰岛素最小模型,在此模型中胰岛素的浓度 I 由以下微分方程控制:
其中:
- 是独立于血糖控制胰岛素消失率的参数。
- 是时间 t 时测得的血糖浓度。
- 是是葡萄糖阈值;当血糖高于这个水平时,会引发血胰岛素浓度的增加。
- 是血糖浓度高于(或低于)时控制血胰岛素浓度升高(或降低)速率的参数。
初始状态是。在葡萄糖最小模型中,我们将初始条件作为一个参数,我们将选择它来拟合数据。
该模型的参数可以用来估计和, 这两个值分别描述第一阶段和第二阶段胰腺反应对葡萄糖的敏感性。它们与以下参数相关:
其中,是测得的最大胰岛素水平,和分别是胰岛素和葡萄糖的基础水平。
在这本书的存储库中,你可以找到笔记本insulin.ipynb,其中包含本案例研究的启动程序代码。用它来实现胰岛素模型,找到拟合数据最好的参数,并估计这些值。
19.3 低通滤波器
下面的电路图[1]展示了由一个电阻和一个电容构成的低通滤波器。
图19.1
“滤波器”是将一个信号作为输入,并产生一个信号作为输出的电路。在这种情况下,”信号“是随时间变化的电压值。
如果一个滤波器允许低频信号保持不变地从到通过,而降低高频信号的振幅,那么它就是“低通”的。
应用电路分析定律,我们可以导出一个描述该系统现象的微分方程。通过求解微分方程,我们可以预测该电路对任何输入信号的影响。
假设我们给定某个特定时刻的和。根据欧姆定律,此定律是电阻特性的一个简单模型,通过电阻的瞬时电流为:
其中是以欧姆()为单位的电阻值。
假设没有电流通过电路的输出,霍尔基夫电流定律表明通过电容器的电流为:
根据电容器特性的一个简单模型,通过电容器的电流会引起电容器上电压的变化:
其中是以法拉()为单位的电容值。合并这些等式可以得到的微分方程:
在这本书的存储库中,你可以找到笔记本filter.ipynb,其中包含本案例研究的启动程序代码。按照以下说明模拟低通滤波器,输入信号如下所示:
其中A是输入信号的的振幅,比如5 V,f是信号的频率,单位为Hz。
在这本书的存储库中,你可以找到笔记本filter.ipynb,其中包含本案例研究的启动程序代码。阅读笔记本,运行代码,并做练习。
19.4 墙的热力学行为
本案例研究是基于Gori等人的一篇论文[2],该论文对砖墙的热力学行为进行了建模,目的是了解“建筑物的预期能量使用与其测量的能量使用之间的性能差距”。
下图展示了墙的场景及其模型:
图19.2
在墙的内外表面,他们测量了三天内的温度和热通量。将两个蓄热体连接到表面,并通过热敏电阻相互连接,以此来模拟墙模型。
该论文的主要方法是用贝叶斯方法推导系统的参数(两个蓄热体和三个热敏电阻)。
主要结果是两个模型的比较:一个模型有两个蓄热体,另外一个更简单的模型则只有一个蓄热体。他们发现双蓄热体的模型能更好地持续性地再生测量的热通量。
对于此案例研究,我们将实现他们的模型,并用论文中估计的参数运行它,然后使用fit_leastsq
来看看我们是否能找到产生较低误差的参数。
在这本书的存储库中,你可以找到笔记本wall.ipynb,其中有本案例研究的代码和结果。
本书的中文翻译由南开大学医学院智能医学工程专业2018级、2019级的师生完成,方便后续学生学习《Python仿真建模》课程。翻译人员(排名不分前后):薛淏源、金钰、张雯、张莹睿、赵子雨、李翀、慕振墺、许靖云、李文硕、尹瀛寰、沈纪辰、迪力木拉、樊旭波、商嘉文、赵旭、连煦、杨永新、樊一诺、刘志鑫、彭子豪、马碧婷、吴晓玲、常智星、陈俊帆、高胜寒、韩志恒、刘天翔、张艺潇、刘畅。
整理校订由刘畅完成,如果您发现有翻译不当或者错误,请邮件联系changliu@nankai.edu.cn。
本书中文版不用于商业用途,供大家自由使用。
未经允许,请勿转载。
-
Gori, Marincioni, Biddulph, Elwell, “Inferring the thermal resistance and effective ther-mal mass distribution of a wall from in situ measurements to characterise heat transfer at both the interior and exterior surfaces”, Energy and Buildings, Volume 135, pages 398-409, http://modsimpy.com/wall2 . 作者将其论文置于知识共享(Creative Commoms)许可下,并在http://modsimpy.com/wall 上提供了他们的数据,我感谢他们致力于开放、可复制的科学,这使得本案例研究成为可能。 ↩