开源方案学习
2025年6月8日
9:42
Retrieval:
第2名用llm2vec这个库,用SentenceTransformerTrainer训练,但是llm2vec这个包太老,自己想办法换成其他的方案。
用Flagembedding微调。
第5名:
第8名和第11名,都用transformer库的Automodel 和自定义Biencoder
第4名用model = Qwen2ModelLabel.from_pretrained(model_path, quantization_config=bnb_config)
第11名:(重点学习):
自定义Trainer中实现了evaluate函数,是不是单独控制eval的过程,eval时,eval_dataset不经过data_collator?
关于在训练过程中cuda oom的问题,可能是某个batch中有个很长的句子序列,由于pad=longest,会将当前batch中所有样本都pad到这个最长序列的长度,导致oom,解决方法:
1. 硬截断:绝对长度限制
方法:在分桶之前,直接丢弃或截断超过安全阈值的样本(核心理念:牺牲少量数据保训练稳定性)
python
max_safe_length = 1024 # 根据你的显存调整(例如 24GB 显存建议 ≤1024)
def filter_long_samples(example):
return len(example["input_ids"]) <= max_safe_length
dataset = dataset.filter(filter_long_samples) # 直接丢弃超长样本
# 或者强制截断(如果语义允许)
tokenizer(input_text, truncation=True, max_length=max_safe_length)
适用场景:长样本是少数异常值,且对任务影响不大时。
2. 动态批处理(Dynamic Batching)
原理:根据当前 batch 的实际序列长度动态调整 batch_size
实现方案:
python
from transformers import Trainer, TrainingArguments
# 自定义动态 batch 的 DataCollator
class DynamicBatchCollator:
def __init__(self, tokenizer, max_tokens=8192): # max_tokens = batch_size * max_len
self.tokenizer = tokenizer
self.max_tokens = max_tokens
def __call__(self, features):
features.sort(key=lambda x: len(x["input_ids"]), reverse=True)
batches = []
current_batch = []
current_tokens = 0
for feature in features:
seq_len = len(feature["input_ids"])
if current_tokens + seq_len > self.max_tokens:
batches.append(current_batch)
current_batch = []
current_tokens = 0
current_batch.append(feature)
current_tokens += seq_len
if current_batch:
batches.append(current_batch)
# 对每个小 batch 单独 pad
return [self.tokenizer.pad(batch, return_tensors="pt") for batch in batches]
# 在 Trainer 中使用
trainer = Trainer(
...,
data_collator=DynamicBatchCollator(tokenizer, max_tokens=8192),
)
已使用 OneNote 创建。