我有两个(20,4)的输入张量(query和target),我将它们连接,相加,展平,然后应用一个简单的密集层。在这个阶段,我有100,000个查询目标对的数据用于训练。
def sum_seqs(seqs):
return K.sum(seqs, axis=3)
def pad_dims(seq):
return K.expand_dims(seq, axis=3)
def pad_outshape(in_shape):
return (in_shape[0], in_shape[1], in_shape[2], 1)
query = Input((20, 4))
query_pad = Lambda(pad_dims, output_shape=pad_outshape, name='gpad')(query)
target = Input((20,4))
target_pad = Lambda(pad_dims, output_shape=pad_outshape)(target)
matching = Concatenate(axis = 3)([query_pad, target_pad])
matching = Lambda(sum_seqs)(matching)
matching = Flatten()(matching)
matching = Dropout(0.1)(matching)
matching = Dense(1, activation = 'sigmoid')(matching)
match_model = Model([query, target], matching)
这个功能完美无误。现在我想使用这个预训练模型来搜索一个更长的目标
序列和不同的查询
序列。
看起来应该是这样:
long_target = Input((100, 4))
short_target = Input((20, 4))
choose_query = Input((20, 4))
spec_match = match_model([choose_query, short_target])
mdl = TimeDistributed(spec_match)(long_target)
但是 TimeDistributed
需要一个 Layer
而不是一个 Tensor
。我是否缺少包装器?我这样做的方式是否有误?我需要以某种方式重新构造为卷积问题吗?
继续尝试:
经过一天的思考,很明显TimeDistributed
和backend.rnn
都只允许您将模型/层应用于单个时间切片的数据。似乎没有办法做到这一点。看起来唯一可以“跨越”时间维度的多个片段的是Conv1D
。
所以,我把我的问题重新构想成了一个卷积问题,但效果也不好。我能构建一个Conv1D
滤波器,使其匹配特定的query
。这运行得相当不错,它确实允许我扫描更长的序列并获得匹配。但是,每个过滤器都是唯一的,对于每个query
张量都需要独立训练一个新的Conv1D
层以获得相应的过滤器权重。由于我的目标是查找与大多数目标匹配的新query
,这没有什么帮助。
由于我的“匹配”需要目标和查询在每个窗口的交互,因此似乎我无法通过Conv1D
在100长度的target
张量上的每个窗口上获取20长度query
张量的交互。
是否有任何方法在Keras / tensorflow中进行这种滑动窗口类型的评估?它看起来很简单,但是距离很远。是否有我找不到的方法可以做到这一点?
响应和进一步尝试。
@today和@nuric的解决方案有效,但它们最终会以平铺方式复制输入 target
数据。因此,对于长度为m
的查询,在图中将有略少于m
个副本的输入数据。我希望找到一种实际上可以在target
上“滑动”评估而不重复的解决方案。
下面是我想出的Conv1D
几乎解决方案的版本。
query_weights = []
for query, (targets, scores) in query_target_gen():
single_query_model = Sequential()
single_query_model.add(Conv1D(1, 20, input_shape = (20, 4)))
single_query_model.add(Flatten())
single_query_model.fit(targets, scores)
query_weights.append(single_query_model.layers[0].get_weights())
multi_query_model_long_targets = Sequential()
multi_query_model_long_targets.add(Conv1D(len(query_weights), 20, input_shape = (100, 4)))
multi_query_model_long_targets.layers[0].set_weights(combine_weights(query_weights))
multi_query_model_long_targets.summary()
combine_weights
函数只是对过滤器进行了一些解包和矩阵重新排列,以按照Conv1D
的要求堆叠过滤器。
这个解决方案解决了数据复制的问题,但它在其他方面给我带来了麻烦。其中一个问题是基于数据的......我的数据包含许多query
,target
对,但往往是相同的target
与许多query
配对,因为按照这种方式生成真实世界的数据更容易。因此,这样做使训练变得困难。其次,这假定每个query
都是独立工作的,而实际上,我知道query
,target
匹配才是真正重要的。因此,使用可以查看多个示例对的模型而不是个体对有意义。
有没有办法将两种方法结合起来?有没有办法使Conv1D
同时获取长的target
张量并将其与恒定的query
组合在一起,当它沿着序列移动时?
target[0:20]
、target[1:21]
、target[2,22]
,...,target[-20:]
是否与长度为20的query
匹配,并使用您训练好的模型?也许每个目标的长度可能是k
,其中k
不一定是100? - todaytarget[0:20, :]
,target[1:21, :]
,...因为匹配需要在评估中使用所有4个通道。我通常假设每个批次的k
都是相同的。最终,我将为每个目标取最大匹配分数到下一层。因此,不同的目标长度不会影响下游层。 - JudoWilltf.extract_image_patches()
吗?这基本上就是你要找的东西。如果你无法使用它,请告诉我。 - todaytf.extract_image_patches()
需要一个4D张量[batch, in_rows, in_cols, depth]
,而我的是2D的。而且不清楚张量是如何输出的(我AFK,所以无法测试)。如果您能写一个带有一些基本代码的答案,我今晚很乐意测试并授予奖励。 - JudoWillConv1D
层时提到的问题?您能否也把您卷积模型的代码贴出来吗? - today