[英]Matlab, Econometrics toolbox - Simulate ARIMA with deterministic time-varying variance
[英]Problem using GEKKO to do regime change detection (estimating time-varying variables)
使用 GEKKO Python,我们在尝试学习每天可能多次变化的参数时遇到了麻烦。 在某些学科中,这也称为“状态检测或状态变化检测”。 我们(我和我来自温德斯海姆应用科学大学的同事 Henri ter Hofte)构思了 3 种策略但都失败了(详见下文)。
我们的问题:
非常感谢您的帮助。
=== 问题:我们有关于以下方面的时间序列数据:(1) 二氧化碳浓度 (2) 通风率(或者更确切地说:阀门分数,当乘以已知的最大通风率时,它给出通风率)(3) 占用率(数量房间里的人)
对于研究问题 (A),我们想知道一天中每个小时对 (2) 的正确估计,给定有关 (1) 和 (3) 的时间序列数据。 对于研究问题 (B),我们想知道一天中每个小时对 (3) 的正确估计,给定关于 (1) 和 (2) 的时间序列数据。
我们专注于研究问题 A(但对 B 也有类似的问题)。
=== 三种策略:
我们考虑了 3 种不同的策略如何使用 GEKKO Python 来实现:策略 I. 在我们的 GEKKO model (m.MV) 中将变量 valve_frac 声明为操纵变量,因为 GEKKO 文档说这些变量可以“由优化器调整以最小化每个时间点的目标 function”。 和“操纵变量类似于 FV,但可以随每个数据行而变化,由优化器计算 (STATUS=1) 或由用户指定 (STATUS=0)。” 根据https://gekko.readthedocs.io/en/latest/imode.html#mv
战略二。 将时间分成几个较短的时间跨度(例如,每小时一个时间跨度),然后将 valve_frac 学习为 GEKKO 固定变量 (m.FV),每小时一个。
战略三。 将问题重新定义为 GEKKO,就好像它是一个控制问题:设定点达到特定的 CO2 浓度,GEKKO 可以使用 valve_frac 作为控制变量 (m.CV)
我们尝试实施策略 I(请参阅下面的更多信息和代码)但未能获得正确的结果。 考虑从物理学中导出的一些方程,我们打算找到一些特定变量的最佳值(下表中的 valve_frac__0 变量。有一个 dataframe (df_learn) 是这样的:
指数 | 约会时间 | 占用__p | valve_frac__0 | co2__ppm |
---|---|---|---|---|
1个 | 2022.12.01 – 00:00:00 | 0 | 0.51 | 546 |
2个 | 2022.12.01 – 00:15:00 | 4个 | 0.85 | 820 |
3个 | 2022.12.01 – 00:30:00 | 1个 | 0.21 | 595 |
4个 | 2022.12.01 – 00:45:00 | 2个 | 0.74 | 635 |
5个 | 2022.12.01 – 00:15:00 | 0 | 0.65 | 559 |
6个 | 2022.12.01 – 00:15:00 | 0 | 0.45 | 538 |
7 | 2022.12.01 – 00:15:00 | 2个 | 0.82 | 659 |
. | . | . | . | . |
. | . | . | . | . |
. | . | . | . | . |
1920 | 2022.12.20 – 00:15:00 | 3个 | 0.73 | 749 |
我们正在尝试开发移动地平线估计 model (IMODE=5) 或控制 model (IMODE=6) 来预测 valve_frac__0 值。 以下是 Gekko 格式的代码:
===代码:
from gekko import GEKKO
# Gekko Model - Initialize
m = GEKKO(remote = False)
m.time = np.arange(0, duration__s, step__s)
# Conversion factors
s_min_1 = 60
min_h_1 = 60
s_h_1 = s_min_1 * min_h_1
mL_m_3 = 1e3 * 1e3
million = 1e6
# Constants
MET__mL_min_1_kg_1_p_1 = 3.5
desk_work__MET = 1.5
P_std__Pa = 101325
R__m3_Pa_K_1_mol_1 = 8.3145
T_room__degC = 20.0
T_std__degC = 0.0
T_zero__K = 273.15
T_std__K = T_zero__K + T_std__degC
T_room__K = T_zero__K + T_room__degC
infilt__m2 = 0.001
# Approximations
room__mol_m_3 = P_std__Pa / (R__m3_Pa_K_1_mol_1 * T_room__K)
std__mol_m_3 = P_std__Pa / (R__m3_Pa_K_1_mol_1 * T_std__K)
co2_ext__ppm = 415
# National averages
weight__kg = 77.5
MET__m3_s_1_p_1 = MET__mL_min_1_kg_1_p_1 * weight__kg / (s_min_1 * mL_m_3)
MET_mol_s_1_p_1 = MET__m3_s_1_p_1 * std__mol_m_3
co2_o2 = 0.894
co2__mol0_p_1_s_1 = co2_o2 * desk_work__MET * MET_mol_s_1_p_1
# Room averages
wind__m_s_1 = 3.0
# GEKKO Manipulated Variables: measured values
occupancy__p = m.MV(value = df_learn.occupancy__p.values)
occupancy__p.STATUS = 0; occupancy__p.FSTATUS = 1
# Strategy I:
valve_frac__0 = m.MV(value = df_learn.valve_frac__0.values)
valve_frac__0.STATUS = 1; valve_frac__0.FSTATUS = 0
# Strategy II:
#valve_frac__0 = m.FV(value = df_learn.valve_frac__0.values)
#valve_frac__0.STATUS = 1; valve_frac__0.FSTATUS = 0
# GEKKO Control Varibale (predicted variable)
co2__ppm = m.CV(value = df_learn.co2__ppm.values)
co2__ppm.STATUS = 1; co2__ppm.FSTATUS = 1
# GEKKO - Equations
co2_loss__ppm_s_1 = m.Intermediate((co2__ppm - co2_ext__ppm) * (vent_max__m3_s_1 * valve_frac__0 + wind__m_s_1 * infilt__m2) / room__m3)
co2_gain_mol0_s_1 = m.Intermediate(occupancy__p * co2__mol0_p_1_s_1 / (room__m3 * room__mol_m_3))
co2_gain__ppm_s_1 = m.Intermediate(co2_gain_mol0_s_1 * million)
m.Equation(co2__ppm.dt() == co2_gain__ppm_s_1 - co2_loss__ppm_s_1)
# GEKKO - Solver setting
m.options.IMODE = 5
m.options.EV_TYPE = 1
m.options.NODES = 2
m.solve(disp = False)
我为每个场景得到的结果如下:
模拟的“co2__ppm”没有 output,valve_frac__0 = 0 的值为 output
valve_frac__0 = 0.166 的模拟和测量“co2__ppm”与 output 值之间存在很大差异(这是不合理的)
只要valve_frac__0
是应该根据 CO2 PPM 数据估算的可调未知参数,代码看起来就应该可以工作。 这是已发布数据的较小子集的结果。
如果阀门 position 的下限为零,则数据不完全吻合。
valve_frac__0 = m.MV(value = valve_frac__0,lb=0)
否则,可以调整阀门 position 以完美匹配 CO2 数据。
这是带有示例数据的完整脚本。
from gekko import GEKKO
import numpy as np
# Gekko Model - Initialize
m = GEKKO(remote = False)
# data
# 1 2022.12.01 – 00:00:00 0 0.51 546
# 2 2022.12.01 – 00:15:00 4 0.85 820
# 3 2022.12.01 – 00:30:00 1 0.21 595
# 4 2022.12.01 – 00:45:00 2 0.74 635
# 5 2022.12.01 – 00:15:00 0 0.65 559
# 6 2022.12.01 – 00:15:00 0 0.45 538
# 7 2022.12.01 – 00:15:00 2 0.82 659
occupancy__p = np.array([0,4,1,2,0,0,2])
valve_frac__0 = np.array([0.51,0.85,0.21,0.74,0.65,0.45,0.82])
co2__ppm_meas = np.array([546,820,595,635,559,538,659])
duration__s = len(co2__ppm_meas)
m.time = np.linspace(0,duration__s-1,duration__s)
vent_max__m3_s_1 = 1
room__m3 = 1
# Conversion factors
s_min_1 = 60
min_h_1 = 60
s_h_1 = s_min_1 * min_h_1
mL_m_3 = 1e3 * 1e3
million = 1e6
# Constants
MET__mL_min_1_kg_1_p_1 = 3.5
desk_work__MET = 1.5
P_std__Pa = 101325
R__m3_Pa_K_1_mol_1 = 8.3145
T_room__degC = 20.0
T_std__degC = 0.0
T_zero__K = 273.15
T_std__K = T_zero__K + T_std__degC
T_room__K = T_zero__K + T_room__degC
infilt__m2 = 0.001
# Approximations
room__mol_m_3 = P_std__Pa / (R__m3_Pa_K_1_mol_1 * T_room__K)
std__mol_m_3 = P_std__Pa / (R__m3_Pa_K_1_mol_1 * T_std__K)
co2_ext__ppm = 415
# National averages
weight__kg = 77.5
MET__m3_s_1_p_1 = MET__mL_min_1_kg_1_p_1 \
* weight__kg / (s_min_1 * mL_m_3)
MET_mol_s_1_p_1 = MET__m3_s_1_p_1 * std__mol_m_3
co2_o2 = 0.894
co2__mol0_p_1_s_1 = co2_o2 * desk_work__MET * MET_mol_s_1_p_1
# Room averages
wind__m_s_1 = 3.0
# GEKKO Manipulated Variables: measured values
occupancy__p = m.MV(value = occupancy__p)
occupancy__p.STATUS = 0; occupancy__p.FSTATUS = 1
# Strategy I:
valve_frac__0 = m.MV(value = valve_frac__0,lb=0)
valve_frac__0.STATUS = 1; valve_frac__0.FSTATUS = 0
# Strategy II:
#valve_frac__0 = m.FV(value = df_learn.valve_frac__0.values)
#valve_frac__0.STATUS = 1; valve_frac__0.FSTATUS = 0
# GEKKO Control Varibale (predicted variable)
co2__ppm = m.CV(value = co2__ppm_meas)
co2__ppm.STATUS = 1; co2__ppm.FSTATUS = 1
# GEKKO - Equations
co2_loss__ppm_s_1 = m.Intermediate((co2__ppm - co2_ext__ppm) \
* (vent_max__m3_s_1 * valve_frac__0 \
+ wind__m_s_1 * infilt__m2) / room__m3)
co2_gain_mol0_s_1 = m.Intermediate(occupancy__p \
* co2__mol0_p_1_s_1 / (room__m3 * room__mol_m_3))
co2_gain__ppm_s_1 = m.Intermediate(co2_gain_mol0_s_1 * million)
m.Equation(co2__ppm.dt() == co2_gain__ppm_s_1 - co2_loss__ppm_s_1)
# GEKKO - Solver setting
m.options.IMODE = 5
m.options.EV_TYPE = 1
m.options.NODES = 2
m.options.SOLVER = 1
m.solve(disp = True)
import matplotlib.pyplot as plt
plt.subplot(2,1,1)
plt.plot(m.time,valve_frac__0.value,'r-',label='Valve Frac')
plt.legend(); plt.grid(); plt.ylabel('Valve Frac')
plt.subplot(2,1,2)
plt.plot(m.time,co2__ppm_meas,'ko',label='Measured')
plt.plot(m.time,co2__ppm.value,'k--',label='Predicted')
plt.legend(); plt.grid()
plt.xlabel('Time'); plt.ylabel('CO2')
plt.savefig('results.png',dpi=300)
plt.show()
B题,调整代码,使阀门position固定在实测值和优化器确定的占用率。
occupancy__p = m.MV(value = occupancy__p)
occupancy__p.STATUS = 1; occupancy__p.FSTATUS = 0
# Strategy I:
valve_frac__0 = m.MV(value = valve_frac__0,lb=0)
valve_frac__0.STATUS = 0; valve_frac__0.FSTATUS = 1
使用occupancy__p.MV_STEP_HOR = 2
或更高降低优化参数可以更改的频率(例如每 2 小时)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.