首页 文章

在keras中的一组文档上应用共享嵌入层

提问于
浏览
2

我正在尝试创建一个模型,在该模型中,我希望在给定特定查询的情况下预测某组文档的顺序 . 我的想法基本上是为查询和文档使用共享嵌入层,然后使用每个文档和查询之间的余弦相似性合并两个“分支”(使用自定义lambda) . 然后,损失函数将计算预期位置和预测相似度之间的差异 .

我的问题是:有没有办法为一组文本功能创建嵌入(假设它们具有相同的长度)?

我可以通过应用Embedding Convolution1D GlobalMaxPooling1D在“类似doc2vec的嵌入”中正确转换我的查询,但我没有运气在文档集上使用相同的策略(并且重塑2D卷积对我来说没有意义,因为我我正在使用文本数据) .

请注意,我有一个约束,我需要为我的查询和文档集使用相同的嵌入层(我使用Keras的功能apis这样做) .

[编辑,添加示例代码]

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)

[SOLUTION] 感谢Nassim Ben,像这样使用 TimeDistributed 将图层反复应用于图层的所有尺寸,如下所示:

right = TimeDistributed(emb)(T)
right = TimeDistributed(Convolution1D(nb_filter=5,
                        filter_length=5,
                        border_mode='valid',
                        activation='relu',
                        subsample_length=1)(right)
right = TimeDistributed(GlobalMaxPooling1D())(right)

1 回答

  • 1

    好的 . 如果我正确理解了这种情况,那么您需要嵌入50个长度为50的文本片段 .

    在执行单词嵌入之后,您会发现自己的Tensor T形状(50,50,emb_size) . 我想做的是在TimeDistributed包装器中使用LSTM层 . 在 emb(T) 之后添加这些行:

    right = TimeDistributed(LSTM(5))(right)
    

    这将对50个文档中的每个文档应用相同的LSTM,并在每个文档处理结束时输出长度为5的最终状态 . 此步骤后的形状为(50,5) . 您已将每个文档嵌入长度为5的向量中 . TimeDistributed的优点是应用于每个文档的LSTM将共享相同的权重,因此您的文档将以相同的方式'treated' . 您可以找到有关LSTM here和TimeDistributed here的文档 .

    我希望这能有所帮助 .

相关问题