Legal-BERT 法律大模型微调

在当今快节奏的法律行业中,专业人士被越来越多的复杂文件淹没——从复杂的合同条款和合并协议到监管合规记录和法庭文件。手动筛选这些文件不仅耗费人力和时间,而且容易出现人为错误和不一致。这种低效率可能导致风险被忽视、不遵守法规,并最终给组织带来财务损失。

挑战:法律文本对于自然语言处理 (NLP) 来说具有独特的挑战性,因为它们具有专业词汇、复杂的语法以及上下文的重要性。在一般语言中看起来相似的术语在法律语境中可能具有截然不同的含义。因此,通用 NLP 模型在直接应用于法律文件时往往会失效。

解决方案:这就是微调专业语言模型发挥作用的地方。通过调整在法律语料库上预先训练的模型,我们可以在合同分析、合规性监控和法律文件检索等任务中实现更高的准确性和可靠性。在本文中,我们将深入研究如何使用 LEDGAR 数据集 [4](专为法律领域设计的综合基准数据集)对 Legal-BERT [5](一种针对法律文本量身定制的基于转换器的模型)进行微调以对合同条款进行分类。

你将学到什么:在本教程结束时,你将拥有一个完整的路线图,以利用 Legal-BERT 来解决法律文本分类问题。今天将提供以下方面的指南:

  • 为涉及法律文件的 NLP 任务设置环境。
  • 理解和预处理 LEDGAR 数据集以获得最佳模型性能。
  • 执行探索性数据分析以深入了解数据集的结构。
  • 对 Legal-BERT 进行微调以对法律条款进行多类分类。
  • 根据既定基准评估模型的性能。
  • 讨论法律 NLP 应用特有的挑战和注意事项。

无论你是想加深 NLP 专业知识的数据科学家,还是对特定领域模型微调感兴趣的机器学习工程师,本教程都将为你提供入门所需的工具和见解。

1、环境设置

我们将使用 Hugging Face Transformers 库,该库提供预先训练的模型和工具来对其进行微调。虽然不是绝对必要的,但使用 GPU 会大大加快训练速度。如果你使用的是 Google Colab,请转到运行时 > 更改运行时类型并选择 GPU 来启用 GPU。

首先,安装必要的库:

!pip install transformers datasets torch scikit-learn
# Import necessary dependencies
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments, AutoModelForMaskedLM
from datasets import load_dataset, DatasetDict
import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score, f1_score, classification_report
from datasets import load_dataset
from transformers import AutoTokenizer
import matplotlib.pyplot as plt
from transformers import AutoModelForSequenceClassification, DataCollatorForLanguageModeling, Trainer
from torch.utils.data import DataLoader
from sklearn.metrics import accuracy_score, f1_score, classification_report, precision_recall_curve
import seaborn as sns
import os
# Set device for GPU usage
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"Using device: {device}")

2、数据集概览

该项目选择的数据集是 LEDGAR(带标签的 EDGAR),它是 LexGLUE 法律语言任务基准的一部分 [1, 3]。LEDGAR 包含来自公开的 SEC 文件的合同条款,也称为 Exhibit 10 合同,这些条款在法律领域必不可少。该数据集包括大约 80,000 条条款,分为 100 个类别,从“协议”和“保密”到“终止”和“归属”[3]。

由于其术语多样且标签特定于上下文,LEDGAR 为 NLP 模型提供了一个具有挑战性的数据集。条款分为训练、验证和测试集,其中 60,000 条条款用于训练,10,000 条条款用于验证,10,000 条条款用于测试。在本教程中,我们将使用 Hugging Face 的数据集库下载和准备数据集。

我建议访问此链接[4]以更好地了解数据集和 LexGLUE 基准。

# Load LEDGAR dataset
dataset = load_dataset('lex_glue', 'ledgar')

# Display dataset features
print(dataset['train'].features)
# Get label information
label_list = dataset['train'].features['label'].names
num_labels = len(label_list)
print(f"Number of labels: {num_labels}")
标签计数

部分训练数据的示例如下 [4]:

{
  "text": "Executive agrees to be employed with the Company, and the Company agrees to employ Executive, during the Term and on the terms and conditions set forth in this Agreement. Executive agrees during the term of this Agreement to devote substantially all of Executive’s business time, efforts, skills and abilities to the performance of Executive’s duties ...",
  "label": "Employment" 
}

3、预处理和标记化

为了有效地微调 Legal-BERT,我们需要通过几个预处理步骤准备 LEDGAR 数据集:

  • 将标签映射到索引:在标签名称和索引之间创建映射,以确保在训练期间与 PyTorch 兼容。
  • 标记长度计算:计算每个文本示例的标记(token)长度。这有助于我们了解数据分布并确保最大序列长度(设置为 512 个标记)适合数据集。
  • 标记文本:使用 Legal-BERT 的标记器对每个条款进行标记,该标记器旨在处理法律术语。
  • 截断和填充序列:截断长度超过最大长度的文本并填充较短的文本,设置最大长度为 512 个标记。这确保了输入长度的一致性。
# Create mappings from label names to indices and vice versa
label2id = {label: idx for idx, label in enumerate(label_list)}
id2label = {idx: label for idx, label in enumerate(label_list)}
# Initialize tokenizer
tokenizer = AutoTokenizer.from_pretrained('nlpaueb/legal-bert-base-uncased')

# Token length computation function
def compute_token_lengths(example):
    tokens = tokenizer.encode(example['text'], add_special_tokens=True)
    example['num_tokens'] = len(tokens)
    return example

# Apply token length computation to the dataset
dataset = dataset.map(compute_token_lengths)

def preprocess_data(examples):
    # Tokenize the texts
    return tokenizer(
        examples['text'],
        truncation=True,            # Truncate texts longer than max_length
        padding='max_length',       # Pad texts shorter than max_length
        max_length=512              
    )

# Apply the preprocessing function to the dataset
encoded_dataset = dataset.map(preprocess_data, batched=True)

# Set the format of the dataset to PyTorch tensors
encoded_dataset.set_format(
    type='torch',
    columns=['input_ids', 'attention_mask', 'label']
)
encoded_dataset

4、探索性数据分析 (EDA)

EDA 是任何机器学习工作流程中必不可少的步骤,尤其是在处理像 LEDGAR 这样的大型复杂数据集时。通过检查数据的结构、分布和关键特征,我们可以对预处理和模型设置做出明智的决策。

4.1 标记长度分布

由于我们的模型 (Legal-BERT) 的最大输入标记长度为 512,因此了解标记长度分布对于评估数据是否符合此限制非常重要。这是一个直方图,显示了训练、验证和测试集的标记长度分布。

我们可以看到,虽然大多数规定都在 512 个标记的限制以下,但有些规定超过了此限制。截断长度超过 512 个标记的序列对于保持输入的一致性是必要的。这与 LexGLUE 基准一致,可以将结果与以前的研究 [1] 进行比较。

4.2 类别分布

LEDGAR 包含 100 个不同的类别,类别间的频率范围很广。下面是条形图,显示了训练集中频率最高的 10 个类别和最低的 10 个类别。

数据集中存在严重的类别不平衡。某些类别(例如“管辖法律”和“通知”)具有大量示例,而其他类别(例如“书籍”和“作业”)则不太常见。

虽然解决类别不平衡问题可以提高模型性能,特别是在代表性不足的类别上,但在这种情况下,我们选择保留原始分布。做出这一决定是为了确保与使用不平衡的 LEDGAR 数据集 [1] 的 LexGLUE 基准进行公平比较。然而,在生产环境中,可以使用类别加权或数据增强等技术来平衡类别,从而增强模型在所有类别中泛化的能力。

现在我们已经完成了必要的预处理和 EDA 步骤,让我们进入我们的微调方法。

5、训练和微调

在 LEDGAR 上微调 Legal-BERT 涉及为具有 100 个类别的多类分类任务配置模型。我们将宏观 F1 和微观 F1 分数优先作为我们的主要评估指标,与 LexGLUE 基准一致,该基准使用这些指标来评估模型性能 [1, 4]。让我们深入了解如何设置和训练我们的模型。

5.1 模型和训练配置

我们为 Legal-BERT 加载一个序列分类头,指定 100 个输出类。此外,我们定义标签名称和索引的映射以确保正确的标签编码。

# Load Legal-BERT with a classification head for 100 classes
model = AutoModelForSequenceClassification.from_pretrained(
    "nlpaueb/legal-bert-base-uncased",
    num_labels=num_labels,  # Number of labels (100)
    id2label=id2label,      # Mapping from IDs to labels
    label2id=label2id       # Mapping from labels to IDs
)
model.to(device)

5.2 自定义评估指标

如前所述,我们将重点关注宏 F1 和微 F1 性能指标。宏 F1 平均每个类别的 F1 分数,深入了解模型处理代表性不足的类别的能力,而微 F1 汇总所有类别的结果,提供整体性能视图。通过使用这些指标,我们确保我们的结果与 LexGLUE 基准直接可比。

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=1)

    # Calculate accuracy
    accuracy = accuracy_score(labels, predictions)

    # Calculate macro F1-score
    macro_f1 = f1_score(labels, predictions, average='macro', zero_division=0)

    # Calculate micro F1-score
    micro_f1 = f1_score(labels, predictions, average='micro', zero_division=0)

    return {
        'accuracy': accuracy,
        'macro_f1': macro_f1,
        'micro_f1': micro_f1
    }

5.3 训练参数

接下来,我们需要建立训练参数,包括批处理大小、时期数、学习率和评估策略等参数。保存的模型是基于宏 F1 分数的“最佳版本”,可确保所选模型在所有类别中具有最均衡的性能。

training_args = TrainingArguments(
    output_dir='./results',
    num_train_epochs=5,
    per_device_train_batch_size=128,
    per_device_eval_batch_size=128,
    evaluation_strategy='epoch',
    save_strategy='epoch',
    learning_rate=2e-5,
    logging_dir='./logs',
    load_best_model_at_end=True,
    metric_for_best_model='macro_f1', 
    greater_is_better=True,
    fp16=True,  # Enables mixed precision for faster training
    logging_steps=100
)

5.4 训练模型

使用 Hugging Face 的 Trainer 类,我们使用指定的参数和评估指标在 LEDGAR 上训练 Legal-BERT。此设置简化了训练过程,并在每个时期后提供自动评估。

# Initialize the Trainer with the model, arguments, and training data
trainer = Trainer(
    model=model,                             
    args=training_args,                      
    train_dataset=encoded_dataset['train'],  
    eval_dataset=encoded_dataset['validation'],  
    compute_metrics=compute_metrics         
)
# Start fine-tuning
trainer.train()

5.5 测试集上的最终评估

训练完成后,我们可以在测试集上评估模型以获得最终性能指标。这使我们能够评估模型对未知数据的泛化能力。

# Evaluate on the validation set
eval_results = trainer.evaluate()

# Extract and print macro and micro F1 scores
val_macro_f1 = eval_results.get('eval_macro_f1')
val_micro_f1 = eval_results.get('eval_micro_f1')

print("Validation Results:")
print(f"Validation Macro F1-score: {val_macro_f1:.4f}")
print(f"Validation Micro F1-score: {val_micro_f1:.4f}")

# Predict on the test set
test_results = trainer.predict(encoded_dataset['test'])

# Extract predictions and true labels
test_logits, test_labels = test_results.predictions, test_results.label_ids
test_predictions = np.argmax(test_logits, axis=1)

# Calculate test metrics
test_accuracy = accuracy_score(test_labels, test_predictions)
test_macro_f1 = f1_score(test_labels, test_predictions, average='macro', zero_division=0)
test_micro_f1 = f1_score(test_labels, test_predictions, average='micro', zero_division=0)

# Print test results
print("Test Results:")
print(f"Test Accuracy: {test_accuracy:.4f}")
print(f"Test Macro F1-score: {test_macro_f1:.4f}")
print(f"Test Micro F1-score: {test_micro_f1:.4f}")

通过关注宏观和微观 F1 分数,我们可以平衡地了解模型在所有类别中的表现,这在 LEDGAR 等不平衡数据集中至关重要。这种评估方法与 LexGLUE 基准 [1, 4] 一致,可以将我们的结果与法律文本分类的行业标准模型进行比较。以下是与我们的模型相比报告的基准结果。

虽然我们的模型的性能与基准结果非常接近,但由于几个因素,可能会出现细微的差异。训练配置的变化(例如超参数、批次大小、时期数或学习率)会影响结果。数据预处理的差异(例如处理稀有类别或序列截断方法)也可能导致差异。最后,训练的随机性意味着不同的随机种子会导致结果的变化,从而解释了观察到的微小性能差距。

6、结论和关键要点

在本教程中,我们探索了在 LEDGAR 数据集上对 Legal-BERT 进行微调以对法律合同条款进行分类。通过利用领域特定模型,我们能够在处理法律文件的细微语言方面取得出色的表现,展示了微调在专业 NLP 任务中的强大功能。

关键要点:

  • 预先训练的法律模型非常有价值:Legal-BERT 等法律特定模型对于准确管理法律文本中复杂、专业的词汇和领域特定细微差别至关重要。
  • 微调以实现专业化:通过微调将 BERT 模型适应特定任务可提高其分类性能和稳健性,尤其是在处理 LEDGAR 等数据集中的不平衡类别和不同类别时。
  • 与基准保持一致:与既定基准(例如 LexGLUE)保持一致,可以进行客观比较并深入了解你的模型与行业标准的比较情况。

原文链接:Fine-Tuning Legal-BERT: LLMs For Automated Legal Text Classification

汇智网翻译整理,转载请标明出处