【发布时间】:2018-12-01 11:16:24
【问题描述】:
我正在尝试跨序列扩展匹配匹配算法。我的比赛有 20 个单位长,每个时间点有 4 个频道。我已经建立了一个封装匹配的模型,我只是不知道如何在滑动窗口中使用它来将它应用到更长的序列中以找到序列中的匹配。
我有 2 个 (20, 4) 输入张量(query 和 target),我将它们连接、添加、展平,然后应用一个简单的密集层。在这个阶段我有数据可以用 100K 查询、目标对进行训练。
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)
这非常有效。现在我想使用这个预训练模型来搜索更长的target 序列和不同的query 序列。
看起来应该是这样的:
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 张量都是唯一的,并且似乎没有办法从新颖的 query 到适当的过滤器权重而不训练全新的 Conv1D 层。由于我的目标是找到与大多数目标匹配的新 querys,这并没有多大帮助。
由于我的“匹配”需要目标和每个窗口中的查询的交互,因此似乎没有一种方法可以在每个窗口中获得 20 长度 query 张量的交互,跨越 100-长度target张量到Conv1D。
有没有办法在 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 许多 querys,因为在该方向上生成真实世界的数据更容易。因此,这样做会使培训变得困难。其次,这假设每个query 都以独立的方式工作,而实际上,我知道query、target 配对才是真正重要的。因此,使用一个可以查看许多配对示例而不是个人示例的模型是有意义的。
有没有办法将这两种方法结合起来?有没有办法让 Conv1D 在沿着序列前进时将长 target 张量与常量 query 结合起来?
【问题讨论】:
-
为了确保我理解你的问题:假设你有一个长度为 100 的目标,你想找出每个
target[0:20]、target[1:21]、target[2,22]、...、@ 987654365@ 与长度为 20 的query匹配,使用您训练的模型?也许每个目标的长度可能是k,其中k不一定是100? -
@今天。这是正确的......虽然它会是
target[0:20, :],target[1:21, :],......因为匹配需要评估中的所有4个通道。我通常假设每个批次的k都是相同的。最终,我会将每个目标的最大匹配分数带入下一层。所以不同的目标长度不会影响下游层。 -
您是否尝试过使用
tf.extract_image_patches()?它基本上就是你要找的东西。如果您不能使用它,请告诉我。 -
@today 也许虽然看起来需要一些技巧。
tf.extract_image_patches()需要一个 4D 张量[batch, in_rows, in_cols, depth]我的是 2D。并且不清楚张量是如何产生的(我是 AFK,所以无法测试)。如果您可以使用一些基本代码将其编写为答案,我很乐意今晚对其进行测试并奖励赏金。 -
好的。我会写一个答案。还有一个问题:如果目标从形状
(batch_size, 100, 4)转换为(batch_size, 81, 20, 4)是否可以,其中 81 正是滑动窗口(即补丁)的数量?你能处理它还是你想要的形状是(batch_size*81, 20, 4)?
标签: python tensorflow keras conv-neural-network sliding-window