Iterative Updates
这段话给iterative updates以定性,输入一个初始化的流场,逐步地更新这个流场。
具体来讲:输入->流场、相关性金字塔和隐藏状态
输出->更新的 Δ f \Delta f Δf
具体步骤
1.初始化
顾名思义,将第一次输入的流场初始化为 f 0 = 0 f_{0} = 0 f0=0
2.inputs
def forward(self, net, inp,corr, flow, upsample=True):
motion_features = self.encoder(flow, corr) #首先通过flow 和 相关 估计一个motion的特征torch.Size([8, 128, 40, 40])
inp = torch.cat([inp, motion_features], dim=1)
#net也属于上下文信息 是gru的隐藏状态
net = self.gru(net, inp)
delta_flow = self.flow_head(net) #输出二通道光流
# scale mask to balence gradients
# mask = .25 * self.mask(net) #用来做特殊的插值
return net, delta_flow
这一部分我认为看代码理解会更加清晰,最开始输入的很明显只有 f 0 f_{0} f0和 c o r r e l a t i o n p y r a m i d correlation pyramid correlationpyramid,输出一个隐藏状态 n e t net net和更新的 Δ f \Delta f Δf
GRU
那么具体的GRU在做什么事情呢?
首先, i n p inp inp实际上就是上下文信息,我们知道上下文信息储存了特征信息,将特征信息 i n p inp inp和运动信息 m o t i o n f e a t u r e s motion features motionfeatures concat到一起就得到了一个新的信息。(我认为这一部分其实非常玄学,很难去解释,如果有小伙伴有更好的理解欢迎交流)
然后,这样一个新的信息 i n p inp inp和原始的上下文特征 n e t net net输入到GRU中输出一个新的 n e t net net,如果要定性理解GRU,我认为也没什么东西,就是一个比较特殊的卷积层(有"记忆"的)。
最后, n e t net net输入到flow的预测头中,输出 Δ f \Delta f Δf。在这一部分,我相信小伙伴都非常好奇,输出是2通道的一个图,为什么它是 Δ f \Delta f Δf而不是 f f f。我的理解是,这跟最后loss的反馈直接相关!如果我定义最终输出的是一个 f f f(这是我可以定义的,因为我要与 f f f的ground truth无限接近),那么我过程中的 f f f是通过 f k f_{k} fk + 一个预测头的输出而来的,这直接限制了预测头的输出不可以是 f f f。(这一部分如果有小伙伴有更好的理解欢迎交流)
4.光流预测
f k + 1 = f k + Δ f f_{k+1} = f{k} + \Delta f fk+1=fk+Δf