szxllm commited on
Commit
71c3881
·
verified ·
1 Parent(s): 9158a7e

Update pretrain.py

Browse files
Files changed (1) hide show
  1. pretrain.py +26 -87
pretrain.py CHANGED
@@ -55,26 +55,21 @@ class PreTrainer:
55
  self.min_lr = learning_rate * 0.1
56
  self.current_step = 0
57
 
58
- # 混合精度
59
  self.use_amp = torch.cuda.is_available()
60
  self.scaler = torch.amp.GradScaler('cuda', enabled=self.use_amp)
61
 
62
- # 训练参数
63
  self.gradient_accumulation_steps = gradient_accumulation_steps
64
  self.max_grad_norm = max_grad_norm
65
  self.max_steps = max_steps
66
  self.log_interval = log_interval
67
  self.save_interval = save_interval
68
 
69
- # Checkpoint管理
70
  self.checkpoint_dir = Path(checkpoint_dir)
71
  self.checkpoint_dir.mkdir(parents=True, exist_ok=True)
72
 
73
- # 损失日志
74
  self.loss_log_file = Path(loss_log_file)
75
  self.loss_log_file.parent.mkdir(parents=True, exist_ok=True)
76
 
77
- # 训练状态
78
  self.global_step = 0
79
  self.tokens_seen = 0
80
  self.running_loss = 0.0
@@ -89,17 +84,13 @@ class PreTrainer:
89
  logger.info(f" Mixed Precision: {self.use_amp}")
90
 
91
  def _get_lr(self) -> float:
92
- """手动计算学习率(Warmup + Cosine)"""
93
  if self.current_step < self.warmup_steps:
94
- # Linear warmup
95
  return self.max_lr * (self.current_step / self.warmup_steps)
96
  else:
97
- # Cosine decay
98
  progress = (self.current_step - self.warmup_steps) / (self.max_steps - self.warmup_steps)
99
  return self.min_lr + (self.max_lr - self.min_lr) * 0.5 * (1 + torch.cos(torch.tensor(progress * 3.14159)))
100
 
101
  def _set_lr(self, lr: float):
102
- """设置学习率"""
103
  for param_group in self.optimizer.param_groups:
104
  param_group['lr'] = lr
105
 
@@ -115,9 +106,6 @@ class PreTrainer:
115
  positions = torch.cumsum(non_pad_mask.long(), dim=0) -1
116
  position_ids[i]=positions * non_pad_mask.long()
117
 
118
-
119
-
120
- # 准备输入
121
  input_data = {
122
  'segments': [{
123
  'type': 'text',
@@ -126,7 +114,6 @@ class PreTrainer:
126
  }]
127
  }
128
 
129
- # 前向传播
130
  with torch.amp.autocast('cuda', enabled=self.use_amp):
131
  outputs = self.model(
132
  input_data,
@@ -134,7 +121,6 @@ class PreTrainer:
134
  position_ids=position_ids)
135
  logits = outputs['logits']
136
 
137
- # 计算损失(标准自回归)
138
  shift_logits = logits[:, :-1, :].contiguous()
139
  shift_labels = input_ids[:, 1:].contiguous()
140
  shift_attention_mask = attention_mask[:, 1:].contiguous()
@@ -145,7 +131,6 @@ class PreTrainer:
145
  reduction='none'
146
  )
147
 
148
- # 应用mask
149
  loss = (loss * shift_attention_mask.view(-1)).sum() / (shift_attention_mask.sum() + 1e-8)
150
  loss_for_backward = loss / self.gradient_accumulation_steps
151
 
@@ -153,27 +138,22 @@ class PreTrainer:
153
  self.tokens_seen += attention_mask.sum().item()
154
 
155
  return {
156
- 'loss': loss.item(), # 返回真实的、未缩放的loss
157
  'lr': self.optimizer.param_groups[0]['lr']
158
  }
159
 
160
  def optimizer_step(self):
161
- """优化器步骤"""
162
- # Unscale梯度
163
  self.scaler.unscale_(self.optimizer)
164
 
165
- # 梯度裁剪
166
  grad_norm = torch.nn.utils.clip_grad_norm_(
167
  self.model.parameters(),
168
  self.max_grad_norm
169
  )
170
 
171
- # 更新参数
172
  self.scaler.step(self.optimizer)
173
  self.scaler.update()
174
  self.optimizer.zero_grad(set_to_none=True)
175
 
176
- # 更新学习率
177
  self.current_step += 1
178
  self.global_step += 1
179
  lr = self._get_lr()
@@ -182,7 +162,6 @@ class PreTrainer:
182
  return grad_norm.item()
183
 
184
  def _write_loss_to_txt(self, step, avg_loss, lr, tokens_seen):
185
- """写入损失日志"""
186
  log_content = (
187
  f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] "
188
  f"Step: {step}/{self.max_steps}, "
@@ -194,19 +173,11 @@ class PreTrainer:
194
  f.write(log_content)
195
 
196
  def train(self, dataloader, resume_from=None):
197
- """训练循环"""
198
- logger.info("\n" + "="*80)
199
- logger.info("Starting Pre-Training (Fixed Version)")
200
- logger.info("="*80 + "\n")
201
-
202
- # 恢复训练
203
  if resume_from:
204
  self.load_checkpoint(resume_from)
205
-
206
- # 初始化日志
207
  if not self.loss_log_file.exists():
208
  with open(self.loss_log_file, 'w', encoding='utf-8') as f:
209
- f.write(" Fixed Training Log (Real Loss Values)\n")
210
  f.write("="*80 + "\n")
211
 
212
  self.model.train()
@@ -219,26 +190,21 @@ class PreTrainer:
219
 
220
  logger.info(f"Current Global Step: {self.global_step}")
221
  if batches_to_skip > 0:
222
- logger.info(f" Resuming: Need to skip {batches_to_skip} batches to restore data state...")
223
- logger.info("This might take a while depending on network/disk speed...")
224
 
225
  # 创建迭代器
226
  data_iterator = iter(dataloader)
227
-
228
  skipped = 0
229
  if batches_to_skip > 0:
230
  with tqdm(total=batches_to_skip, desc="Skipping trained batches", unit="batch") as skip_pbar:
231
  while skipped < batches_to_skip:
232
  try:
233
- # 只取数据,不进模型,不计算梯度
234
  _ = next(data_iterator)
235
  skipped += 1
236
  skip_pbar.update(1)
237
  except StopIteration:
238
- logger.error("Dataset exhausted during skipping! Check your dataset size or max_steps.")
239
  return
240
-
241
- logger.info(" Data fast-forward complete. Resuming training...")
242
 
243
  try:
244
  while True:
@@ -251,17 +217,20 @@ class PreTrainer:
251
  continue
252
  stats = self.train_step(batch)
253
  step_in_accumulation += 1
254
- accumulated_loss += stats['loss']
255
 
256
  if step_in_accumulation >= self.gradient_accumulation_steps:
257
  avg_step_loss = accumulated_loss / self.gradient_accumulation_steps
 
258
  grad_norm = self.optimizer_step()
259
  stats['grad_norm'] = grad_norm
260
- stats['loss'] = avg_step_loss
 
261
  self.running_loss += avg_step_loss
262
 
263
  step_in_accumulation = 0
264
- accumulated_loss = 0.0
 
265
  progress_bar.update(1)
266
  progress_bar.set_postfix({
267
  'loss': f"{stats['loss']:.4f}",
@@ -270,7 +239,6 @@ class PreTrainer:
270
  'grad': f"{grad_norm:.2f}"
271
  })
272
 
273
- # 日志记录
274
  if self.global_step % self.log_interval == 0:
275
  avg_loss = self.running_loss / self.log_interval
276
 
@@ -293,37 +261,26 @@ class PreTrainer:
293
  tokens_seen=self.tokens_seen
294
  )
295
  self.running_loss = 0.0
296
-
297
- # 保存checkpoint
298
  if self.global_step % self.save_interval == 0:
299
  self.save_checkpoint(
300
  self.checkpoint_dir / f"step_{self.global_step}.pt"
301
  )
302
 
303
- # 完成训练
304
  if self.global_step >= self.max_steps:
305
  break
306
 
307
  except KeyboardInterrupt:
 
308
  self.save_checkpoint(
309
  self.checkpoint_dir / f"interrupted_step_{self.global_step}.pt"
310
  )
311
 
312
  finally:
313
  progress_bar.close()
314
-
315
- logger.info("\n" + "="*80)
316
- logger.info("Pre-Training Complete!")
317
- logger.info(f" Total Steps: {self.global_step}")
318
- logger.info(f" Total Tokens: {self.tokens_seen/1e9:.2f}B")
319
- logger.info(f" Best Loss: {self.best_loss:.4f}")
320
- logger.info("="*80 + "\n")
321
-
322
- # 保存最终模型
323
  self.save_checkpoint(self.checkpoint_dir / "final_model.pt")
324
 
325
  def save_checkpoint(self, path: Path):
326
- """保存checkpoint"""
327
  checkpoint = {
328
  'model_state_dict': self.model.state_dict(),
329
  'optimizer_state_dict': self.optimizer.state_dict(),
@@ -339,7 +296,6 @@ class PreTrainer:
339
  logger.info(f" Checkpoint saved to {path}")
340
 
341
  def load_checkpoint(self, path: str):
342
- """加载checkpoint"""
343
  checkpoint = torch.load(path, map_location=self.device, weights_only=True)
344
 
345
  self.model.load_state_dict(checkpoint['model_state_dict'])
@@ -352,49 +308,38 @@ class PreTrainer:
352
  self.current_step = checkpoint.get('current_step', self.global_step)
353
  self.tokens_seen = checkpoint['tokens_seen']
354
  self.best_loss = checkpoint.get('best_loss', float('inf'))
355
-
356
- logger.info(f" Checkpoint loaded from {path}")
357
- logger.info(f" Resuming from step {self.global_step}")
358
- logger.info(f" Tokens seen: {self.tokens_seen/1e9:.2f}B")
359
 
360
 
361
  def main():
362
  config = {
363
- # 模型配置
364
  'model_dim': 1536,
365
  'vocab_size': 151665,
366
  'n_layers': 12,
367
  'n_heads': 12,
368
  'n_kv_heads': 4,
369
- 'max_seq_len': 512,
370
  'dropout': 0.1,
371
  'use_moe': False,
 
 
372
  'batch_size': 4,
373
  'gradient_accumulation_steps': 8,
374
- 'learning_rate': 3e-4,
375
  'weight_decay': 0.1,
376
  'warmup_steps': 500,
377
- 'max_steps': 10000,
378
  'max_grad_norm': 1.0,
379
 
380
- # 数据配置
381
- 'data_mix': 'text_only',
382
- 'max_length': 512,
383
  'num_workers': 2,
384
 
385
- # 日志和保存
386
  'log_interval': 10,
387
- 'save_interval': 500,
388
  'checkpoint_dir': 'checkpoints/pretrain_fixed',
389
- 'loss_log_file': 'checkpoints/pretrain_fixed/train_loss.log'
390
  }
391
-
392
- logger.info("="*80)
393
- logger.info(json.dumps(config, indent=2))
394
- logger.info("="*80 + "\n")
395
-
396
- # 初始化tokenizer
397
- logger.info("Initializing tokenizer...")
398
  tokenizer = AutoTokenizer.from_pretrained(
399
  "Qwen/Qwen2.5-7B-Instruct",
400
  use_fast=True,
@@ -406,9 +351,7 @@ def main():
406
  tokenizer.pad_token_id = tokenizer.eos_token_id
407
 
408
  config['vocab_size'] = len(tokenizer)
409
- logger.info(f"Vocab size: {config['vocab_size']}\n")
410
-
411
- # 初始化模型
412
  logger.info("Initializing model...")
413
  model = MultiModalDenseTransformer(
414
  model_dim=config['model_dim'],
@@ -424,9 +367,7 @@ def main():
424
  use_multimodal_fusion=False,
425
  use_contrastive=False
426
  )
427
-
428
- # 创建数据加载器
429
- logger.info(f"\nCreating dataloader (mix: {config['data_mix']})...")
430
  dataloader = create_pretrain_dataloader(
431
  mix_name=config['data_mix'],
432
  tokenizer=tokenizer,
@@ -434,8 +375,6 @@ def main():
434
  num_workers=config['num_workers'],
435
  max_length=config['max_length']
436
  )
437
-
438
- # 创建训练器
439
  trainer = PreTrainer(
440
  model=model,
441
  tokenizer=tokenizer,
@@ -450,9 +389,9 @@ def main():
450
  checkpoint_dir=config['checkpoint_dir'],
451
  loss_log_file=config['loss_log_file']
452
  )
453
-
454
  logger.info("\n Starting fresh training with fixes...\n")
455
- trainer.train(dataloader, resume_from="/root/step_6500.pt")
456
  #trainer.train(dataloader)
457
 
458
 
 
55
  self.min_lr = learning_rate * 0.1
56
  self.current_step = 0
57
 
 
58
  self.use_amp = torch.cuda.is_available()
59
  self.scaler = torch.amp.GradScaler('cuda', enabled=self.use_amp)
60
 
 
61
  self.gradient_accumulation_steps = gradient_accumulation_steps
62
  self.max_grad_norm = max_grad_norm
63
  self.max_steps = max_steps
64
  self.log_interval = log_interval
65
  self.save_interval = save_interval
66
 
 
67
  self.checkpoint_dir = Path(checkpoint_dir)
68
  self.checkpoint_dir.mkdir(parents=True, exist_ok=True)
69
 
 
70
  self.loss_log_file = Path(loss_log_file)
71
  self.loss_log_file.parent.mkdir(parents=True, exist_ok=True)
72
 
 
73
  self.global_step = 0
74
  self.tokens_seen = 0
75
  self.running_loss = 0.0
 
84
  logger.info(f" Mixed Precision: {self.use_amp}")
85
 
86
  def _get_lr(self) -> float:
 
87
  if self.current_step < self.warmup_steps:
 
88
  return self.max_lr * (self.current_step / self.warmup_steps)
89
  else:
 
90
  progress = (self.current_step - self.warmup_steps) / (self.max_steps - self.warmup_steps)
91
  return self.min_lr + (self.max_lr - self.min_lr) * 0.5 * (1 + torch.cos(torch.tensor(progress * 3.14159)))
92
 
93
  def _set_lr(self, lr: float):
 
94
  for param_group in self.optimizer.param_groups:
95
  param_group['lr'] = lr
96
 
 
106
  positions = torch.cumsum(non_pad_mask.long(), dim=0) -1
107
  position_ids[i]=positions * non_pad_mask.long()
108
 
 
 
 
109
  input_data = {
110
  'segments': [{
111
  'type': 'text',
 
114
  }]
115
  }
116
 
 
117
  with torch.amp.autocast('cuda', enabled=self.use_amp):
118
  outputs = self.model(
119
  input_data,
 
121
  position_ids=position_ids)
122
  logits = outputs['logits']
123
 
 
124
  shift_logits = logits[:, :-1, :].contiguous()
125
  shift_labels = input_ids[:, 1:].contiguous()
126
  shift_attention_mask = attention_mask[:, 1:].contiguous()
 
131
  reduction='none'
132
  )
133
 
 
134
  loss = (loss * shift_attention_mask.view(-1)).sum() / (shift_attention_mask.sum() + 1e-8)
135
  loss_for_backward = loss / self.gradient_accumulation_steps
136
 
 
138
  self.tokens_seen += attention_mask.sum().item()
139
 
140
  return {
141
+ 'loss': loss.item(),
142
  'lr': self.optimizer.param_groups[0]['lr']
143
  }
144
 
145
  def optimizer_step(self):
 
 
146
  self.scaler.unscale_(self.optimizer)
147
 
 
148
  grad_norm = torch.nn.utils.clip_grad_norm_(
149
  self.model.parameters(),
150
  self.max_grad_norm
151
  )
152
 
 
153
  self.scaler.step(self.optimizer)
154
  self.scaler.update()
155
  self.optimizer.zero_grad(set_to_none=True)
156
 
 
157
  self.current_step += 1
158
  self.global_step += 1
159
  lr = self._get_lr()
 
162
  return grad_norm.item()
163
 
164
  def _write_loss_to_txt(self, step, avg_loss, lr, tokens_seen):
 
165
  log_content = (
166
  f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] "
167
  f"Step: {step}/{self.max_steps}, "
 
173
  f.write(log_content)
174
 
175
  def train(self, dataloader, resume_from=None):
 
 
 
 
 
 
176
  if resume_from:
177
  self.load_checkpoint(resume_from)
 
 
178
  if not self.loss_log_file.exists():
179
  with open(self.loss_log_file, 'w', encoding='utf-8') as f:
180
+ f.write("Training Log (Real Loss Values)\n")
181
  f.write("="*80 + "\n")
182
 
183
  self.model.train()
 
190
 
191
  logger.info(f"Current Global Step: {self.global_step}")
192
  if batches_to_skip > 0:
193
+ logger.info(f"Resuming: Need to skip {batches_to_skip} batches to restore data state...")
 
194
 
195
  # 创建迭代器
196
  data_iterator = iter(dataloader)
 
197
  skipped = 0
198
  if batches_to_skip > 0:
199
  with tqdm(total=batches_to_skip, desc="Skipping trained batches", unit="batch") as skip_pbar:
200
  while skipped < batches_to_skip:
201
  try:
 
202
  _ = next(data_iterator)
203
  skipped += 1
204
  skip_pbar.update(1)
205
  except StopIteration:
206
+ logger.error("Dataset exhausted during skipping!")
207
  return
 
 
208
 
209
  try:
210
  while True:
 
217
  continue
218
  stats = self.train_step(batch)
219
  step_in_accumulation += 1
220
+ accumulated_loss += stats['loss']
221
 
222
  if step_in_accumulation >= self.gradient_accumulation_steps:
223
  avg_step_loss = accumulated_loss / self.gradient_accumulation_steps
224
+
225
  grad_norm = self.optimizer_step()
226
  stats['grad_norm'] = grad_norm
227
+ stats['loss'] = avg_step_loss
228
+
229
  self.running_loss += avg_step_loss
230
 
231
  step_in_accumulation = 0
232
+ accumulated_loss = 0.0
233
+
234
  progress_bar.update(1)
235
  progress_bar.set_postfix({
236
  'loss': f"{stats['loss']:.4f}",
 
239
  'grad': f"{grad_norm:.2f}"
240
  })
241
 
 
242
  if self.global_step % self.log_interval == 0:
243
  avg_loss = self.running_loss / self.log_interval
244
 
 
261
  tokens_seen=self.tokens_seen
262
  )
263
  self.running_loss = 0.0
 
 
264
  if self.global_step % self.save_interval == 0:
265
  self.save_checkpoint(
266
  self.checkpoint_dir / f"step_{self.global_step}.pt"
267
  )
268
 
 
269
  if self.global_step >= self.max_steps:
270
  break
271
 
272
  except KeyboardInterrupt:
273
+ logger.info("\n Training interrupted by user")
274
  self.save_checkpoint(
275
  self.checkpoint_dir / f"interrupted_step_{self.global_step}.pt"
276
  )
277
 
278
  finally:
279
  progress_bar.close()
280
+
 
 
 
 
 
 
 
 
281
  self.save_checkpoint(self.checkpoint_dir / "final_model.pt")
282
 
283
  def save_checkpoint(self, path: Path):
 
284
  checkpoint = {
285
  'model_state_dict': self.model.state_dict(),
286
  'optimizer_state_dict': self.optimizer.state_dict(),
 
296
  logger.info(f" Checkpoint saved to {path}")
297
 
298
  def load_checkpoint(self, path: str):
 
299
  checkpoint = torch.load(path, map_location=self.device, weights_only=True)
300
 
301
  self.model.load_state_dict(checkpoint['model_state_dict'])
 
308
  self.current_step = checkpoint.get('current_step', self.global_step)
309
  self.tokens_seen = checkpoint['tokens_seen']
310
  self.best_loss = checkpoint.get('best_loss', float('inf'))
 
 
 
 
311
 
312
 
313
  def main():
314
  config = {
 
315
  'model_dim': 1536,
316
  'vocab_size': 151665,
317
  'n_layers': 12,
318
  'n_heads': 12,
319
  'n_kv_heads': 4,
320
+ 'max_seq_len': 1024,
321
  'dropout': 0.1,
322
  'use_moe': False,
323
+
324
+
325
  'batch_size': 4,
326
  'gradient_accumulation_steps': 8,
327
+ 'learning_rate': 1e-4,
328
  'weight_decay': 0.1,
329
  'warmup_steps': 500,
330
+ 'max_steps': 100000,
331
  'max_grad_norm': 1.0,
332
 
333
+ 'data_mix': 'skypile_training',
334
+ 'max_length': 1024,
 
335
  'num_workers': 2,
336
 
 
337
  'log_interval': 10,
338
+ 'save_interval': 5000,
339
  'checkpoint_dir': 'checkpoints/pretrain_fixed',
340
+ 'loss_log_file': 'checkpoints/pretrain_fixed/train_loss_skypile_training.log'
341
  }
342
+
 
 
 
 
 
 
343
  tokenizer = AutoTokenizer.from_pretrained(
344
  "Qwen/Qwen2.5-7B-Instruct",
345
  use_fast=True,
 
351
  tokenizer.pad_token_id = tokenizer.eos_token_id
352
 
353
  config['vocab_size'] = len(tokenizer)
354
+
 
 
355
  logger.info("Initializing model...")
356
  model = MultiModalDenseTransformer(
357
  model_dim=config['model_dim'],
 
367
  use_multimodal_fusion=False,
368
  use_contrastive=False
369
  )
370
+
 
 
371
  dataloader = create_pretrain_dataloader(
372
  mix_name=config['data_mix'],
373
  tokenizer=tokenizer,
 
375
  num_workers=config['num_workers'],
376
  max_length=config['max_length']
377
  )
 
 
378
  trainer = PreTrainer(
379
  model=model,
380
  tokenizer=tokenizer,
 
389
  checkpoint_dir=config['checkpoint_dir'],
390
  loss_log_file=config['loss_log_file']
391
  )
392
+
393
  logger.info("\n Starting fresh training with fixes...\n")
394
+ trainer.train(dataloader, resume_from="/root/checkpoints/pretrain_fixed/step_35000.pt")
395
  #trainer.train(dataloader)
396
 
397