Dear恩予 2025-09-12 14:54 采纳率: 0%
浏览 7

在autodl服务器上完成数据集的微调

求解决问题:请使用Bert语言模型,在cmrc2018阅读理解数据集上进行微调,使模型能够完成简单的抽取式阅读理解任务,即问答任务。
说明:
1、需要在autodl服务器上配置运行,推荐显卡配置3090
2、使用精准匹配度EM和模糊匹配度F1作为评估指标,并进行展示(F1需大于80%)

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-09-12 14:55
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    在AutoDL服务器上使用 BERT 模型对 CMRC2018 数据集进行微调,以完成抽取式阅读理解任务(问答任务),是一个典型的NLP任务。以下是详细的步骤说明和代码示例。


    📌 一、环境准备

    1. 登录 AutoDL 服务器

    • 访问 AutoDL 官网,创建一个实例。
    • 推荐配置:选择 3090 显卡 的实例(如 A100RTX 3090),内存建议 24G+

    2. 安装必要的依赖库

    在终端中执行以下命令:

    # 安装 PyTorch(根据显卡型号选择版本)
    pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu118
    
    # 安装 transformers 库
    pip install transformers
    
    # 安装 datasets 和 evaluate 用于评估
    pip install datasets evaluate
    
    # 安装 sentencepiece(用于 BERT tokenizer)
    pip install sentencepiece
    

    🧠 二、数据准备(CMRC2018)

    1. 下载 CMRC2018 数据集

    你可以从 CMRC2018 官方地址 获取数据,或通过 Hugging Face 加载:

    from datasets import load_dataset
    
    dataset = load_dataset("cmrc2018")
    train_dataset = dataset["train"]
    validation_dataset = dataset["validation"]
    test_dataset = dataset["test"]
    

    注意:如果无法直接加载,可以手动下载并上传到 AutoDL 服务器,然后用 load_from_disk() 加载。


    🤖 三、模型加载与预处理

    1. 加载 BERT 模型和 Tokenizer

    from transformers import BertTokenizer, BertForQuestionAnswering
    
    model_name = "bert-base-chinese"
    tokenizer = BertTokenizer.from_pretrained(model_name)
    model = BertForQuestionAnswering.from_pretrained(model_name)
    

    2. 数据预处理函数

    def preprocess_function(examples):
        questions = [q.strip() for q in examples["question"]]
        contexts = [c.strip() for c in examples["context"]]
        answers = examples["answer"]
        
        # 将答案转换为起始和结束位置
        tokenized = tokenizer(
            questions,
            contexts,
            truncation="only_second",
            padding="max_length",
            max_length=512,
            return_offsets_mapping=True,
            return_tensors="pt"
        )
        
        # 找到答案的起始和结束索引
        start_positions = []
        end_positions = []
        
        for i in range(len(answers)):
            answer = answers[i]
            if not answer:
                start_positions.append(0)
                end_positions.append(0)
                continue
            
            # 将答案文本转为token的位置
            answer_start = answer["answer_start"]
            answer_text = answer["text"]
            
            # 获取 offset mapping
            offset_mapping = tokenized.offset_mapping[i]
            
            # 找到答案对应的token起始和结束位置
            start_idx = None
            end_idx = None
            
            for j, (start, end) in enumerate(offset_mapping):
                if start == answer_start:
                    start_idx = j
                if end == answer_start + len(answer_text):
                    end_idx = j
            
            if start_idx is None or end_idx is None:
                start_positions.append(0)
                end_positions.append(0)
            else:
                start_positions.append(start_idx)
                end_positions.append(end_idx)
        
        tokenized["start_positions"] = start_positions
        tokenized["end_positions"] = end_positions
        
        return tokenized
    

    3. 应用预处理

    tokenized_datasets = train_dataset.map(preprocess_function, batched=True)
    val_tokenized = validation_dataset.map(preprocess_function, batched=True)
    

    🛠 四、训练模型

    1. 设置 Trainer 参数

    from transformers import TrainingArguments, Trainer
    
    training_args = TrainingArguments(
        output_dir="./results",
        evaluation_strategy="epoch",
        learning_rate=2e-5,
        per_device_train_batch_size=16,
        num_train_epochs=3,
        weight_decay=0.01,
        save_strategy="epoch",
        load_best_model_at_end=True,
    )
    
    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=tokenized_datasets,
        eval_dataset=val_tokenized,
    )
    

    2. 开始训练

    trainer.train()
    

    🔍 五、模型评估(EM & F1)

    1. 使用 evaluate 库计算指标

    from evaluate import load
    
    em = load("exact_match")
    f1 = load("f1")
    
    def compute_metrics(p):
        predictions, labels = p
        # 取出预测的 start 和 end 位置
        start_logits, end_logits = predictions
        # 转换为预测的答案
        predicted_answers = []
        for i in range(len(start_logits)):
            start_idx = start_logits[i].argmax()
            end_idx = end_logits[i].argmax()
            predicted_answers.append(tokenizer.decode(tokenized_datasets[i]["input_ids"][start_idx:end_idx+1]))
        
        # 原始答案
        original_answers = [example["answer"]["text"] for example in validation_dataset]
        
        em_score = em.compute(predictions=predicted_answers, references=original_answers)
        f1_score = f1.compute(predictions=predicted_answers, references=original_answers)
        
        return {
            "exact_match": em_score["exact_match"],
            "f1": f1_score["f1"]
        }
    
    # 在验证集上评估
    metrics = trainer.evaluate()
    print(f"EM: {metrics['exact_match']}, F1: {metrics['f1']}")
    

    ✅ 六、结果要求

    • F1 分数需大于 80%
    • EM 分数越高越好

    🧪 七、优化建议(可选)

    | 优化项 | 说明 | |--------|------| | 学习率调整 | 可尝试 1e-55e-5 | | 批量大小 | 若显存不足,可降低 per_device_train_batch_size | | 模型结构 | 可尝试 bert-large-chinese 提升性能 | | 早停机制 | 在 TrainingArguments 中添加 early_stopping_patience |


    📦 八、完整代码(简化版)

    from transformers import BertTokenizer, BertForQuestionAnswering, TrainingArguments, Trainer
    from datasets import load_dataset
    from evaluate import load
    
    # 1. 加载数据
    dataset = load_dataset("cmrc2018")
    train_dataset = dataset["train"]
    val_dataset = dataset["validation"]
    
    # 2. 加载模型和 tokenizer
    tokenizer = BertTokenizer.from_pretrained("bert-base-chinese")
    model = BertForQuestionAnswering.from_pretrained("bert-base-chinese")
    
    # 3. 预处理函数
    def preprocess_function(examples):
        # ... (同上文)
    
    # 4. 应用预处理
    tokenized_datasets = train_dataset.map(preprocess_function, batched=True)
    val_tokenized = val_dataset.map(preprocess_function, batched=True)
    
    # 5. 训练器设置
    training_args = TrainingArguments(...)
    trainer = Trainer(...)
    
    # 6. 训练
    trainer.train()
    
    # 7. 评估
    def compute_metrics(p):
        # ... (同上文)
    
    metrics = trainer.evaluate()
    print(f"EM: {metrics['exact_match']}, F1: {metrics['f1']}")
    

    📌 总结

    ✅ 完成目标的关键点如下:

    1. 正确加载 CMRC2018 数据集
    2. 使用 BERT 模型进行微调
    3. 实现抽取式 QA 的预处理逻辑
    4. 使用 EM 和 F1 作为评估指标
    5. 确保 F1 > 80%

    如果你需要我帮你生成完整的 Python 脚本文件或提供进一步的调试帮助,请告诉我!

    评论

报告相同问题?

问题事件

  • 创建了问题 9月12日