我试图创建一个模型,在这个模型中,我想预测给定查询的某一组文档的顺序。我的想法基本上是对查询和文档使用一个共享的嵌入层,然后使用每个文档和查询之间的余弦相似性合并两个“分支”(使用自定义lambda)。然后,损失函数将计算预期位置和预测相似性之间的差异。在
我的问题是:有没有一种方法可以为一组文本特征创建嵌入(只要它们具有相同的长度)?在
我可以通过应用embedding+complication1d+GlobalMaxPooling1D在“类似doc2vec的嵌入”中正确地转换我的查询,但是我没有在文档集上使用相同的策略(而且由于我使用的是文本数据,所以重塑+2D卷积对我来说没有真正意义)。在
注意,我的一个限制是,我需要对我的查询和文档集使用相同的嵌入层(我使用Keras的函数api来实现这一点)。在
[编辑,添加示例代码]
Q = Input(shape=(5, )) # each query is made of 5 words
T = Input(shape=(50, 50)) # each search result is made of 50 words and 50 docs
emb = Embedding(
max_val,
embedding_dims,
dropout=embedding_dropout
)
left = emb(Q)
left = Convolution1D(nb_filter=5,
filter_length=5,
border_mode='valid',
activation='relu',
subsample_length=1)(left)
left = GlobalMaxPooling1D()(left)
print(left)
right = emb(T) # <-- this is my problem, I don't really know what to do/apply here
def merger(vests):
x, y = vests
x = K.l2_normalize(x, axis=0) # Normalize rows
y = K.l2_normalize(y, axis=-1) # Normalize the vector
return tf.matmul(x, y) # obviously throws an error because of mismatching matrix ranks
def cos_dist_output_shape(shapes):
shape1, shape2 = shapes
return (50, 1)
merger_f = Lambda(merger)
predictions = merge([left, right], output_shape=cos_dist_output_shape, mode=merger_f)
model = Model(input=[Q, T], output=predictions)
def custom_objective(y_true, y_pred):
ordered_output = tf.cast(tf.nn.top_k(y_pred)[1], tf.float32) # returns the indices of the top values
return K.mean(K.square(ordered_output - y_true), axis=-1)
model.compile(optimizer='adam', loss=custom_objective)
[解决方案]感谢Nassim Ben,使用TimeDistributed
将一个层循环应用到如下层的所有维度:
好吧。如果我理解正确的情况,你有50个长度为50的文本片段,你想嵌入。
完成单词嵌入后,你会发现自己有一个形状的张量T(50,50,emb_size)。 我要做的是在时间分布的包装器中使用LSTM层。在
emb(T)
之后添加这些行:这将对50个文档中的每个文档应用相同的LSTM,并在每个文档处理结束时输出长度为5的最终状态。这一步后右边的形状是(50,5)。您已经将每个文档嵌入到一个长度为5的向量中。 TimeDistributed的优点是,应用于每个文档的LSTM将共享相同的权重,因此您的文档将以相同的方式“处理”。您可以找到关于LSTM here和关于时间分布here的文档。
我希望这能有所帮助。
相关问题 更多 >
编程相关推荐