unilm LayoutLMv2/XLM缺少文档分类的实现

ffscu2ro  于 4个月前  发布在  其他
关注(0)|答案(3)|浏览(76)

通过查看recently posted codebase,我注意到modeling_layoutlmv2.py没有包含文档或序列分类的实现。原始的LayoutLMv2论文描述了:

Fine-tuning LayoutLMv2 for Document Image Classification This task depends on high-level
visual information, thereby we leverage the image features explicitly in the fine-tuning. We pool the
visual embeddings into a global pre-encoder feature, and pool the visual part of LayoutLMv2 output
representations into a global post-encoder feature. The pre and post-encoder features along with the
[CLS] output feature are concatenated and fed into the final classification layer

是否有关于微调LayoutLMv2或LayoutXLM进行文档分类的例子?如果没有,您是否计划在未来添加此类示例?
如果您不打算添加这样的示例,您能为那些希望添加此功能的人提供一些见解吗?实现是否会遵循在已弃用的LayoutLM遗留代码中呈现的模式?

x759pob2

x759pob21#

是的,您可以按照LayoutLMv1的实现方法来微调[CLS]输出。

ilmyapht

ilmyapht2#

是的,你可以按照LayoutLMv1的实现来微调[CLS]输出。
感谢@wolfshow的回复。我正在尝试使用现有的LayoutLMv2Model的池化输出([CLS])构建一个基本版本,现在我正试图添加论文中描述的全局前置和后置编码器视觉特征(在原始帖子中引用)。我不知道如何处理描述的池化。
我修改了现有的LayoutLMv2Model的前向实现,使其返回视觉嵌入如下:

class LayoutLMv2Model(LayoutLMv2PreTrainedModel):
      ...
      def forward(..):
         ....
         return BaseModelOutputWithPoolingAndCrossAttentions(...), visual_emb

然后我的派生模型试图利用这些嵌入:

# Need help with implementing this pooler
class VisualPooler(nn.Module):
    def __init__(self):
        super().__init__()
        self.dense = nn.Linear(49, 1)
        self.activation = nn.Tanh()

    def forward(self, input):
        pooled_output = self.dense(input.permute(0, 2, 1)).permute(0, 2, 1)
        pooled_output = torch.squeeze(pooled_output, 1)
        pooled_output = self.activation(pooled_output)
        return pooled_output

class LayoutLMv2ForSequenceClassification(LayoutLMv2PreTrainedModel):
    def __init__(self, config):
        super().__init__(config)
        self.num_labels = config.num_labels
        self.layoutlmv2 = LayoutLMv2Model(config)
        self.pre_encoder_visual_emb_pooler = VisualPooler()
        self.visual_output_pooler = VisualPooler()
        self.dropout = nn.Dropout(config.hidden_dropout_prob)
        self.classifier = nn.Linear(3 * config.hidden_size, config.num_labels)
        self.init_weights()
  ...
  def forward(...):
     ...
     outputs, visual_emb = self.layoutlmv2(...)
     # pool the visual embeddings into a global pre-encoder feature
     pre_encoder_visual_feature = self.pre_encoder_visual_emb_pooler(visual_emb)
     # pool the visual part of LayoutLMv2 output representations into a global post-encoder feature
     visual_output_representation = outputs.last_hidden_state[:, -49:]
     post_encoder_visual_output_feature = self.visual_output_pooler(visual_output_representation)
     # Concatenate the pre and post-encoder features along with the [CLS] output feature
     cls_output_feature = outputs.pooler_output
     combined_pooled_features =  torch.cat([pre_encoder_visual_feature,cls_output_feature,post_encoder_visual_output_feature,],dim=1,)
     # Classify
     classifier_input = self.dropout(combined_pooled_features)
     logits = self.classifier(classifier_input)
     ....

[CLS]的输出特征具有维度(batch_size, 768),而视觉嵌入和输出具有维度(batch_size, 49, 768)。我不知道如何对这些视觉特征进行池化。

  • 2D空间池化似乎不合适,因为输出并不直接表示图像数据
  • 天真地将2D特征展平会得到一个长度为49x768 =37,632的向量。我认为在连接输出中的[CLS]特征两侧都有这样一个大的向量,会淹没[CLS]特征。
  • 我缺乏关于如何减少2D特征的维数的直觉

你能提供方向并可能提供一些关于如何更好地实现上面提到的VisualPooler的建议吗?

iq0todco

iq0todco3#

你好,@dcyoung,
感谢你发布这个问题,我也想使用LayoutLMv2进行文档分类。
你能分享一下你的代码片段吗?
谢谢,
Dhananjay

相关问题