LayoutLM Code Study

Layoutlm是一个视觉文档多任务通用的预训练模型。

本文是一个本科生对多模态浅薄理解的一个过程的学习和总结

目录结构

layoutlm在微软开源工作总仓库unilm下,将其全部clone。

layoutlm作为第一版本,如今已被弃用,微调样例和主模型代码,被额外一层 deprecated 目录包裹。

├── examples  #微调示例
│   ├── classification  #分类任务
│   │   └── run_classification.py
│   └── seq_labeling    #序列标记(信息抽取)任务
│       ├── preprocess.py
│       ├── preprocess.sh
│       └── run_seq_labeling.py
├── layoutlm    #模型代码
│   ├── data    #数据集代码,包含Dataset类
│   │   ├── funsd.py
│   │   └── rvl_cdip.py
│   └── modeling    #模型主代码
│       ├── __init__.py
│       └── layoutlm.py
├── mypy.ini
├── README.md
└── setup.py

主要是有两个示例,代码里包含两个数据集和模型的主代码,init和layoutlm

Shell命令

在这种代码里,不会再以ipynb的形式一步一步的进行跑代码,实际上只需要跑.sh文件(在服务器linux环境)可以一步跑完

例如preprocess.sh

#!/bin/bash
wget https://guillaumejaume.github.io/FUNSD/dataset.zip
​
unzip dataset.zip && mv dataset data && rm -rf dataset.zip __MACOSX
​
python preprocess.py --data_dir data/training_data/annotations \
                                    --data_split train \
                                    --output_dir data \
                                    --model_name_or_path bert-base-uncased \
                                    --max_len 510
​
python preprocess.py --data_dir data/testing_data/annotations \
                                    --data_split test \
                                    --output_dir data \
                                    --model_name_or_path bert-base-uncased \
                                    --max_len 510
​
cat data/train.txt | cut -d$'\t' -f 2 | grep -v "^$"| sort | uniq > data/labels.txt

简单的解释一下——先运行python的脚本 --data_dir data/training_data/annotations 制定了输入python文件的数据目录

--data_split train :这个参数指定了要处理的数据集的划分。在这个例子中,使用的是"train",表示训练集。 --output_dir data :这个参数指定了输出目录,即处理后的数据将保存在data目录中。 --model_name_or_path bert-base-uncased :这个参数指定了模型的名称或路径。在这个例子中,使用的是bert-base-uncased,表示使用了预训练的BERT模型,该模型是一个小写版本。 --max_len 510 :这个参数指定了文本序列的最大长度。在这个例子中,文本序列的最大长度被限制为510个标记。BERT模型在输入序列的长度上有限制,通常是512个标记,但会有一些保留给特殊标记。

实际上就是把一些参数放到py文件里,给它选定 测试训练集,输出路径 model name 最大长度限制。

再解释一下cat 操作

这是一个命令行操作序列,主要是针对文件data/train.txt进行一系列文本处理。让我为你解释一下:

  1. cat data/train.txt: 读取data/train.txt文件的内容并输出到标准输出(屏幕)。

  2. cut -d$'\t' -f 2: 使用制表符(\t)作为分隔符,提取每一行的第二个字段。假设文件中的每一行都包含制表符分隔的字段,这个操作会提取第二个字段。

  3. grep -v "^$": 从之前的操作结果中过滤掉空白行。grep -v "^$"表示匹配不以开头是空白的行,即只保留非空行。

  4. sort: 对文本进行排序。

  5. uniq: 去除重复的行。

  6. > data/labels.txt: 将最终的结果保存到data/labels.txt文件中。

综合起来,这个命令的目的是从data/train.txt文件中提取第二个字段,过滤掉空白行,对结果进行排序并去除重复的行,最后将处理后的结果保存到data/labels.txt文件中。这样,data/labels.txt文件应该包含了data/train.txt文件中第二个字段的非重复值。

实际上就是一个标签的提取

image-20231210192159611

在最开始,只需要我们执行这个预加工的shell命令,就可以完成数据的加载

例如命令: chomd u+x hello.sh(添加x执行权限) ./hello.sh sh hello.sh

cd examples/seq_labeling
./preprocess.sh

执行微调脚本

python run_seq_labeling.py  --data_dir data \
                            --model_type layoutlm \
                            --model_name_or_path path/to/pretrained/model/directory \
                            --do_lower_case \
                            --max_seq_length 512 \
                            --do_train \
                            --num_train_epochs 100.0 \
                            --logging_steps 10 \
                            --save_steps -1 \
                            --output_dir path/to/output/directory \
                            --labels data/labels.txt \
                            --per_gpu_train_batch_size 16 \
                            --per_gpu_eval_batch_size 16 \
                            --fp16

image-20231210195423552

Funsd数据集内容

目录结构

data
├── testing_data  # 50个样本
│   ├── annotations
│   └── images
└── training_data # 149个样本
    ├── annotations
    └── images

data目录下,含有训练集和测试集,每个数据集拥有images和annotations两个目录

其中训练集中有149个样本,测试集中有50个样本。

Funsd数据集的标记比较仔细,以文本块为基本单位,包括文本框、文本、标签、词集合、关系,id,如下所示。

其中文本包含多个单词,词集合中又分别描述了子单词的文本和文本框位置信息。

标签表示该文本段的实体属性。关系则表示实体之间的关联关系,如问题和答案,以文本块之间的id双元组表示。

        {
            "box": [84,109,136,119],
            "text": "COMPOUND",
            "label": "question",
            "words": [
                {
                    "box": [84,109,136,119],
                    "text": "COMPOUND"
                }
            ],
            "linking": [
                [0,37]
            ],
            "id": 0
        },

以上annotation信息,表示了一个扫描视觉文档具有的文本和布局信息,需要将其转换为模型可以学习的格式。

流程概览

由于本人能力有限,不能够完全的理解每一部分代码的含义并把它讲出来,我依据心哥@丘野对代码的注释,主要是提炼出一些必要的操作。

随机采样——set_Seed 因为要随机采样,先设计一个种子。接着get_labels是对原来label.txt的数据进行加工

train函数中,要设置batch size 其大小为每一个gpu的batch*gpu个数

设置dataloader 和 step步长 设置epoch=最大步长除以每个epoch的步长

设置优化器和半精训练

然后利用model.train()进入训练模式

  • train方法,加载模型、训练参数,执行训练流程,保存权重

  • evaluation 方法,在测试集上评估模型方法

main函数只要调用上面的操作

最后就是把输出的结果存到data里就可以了

主模型

模型里面定义了一些类

  1. LayoutlmConfig: 这是一个模型配置类,继承自BertConfig,包含了一些关于模型的配置信息,例如词汇表大小、隐藏层大小等。

  2. LayoutlmEmbeddings: 这个类定义了模型的嵌入层,用于将输入转换为模型可接受的格式。该嵌入层包括词嵌入、位置嵌入、类型嵌入等。

  3. LayoutlmModel: 这是主要的Layoutlm模型类,继承自BertModel。在这里,主要修改了模型的嵌入层为LayoutlmEmbeddings

  4. LayoutlmForTokenClassification: 这个类是用于标注任务的模型,继承自BertPreTrainedModel。它包括了LayoutlmModel以及一个线性分类器用于预测每个标记的类别。在训练时,可以计算损失值并进行反向传播。

  5. LayoutlmForSequenceClassification: 这个类是用于序列分类任务的模型,继承自BertPreTrainedModel。类似于LayoutlmForTokenClassification,它包含了LayoutlmModel以及一个线性分类器用于预测整个序列的类别。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值