利用CNTK在每个生成步骤采样生成序列

2024-05-16 20:54:42 发布

您现在位置:Python中文网/ 问答频道 /正文

在带有编码器和解码器的seq2seq模型中,在每一生成步骤中,softmax层输出整个词汇表的分布。在CNTK中,贪婪解码器可以很容易地利用C.hardmax函数实现。看起来像这样。

def create_model_greedy(s2smodel):
    # model used in (greedy) decoding (history is decoder's own output)
    @C.Function
    @C.layers.Signature(InputSequence[C.layers.Tensor[input_vocab_dim]])
    def model_greedy(input): # (input*) --> (word_sequence*)
        # Decoding is an unfold() operation starting from sentence_start.
        # We must transform s2smodel (history*, input* -> word_logp*) into a generator (history* -> output*)
        # which holds 'input' in its closure.
        unfold = C.layers.UnfoldFrom(lambda history: s2smodel(history, input) >> **C.hardmax**,
                                     # stop once sentence_end_index was max-scoring output
                                     until_predicate=lambda w: w[...,sentence_end_index],
                                     length_increase=length_increase)
        return unfold(initial_state=sentence_start, dynamic_axes_like=input)
    return model_greedy

但是,在每个步骤中,我都不希望以最大概率输出令牌。相反,我想有一个随机解码器,它根据词汇的概率分布生成令牌。

我怎么能做到?如有任何帮助,不胜感激。谢谢。


Tags: ininputoutputmodelislayersdef步骤
2条回答

非常感谢Nikos Karampatziakis。在

如果您希望有一个随机采样解码器,它生成与目标序列长度相同的序列,那么下面的代码可以工作。在

@C.Function
def sampling(x):
    noisy_x = x + C.random.gumbel_like(x)
    return C.hardmax(noisy_x)

def create_model_sampling(s2smodel):
    @C.Function
    @C.layers.Signature(input=InputSequence[C.layers.Tensor[input_vocab_dim]],
                        labels=LabelSequence[C.layers.Tensor[label_vocab_dim]])
    def model_sampling(input, labels): # (input*)  > (word_sequence*)
        unfold = C.layers.UnfoldFrom(lambda history: s2smodel(history, input) >> sampling,
                                     length_increase=1)
        return unfold(initial_state=sentence_start, dynamic_axes_like=labels)
    return model_sampling

你可以在使用hardmax之前给输出加上噪声。特别是,可以使用C.random.gumbelC.random.gumbel_like按比例采样{}。这被称为gumbel-max trickcntk.random模块也包含其他分布,但是如果您有对数概率,您很可能希望在hardmax之前添加gumbel noise。一些代码:

@C.Function
def randomized_hardmax(x):
    noisy_x = x + C.random.gumbel_like(x)
    return C.hardmax(noisy_x)

然后将您的hardmax替换为randomized_hardmax。在

相关问题 更多 >