Delete train_pretrain.py

pull/424/head
紫苏 2025-05-28 17:48:49 +08:00 committed by GitHub
parent 3babaea826
commit ab170f57f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 0 additions and 234 deletions

View File

@ -1,234 +0,0 @@
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import time
import math
import warnings
import torch
import torch.distributed as dist
from torch import optim, nn
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from contextlib import nullcontext
from transformers import AutoTokenizer
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
from dataset.lm_dataset import PretrainDataset
warnings.filterwarnings('ignore')
def Logger(content):
if not ddp or dist.get_rank() == 0:
print(content)
def get_lr(current_step, total_steps, lr):
return lr / 10 + 0.5 * lr * (1 + math.cos(math.pi * current_step / total_steps))
loss_fct = nn.CrossEntropyLoss(reduction='none')
def train_epoch(epoch, start_step, wandb):
start_time = time.time()
if epoch == start_epoch:
train_loader_iter = iter(train_loader)
for _ in range(start_step + 1):
next(train_loader_iter)
for step, (X, Y, loss_mask) in enumerate(train_loader_iter, start=start_step + 1):
train_step(epoch, step, X, Y, loss_mask, wandb, start_time)
else:
for step, (X, Y, loss_mask) in enumerate(train_loader):
train_step(epoch, step, X, Y, loss_mask, wandb, start_time)
def train_step(epoch, step, X, Y, loss_mask, wandb, start_time):
X = X.to(args.device)
Y = Y.to(args.device)
loss_mask = loss_mask.to(args.device)
lr = get_lr(epoch * iter_per_epoch + step, args.epochs * iter_per_epoch, args.learning_rate)
for param_group in optimizer.param_groups:
param_group['lr'] = lr
with ctx:
res = model(X)
loss = loss_fct(
res.logits.view(-1, res.logits.size(-1)),
Y.view(-1)
).view(Y.size())
loss = (loss * loss_mask).sum() / loss_mask.sum()
loss += res.aux_loss
loss = loss / args.accumulation_steps
scaler.scale(loss).backward()
if (step + 1) % args.accumulation_steps == 0:
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad(set_to_none=True)
if step % args.log_interval == 0:
spend_time = time.time() - start_time
Logger(
'Epoch:[{}/{}]({}/{}) loss:{:.3f} lr:{:.12f} epoch_Time:{}min:'.format(
epoch + 1,
args.epochs,
step,
iter_per_epoch,
loss.item() * args.accumulation_steps,
optimizer.param_groups[-1]['lr'],
spend_time / (step + 1) * iter_per_epoch // 60 - spend_time // 60))
if (wandb is not None) and (not ddp or dist.get_rank() == 0):
wandb.log({"loss": loss.item() * args.accumulation_steps,
"lr": optimizer.param_groups[-1]['lr'],
"epoch_Time": spend_time / (step + 1) * iter_per_epoch // 60 - spend_time // 60})
if (step + 1) % args.save_interval == 0 and (not ddp or dist.get_rank() == 0):
model.eval()
moe_path = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/pretrain_{lm_config.hidden_size}{moe_path}.pth'
if isinstance(model, torch.nn.parallel.DistributedDataParallel):
state_dict = model.module.state_dict()
else:
state_dict = model.state_dict()
state_dict = {k: v.half() for k, v in state_dict.items()} # 半精度保存
torch.save(state_dict, ckp)
# 保存训练状态
training_state = {
'epoch': epoch,
'step': step,
'optimizer_state_dict': optimizer.state_dict(),
'scaler_state_dict': scaler.state_dict() if scaler is not None else None
}
training_state_path = f'{args.save_dir}/training_state.pth'
torch.save(training_state, training_state_path)
model.train()
def init_model(lm_config):
tokenizer = AutoTokenizer.from_pretrained('../model/')
model = MiniMindForCausalLM(lm_config).to(args.device)
Logger(f'LLM可训练总参数量:{sum(p.numel() for p in model.parameters() if p.requires_grad) / 1e6:.3f} 百万')
return model, tokenizer
def init_distributed_mode():
if not ddp: return
global ddp_local_rank, DEVICE
dist.init_process_group(backend="nccl")
ddp_rank = int(os.environ["RANK"])
ddp_local_rank = int(os.environ["LOCAL_RANK"])
ddp_world_size = int(os.environ["WORLD_SIZE"])
DEVICE = f"cuda:{ddp_local_rank}"
torch.cuda.set_device(DEVICE)
# torchrun --nproc_per_node 2 1-pretrain.py
if __name__ == "__main__":
# 命令行参数解析
parser = argparse.ArgumentParser(description="MiniMind Pretraining")
parser.add_argument("--out_dir", type=str, default="../out") # 输出目录
parser.add_argument("--epochs", type=int, default=8) # 训练轮次
parser.add_argument("--batch_size", type=int, default=8) # 物理批次大小
parser.add_argument("--learning_rate", type=float, default=5e-4)
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu")
parser.add_argument("--dtype", type=str, default="bfloat16") # 混合精度类型
parser.add_argument("--use_wandb", action="store_true") # 是否使用WandB
parser.add_argument("--wandb_project", type=str, default="MiniMind-Pretrain")
parser.add_argument("--num_workers", type=int, default=1) # 数据加载线程数
parser.add_argument("--ddp", action="store_true") # 是否启用DDP
parser.add_argument("--accumulation_steps", type=int, default=4) # 梯度累积步数
parser.add_argument("--grad_clip", type=float, default=1.0) # 梯度裁剪阈值
parser.add_argument("--log_interval", type=int, default=100) # 日志间隔(步)
parser.add_argument("--save_interval", type=int, default=100) # 保存间隔(步)
parser.add_argument('--local_rank', type=int, default=-1) # DDP自动传入参数
# 模型架构参数
parser.add_argument('--hidden_size', default=512, type=int) # 隐藏层维度
parser.add_argument('--num_hidden_layers', default=8, type=int) # 层数
parser.add_argument('--max_seq_len', default=4096, type=int) # 序列长度
parser.add_argument('--use_moe', default=False, type=bool) # 是否使用MoE
parser.add_argument("--data_path", type=str, default="../dataset/pretrain_hq.jsonl")
args = parser.parse_args()
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers, use_moe=args.use_moe)
args.save_dir = os.path.join(args.out_dir)
os.makedirs(args.save_dir, exist_ok=True)
os.makedirs(args.out_dir, exist_ok=True)
tokens_per_iter = args.batch_size * args.max_seq_len
device_type = "cuda" if "cuda" in args.device else "cpu"
args.wandb_run_name = f"MiniMind-Pretrain-Epoch-{args.epochs}-BatchSize-{args.batch_size}-LearningRate-{args.learning_rate}"
ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast()
ddp = int(os.environ.get("RANK", -1)) != -1 # is this a ddp run?
ddp_local_rank, DEVICE = 0, "cuda:0"
base_seed = 1337
torch.manual_seed(base_seed)
torch.cuda.manual_seed(base_seed)
if ddp:
init_distributed_mode()
args.device = torch.device(DEVICE)
rank = dist.get_rank()
torch.manual_seed(base_seed + rank)
# 同时设置 CUDA 的随机种子
torch.cuda.manual_seed(base_seed + rank)
if args.use_wandb and (not ddp or ddp_local_rank == 0):
import wandb
wandb.init(project=args.wandb_project, name=args.wandb_run_name)
else:
wandb = None
model, tokenizer = init_model(lm_config)
train_ds = PretrainDataset(args.data_path, tokenizer, max_length=args.max_seq_len)
train_sampler = DistributedSampler(train_ds) if ddp else None
train_loader = DataLoader(
train_ds,
batch_size=args.batch_size,
pin_memory=True,
drop_last=False,
shuffle=False,
num_workers=args.num_workers,
sampler=train_sampler
)
scaler = torch.cuda.amp.GradScaler(enabled=(args.dtype in ['float16', 'bfloat16']))
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
if ddp:
model._ddp_params_and_buffers_to_ignore = {"pos_cis"}
model = DistributedDataParallel(model, device_ids=[ddp_local_rank])
iter_per_epoch = len(train_loader)
# 检查是否存在保存的训练状态文件
training_state_path = f'{args.save_dir}/training_state.pth'
if os.path.exists(training_state_path):
training_state = torch.load(training_state_path)
start_epoch = training_state['epoch']
start_step = training_state['step']
optimizer.load_state_dict(training_state['optimizer_state_dict'])
if scaler is not None and training_state['scaler_state_dict'] is not None:
scaler.load_state_dict(training_state['scaler_state_dict'])
else:
start_epoch = 0
start_step = 0
for epoch in range(start_epoch, args.epochs):
train_epoch(epoch, start_step if epoch == start_epoch else 0, wandb)