0. Encoder.onnx 和decoder.onnx
Seq2seq结构也称为encoder-decoder结构,在decoder结构为单步解码时,seq2seq的导出的与只有encoder时(如BERT等)没有差别。当decoder为多步解码时,如生成式任务中的机器翻译、文本摘要等,由于decoder需要多次用到,问题变得稍稍复杂了一点。
由于onnx对多步解码的支持较差,我们选择将模型拆分成encoder和decoder两部分。(官网上有torch.jit.script(model),但对transformers之外的框架不一定适用,所以我们讨论更一般的情况。)
在常见的基于transformer机制的框架中,一般都是先定义各层中的计算机制,如linear,activation (relu, gelu), scaled_multi_head_attention等,再定义各层(layer, T5中的block)的计算,然后再定义encoder, decoder,最后定义整个transformer及对应的train和inferece各状态对应的输入输出。
在定义encoder和decoder的时候,分别加入了src和tgt embedding来进行初始化,有时使用shared embedding, 即src embedding和tgt embedding相同。Encoder和decoder的最大不同在于,encoder中只涉及self-attention的计算,decoder先进行self-attention的计算,再进行cross_attention的计算。