NeMo
Megatron-LM / tasks /integrated_eval_example.py
KexuanShi's picture
Upload folder using huggingface_hub
88e6849 verified
Raw
History Blame Contribute Delete
9.57 kB
#!/usr/bin/env python3
# Copyright (c) 2025 NVIDIA CORPORATION. All rights reserved.
"""
集成示例:同时使用 eval_utils.py 和 lm-eval-harness 进行评测
这个示例展示了如何:
1. 使用 eval_utils.py 评测自定义数据集
2. 使用 lm-eval-harness 评测标准任务
3. 在训练过程中同时运行两种评测
"""
import os
import sys
import torch
# 添加 Megatron 路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from megatron.training import get_args, print_rank_last
from megatron.core.enums import ModelType
from tasks.eval_utils import accuracy_func_provider
from tasks.lm_eval_adapter import (
create_megatron_adapter_from_checkpoint,
use_megatron_with_lm_eval_harness
)
from tasks.finetune_utils import finetune
def create_integrated_eval_callback(
single_dataset_provider,
model_provider_func,
tokenizer,
lm_eval_tasks=None,
lm_eval_checkpoint_path=None
):
"""
创建集成的评测回调函数
这个函数结合了:
- eval_utils.py 的 accuracy_func_provider(用于自定义数据集)
- lm-eval-harness(用于标准评测任务)
Args:
single_dataset_provider: 数据集提供函数(用于 eval_utils.py)
model_provider_func: 模型提供函数
tokenizer: tokenizer 对象
lm_eval_tasks: lm-eval-harness 要评测的任务列表
lm_eval_checkpoint_path: 用于 lm-eval 的检查点路径(如果与训练检查点不同)
Returns:
评测回调函数
"""
# 创建原生 Megatron 评测函数
native_metrics_func = accuracy_func_provider(single_dataset_provider)
def integrated_metrics_func(model, epoch, output_predictions=False):
"""
集成的评测函数
这个函数会:
1. 运行原生 Megatron 评测(使用 eval_utils.py)
2. 如果指定了 lm-eval 任务,也运行它们
"""
print_rank_last("=" * 80)
print_rank_last(f"开始评测 Epoch {epoch}")
print_rank_last("=" * 80)
# 1. 运行原生 Megatron 评测
print_rank_last("\n[1/2] 运行 Megatron 原生评测 (eval_utils.py)...")
native_metrics_func(model, epoch, output_predictions)
# 2. 运行 lm-eval-harness 评测(如果指定了任务)
if lm_eval_tasks:
print_rank_last(f"\n[2/2] 运行 lm-eval-harness 评测 (任务: {lm_eval_tasks})...")
try:
from lm_eval import simple_evaluate
# 确定检查点路径
args = get_args()
checkpoint_path = lm_eval_checkpoint_path or args.load
if checkpoint_path is None:
print_rank_last("警告: 未指定检查点路径,跳过 lm-eval 评测")
return
# 创建适配器
print_rank_last(f"加载检查点: {checkpoint_path}")
adapter = create_megatron_adapter_from_checkpoint(
checkpoint_path=checkpoint_path,
model_provider_func=model_provider_func,
tokenizer=tokenizer,
model_type=ModelType.encoder_or_decoder
)
# 运行评测
print_rank_last("开始 lm-eval-harness 评测...")
results = simple_evaluate(
model=adapter,
tasks=lm_eval_tasks,
batch_size=getattr(args, 'eval_batch_size', 8),
device='cuda' if torch.cuda.is_available() else 'cpu'
)
# 打印结果
print_rank_last("\n=== lm-eval-harness 评测结果 ===")
if 'results' in results:
for task_name, task_results in results['results'].items():
print_rank_last(f"\n任务: {task_name}")
if isinstance(task_results, dict):
for metric, value in task_results.items():
if isinstance(value, (int, float)):
print_rank_last(f" {metric}: {value:.4f}")
else:
print_rank_last(f" {metric}: {value}")
else:
print_rank_last(f" 结果: {task_results}")
print_rank_last("=" * 80)
except ImportError:
print_rank_last("警告: lm-eval-harness 未安装,跳过 lm-eval 评测")
print_rank_last("安装方法: pip install lm-eval")
except Exception as e:
print_rank_last(f"lm-eval 评测出错: {e}")
import traceback
traceback.print_exc()
return integrated_metrics_func
def example_usage():
"""
使用示例
这个函数展示了如何在实际训练脚本中使用集成评测
"""
# 示例1: 定义数据集提供函数
def my_dataset_provider(datapath):
"""
你的数据集提供函数
需要返回一个数据集对象,包含:
- dataset_name 属性
- __getitem__ 方法,返回包含 'text', 'types', 'label', 'padding_mask' 的字典
"""
# 这里需要根据你的实际数据集实现
# 示例:
# from your_dataset import YourDataset
# return YourDataset(datapath)
raise NotImplementedError("请实现你的数据集提供函数")
# 示例2: 定义模型提供函数
def model_provider(pre_process=True, post_process=True):
"""
你的模型提供函数
"""
# 这里需要根据你的实际模型实现
# 示例:
# from megatron.model import GPTModel
# args = get_args()
# model = GPTModel(...)
# return model
raise NotImplementedError("请实现你的模型提供函数")
# 示例3: 获取 tokenizer
def get_tokenizer():
"""
获取 tokenizer
"""
from transformers import AutoTokenizer
args = get_args()
tokenizer_path = getattr(args, 'tokenizer_path', 'gpt2')
tokenizer = AutoTokenizer.from_pretrained(tokenizer_path)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
return tokenizer
# 示例4: 创建集成评测回调
tokenizer = get_tokenizer()
integrated_callback = create_integrated_eval_callback(
single_dataset_provider=my_dataset_provider,
model_provider_func=model_provider,
tokenizer=tokenizer,
lm_eval_tasks=["hellaswag", "arc"], # 可选:指定要评测的 lm-eval 任务
lm_eval_checkpoint_path=None # 如果为 None,使用训练检查点
)
# 示例5: 在训练中使用
def end_of_epoch_callback_provider():
return integrated_callback
# 在 finetune 函数中使用
# finetune(
# train_valid_datasets_provider=...,
# model_provider=model_provider,
# end_of_epoch_callback_provider=end_of_epoch_callback_provider
# )
def standalone_eval_example():
"""
独立评测示例(不训练,只评测)
这个示例展示了如何仅运行评测,不进行训练
"""
print("=" * 80)
print("独立评测示例")
print("=" * 80)
# 设置参数(仅评测模式)
args = get_args()
args.epochs = 0 # 不训练
# 定义你的函数
def model_provider(pre_process=True, post_process=True):
# 实现你的模型
pass
def get_tokenizer():
from transformers import AutoTokenizer
return AutoTokenizer.from_pretrained('gpt2')
def dataset_provider(datapath):
# 实现你的数据集
pass
tokenizer = get_tokenizer()
checkpoint_path = args.load
# 方法1: 使用原生 eval_utils.py
print("\n方法1: 使用 eval_utils.py 评测自定义数据集")
metrics_func = accuracy_func_provider(dataset_provider)
# metrics_func(model, epoch=-1, output_predictions=False)
# 方法2: 使用 lm-eval-harness
print("\n方法2: 使用 lm-eval-harness 评测标准任务")
results = use_megatron_with_lm_eval_harness(
model_provider_func=model_provider,
checkpoint_path=checkpoint_path,
tokenizer=tokenizer,
tasks=["hellaswag", "arc", "mmlu"],
batch_size=8
)
print(f"评测结果: {results}")
# 方法3: 同时使用两种方法
print("\n方法3: 同时使用两种评测方法")
integrated_callback = create_integrated_eval_callback(
single_dataset_provider=dataset_provider,
model_provider_func=model_provider,
tokenizer=tokenizer,
lm_eval_tasks=["hellaswag", "arc"]
)
# integrated_callback(model, epoch=-1)
if __name__ == '__main__':
print("这是一个示例脚本,展示了如何集成使用 eval_utils.py 和 lm-eval-harness")
print("请根据你的实际需求修改和实现相关函数")
print("\n主要功能:")
print("1. create_integrated_eval_callback() - 创建集成评测回调")
print("2. example_usage() - 在训练中使用集成评测")
print("3. standalone_eval_example() - 独立评测示例")