如何在温度时间序列中检测温度控制的开始和结束
信息处理
时间序列
衍生物
2022-01-31 13:27:32
2个回答
一种选择:很明显,在不受控制的范围内,温度遵循简单的指数加热/冷却曲线。就像是
在哪里是样本和之间的时间差建筑物的热时间常数(在不同的传感器位置可能略有不同)。
您可以简单地测试每个新样本与模型预测的差异,并设置允许误差的阈值。仅有的两个模型参数是建筑物的环境温度和热时间常数。
热时间常数是建筑物热阻的函数,除非有人打开/关闭窗户或发生一些实际的结构工作,否则它实际上不会改变。查看应该易于估计的数据。您可以尝试直接使用传感器或查看可靠的天气报告来获取环境。您也可以只使用前几个传感器的数据来估计环境,然后测试其他传感器是否同意。
所以这是一种尝试,但它并不是真正基于您的“受控”部分的方式。
这个想法是使用卡尔曼滤波器将开始和结束部分建模为一阶系统(正如 Hilmar 的好答案所暗示的那样)。受控部分将与此不同。
您可以查看卡尔曼滤波器中的创新(误差项),以查看创新是噪声还是更结构化的东西。
第一个代码只是生成信号。
from numpy import log10, asarray, polyfit, ceil, arange, exp, sin, pi, log, random, sum, diff
import matplotlib.pyplot as plt
T = 1000
Ton = 300
Toff = 650
#
# First period: temperature rising or falling as a first order system.
#
# IC @ 1 = min FC @ Ton = max
# f(t) = K1 + K2 exp(-t/tau)
# f(1) = K1 + K2 exp(-1/tau) = min (1)
# f(Ton) = K1 + K2 exp(-Ton/tau) = max (2)
#
# (1) - (2) --> K2 ( exp(-1/tau) - exp(-Ton/tau) ) = min - max --> K2 = (min - max) / (exp(-1/tau) - exp(-Ton/tau) )
mx = 100
mn = 10
tau = 150
time_period_1 = list(arange(1,Ton))
K2 = (mn - mx) / (exp(-1/tau) - exp(-Ton/tau))
print(K2)
K1 = mn - K2*exp(-1/tau)
K1_2 = mx - K2*exp(-Ton/tau)
print(str(K1) + " " + str(K1_2))
temperature = [K1 + K2*exp(-x/tau) + random.normal(0,0.001) for x in time_period_1]
plt.figure(1)
plt.plot(time_period_1, temperature)
#
# Second period: being controlled.
#
time_period_2 = list(arange(Ton, Toff))
variation = 50
mean_value = temperature[Ton-2]
tau2 = 120
temperature2 = [variation*sin(2.0*pi*(x/100))*exp(-(x-Ton)/tau2) + mean_value for x in time_period_2]
plt.plot(time_period_2, temperature2)
#
# Third period: back to first order.
#
# IC @ Toff = last value of previous period FC @ T = mx3
# f(t) = K1 + K2 exp(-t/tau)
# f(Toff) = K1 + K2 exp(-Toff/tau) = min (1)
# f(T) = K1 + K2 exp(-T/tau) = max (2)
#
# (1) - (2) --> K2 ( exp(-Toff/tau) - exp(-T/tau) ) = last value - mx3
# --> K2 = (last value - mx) / (exp(-Toff/tau) - exp(-T/tau) )
mx3 = 110
mn3 = temperature2[Toff-Ton-2]
tau2 = 50
time_period_3 = list(arange(Toff, T))
K23 = (mn3 - mx3) / (exp(-Toff/tau2) - exp(-T/tau2))
print(K23)
K13 = mn3 - K23*exp(-Toff/tau2)
K13_2 = mx3 - K23*exp(-T/tau2)
print(str(K13) + " " + str(K13_2))
temperature3 = [K13 + K23*exp(-x/tau2) for x in time_period_3]
plt.plot(time_period_3, temperature3)
all_temps = list(temperature) + list(temperature2) + list(temperature3)
plt.figure(2)
plt.plot(arange(1,T), all_temps)
然后设置卡尔曼滤波器:
import matplotlib.pyplot as plt
import numpy as np
from filterpy.kalman import KalmanFilter
from filterpy.common import Q_discrete_white_noise, Saver
dt = 0.1
r_std = 0.1
q_std = 0.1
cv = KalmanFilter(dim_x=2, dim_z=1)
cv.x = np.array([[all_temps[0]], [10.]]) # position, velocity
cv.F = np.array([[1, dt],[0, 1]])
cv.R = np.array([[r_std**2]])
cv.H = np.array([[1., 0.]])
cv.P = np.diag([.1**2, .03**2])
cv.Q = Q_discrete_white_noise(2, dt, q_std**2)
saver = Saver(cv)
for z in range(len(all_temps)):
cv.predict()
cv.update([all_temps[z] + random.randn()*q_std ])
saver.save() # save the filter's state
saver.to_array()
plt.figure(figsize=(10,10))
plt.plot(saver.x[:, 0], 'b.')
plt.plot(saver.x[:, 1], 'go')
plt.plot(all_temps,'k.')
# plot all of the priors
plt.plot(saver.x_prior[:, 0], 'r+')
# plot mahalanobis distance
plt.figure()
plt.figure(figsize=(10,10))
plt.plot(saver.P[:,0,0])
plt.plot(saver.P[:,0,1])
plt.plot(saver.P[:,1,0])
plt.plot(saver.P[:,1,1])
plt.figure()
plt.figure(figsize=(10,10))
plt.plot(abs(saver.y[:,0,0]))
N = 50
smoothed_innovations = np.convolve(abs(saver.y[:,0,0]), np.ones((N,))/N, mode='valid')
plt.plot(smoothed_innovations)
threshold = np.mean(smoothed_innovations[100:200])
standard_deviation = np.std(smoothed_innovations[100:200])
plt.plot(8*(smoothed_innovations > threshold + 3*standard_deviation))
plt.savefig('Q70221.png')
结果如下所示。
蓝线是创新的绝对值。橙色线是它的平滑版本。绿线表示橙色线何时高于或低于所选阈值。
不是真的 CUSUM,但我会努力让它更接近。
其它你可能感兴趣的问题