这一节的代码,对于tensor切片的操作(下标),会让人头晕,在此总结一些个人理解希望有所裨益!
滑动窗口
max_steps = 64
最大观测步数,就是基于现有数据,最多预测未来多少个数据
举例如tau为4,现有t-4,t-3,t-2,t-1四个已知数据,预测t,则为一步预测
根据t-3,t-2,t-1,t,预测t+1,则为第二步预测
把这个过程看作滑动窗口来理解很形象
数据形状
features = torch.zeros((T - tau - max_steps + 1, tau + max_steps))
这节代码是做并行化处理的,所以比较绕
先看列数,前tau列放真实数据,后max_steps放预测数据
再看行数,对于总数据量T,已知tau,观测最大步数为max_steps,则已知数据的行数为T - tau - (max_steps - 1),这里算不清楚的,把T=1000,tau=4,max=1带进去算算就知道为什么了:
第一行为(x0,x1,x2,x3)
第二行为(x1,x2,x3,x4)
由于观测步数和tau的限制,最后一行需要预留够tau与max_steps的位置
最后一行为(x995,x996,x997,x998)——预测x999
995 = 1000 - 4 - (1 - 1)
数据填充
for i in range(tau):
features[:, i] = x[i: i + T - tau - max_steps + 1]
前tau列,填充真实数据,排列如下:
(x0,x1,x2,x3)
(x1,x2,x3,x4)
(x2,x3,x4,x5)
........
1000 - 4 - 64 = 932
(x932,x933,x934,x935)
这里对于features进行列填充,那么截取的x长度就是features的行数
预测操作
for i in range(tau, tau + max_steps):
features[:, i] = net(features[:, i - tau:i]).reshape(-1)
从features[tau]开始,就是预测的数据,进行预测、填充、再预测的循环
那么对于features的每一列,选取features的所有行,其 i-tau ~ i-1 这tau列数据进行并行化预测,然后填充至features[i]
画图操作
steps = (1, 4, 16, 64)
d2l.plot([time[tau + i - 1: T - max_steps + i] for i in steps],
[features[:, (tau + i - 1)].detach().numpy() for i in steps],
'time',
'x',
legend=[f'{i}-step preds' for i in steps], xlim=[5, 1000],
figsize=(6, 3)
)
根据steps,画出不同step的预测结果图
首先看横轴time
起点:
tau + i - 1
具体举例看tau为4,i为1时,得到预测的第一个时间点就是time[4],也就是用
(x0,x1,x2,x3)预测出了x4,画在time[4]的位置
终点:
T - max_steps + i
features总共为T - tau - max_steps + 1行,time起点为tau + i - 1,终点就为起点+行数
纵轴features
选取所有行,对应列,重点看对应列
对应列的意思是,基于不同的已知数据,往前推测k步得到的不同结果,总共有行数那么多个
对于k=1时,就为features【4+1-1】,以此类推
max_steps = 64
features = torch.zeros((T - tau - max_steps + 1, tau + max_steps))
# 列i(i<tau)是来自x的观测,其时间步从(i)到(i+T-tau-max_steps+1)
for i in range(tau):
features[:, i] = x[i: i + T - tau - max_steps + 1]
# 列i(i>=tau)是来自(i-tau+1)步的预测,其时间步从(i)到(i+T-tau-max_steps+1)
for i in range(tau, tau + max_steps):
features[:, i] = net(features[:, i - tau:i]).reshape(-1)
steps = (1, 4, 16, 64)
d2l.plot([time[tau + i - 1: T - max_steps + i] for i in steps],
[features[:, (tau + i - 1)].detach().numpy() for i in steps],
'time',
'x',
legend=[f'{i}-step preds' for i in steps], xlim=[5, 1000],
figsize=(6, 3)
)