Fragmented-Training / 1.unsloth-Burden-based.py
aifeifei798's picture
Upload 2 files
2509a70 verified
raw
history blame
5.89 kB
from unsloth import FastLanguageModel
import os
import torch
from datasets import load_dataset
from trl import SFTConfig, SFTTrainer
import random # 【魔改】导入 random 库用于乱序
# os.environ["UNSLOTH_VLLM_STANDBY"] = "1"
# --- 本地路径配置 (无需更改) ---
# my_load_model = "Qwen3-30B-A3B-Thinking-2507"
my_load_model = "Qwen3-4B-Thinking-2507"
my_model_name = "QiMing-Polaris"
max_seq_length = 4096
print(f"Dataset: {my_model_name}")
local_model_path = f"/home/aifeifei/AI_Data/develop/mini_tang/modules/{my_load_model}"
local_data_dir = f"{my_model_name}"
local_data_file = os.path.join(local_data_dir, f"{my_model_name}.jsonl")
final_model_path = f"{my_model_name}-{my_load_model}_burden_trained_lora" # 【魔改】改个名,标记这是负重训练版
# --- 配置结束 ---
# 1. 加载模型和分词器 (无需更改)
dtype = (
None
)
load_in_4bit = True
print(f"✅ 步骤 1/6: 正在从本地路径 '{local_model_path}' 加载模型和分词器...")
model, tokenizer = FastLanguageModel.from_pretrained(
model_name=local_model_path,
max_seq_length=max_seq_length,
dtype=dtype,
load_in_4bit=load_in_4bit,
full_finetuning=False,
)
print("🎉 模型加载完成!")
# 2. 配置 LoRA (无需更改)
print("✅ 步骤 2/6: 正在配置 LoRA 适配器...")
model = FastLanguageModel.get_peft_model(
model,
r=8,
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
lora_alpha=16,
lora_dropout=0,
bias="none",
use_gradient_checkpointing="unsloth",
random_state=3407,
use_rslora=False,
loftq_config=None,
)
print("🎉 LoRA 配置完成!")
# 3. 加载和准备数据集 (【魔改】核心部分)
alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
### Instruction:
{}
### Input:
{}
### Response:
{}"""
EOS_TOKEN = tokenizer.eos_token
# =================================================================================
# 【魔改】 注入“负重训练”逻辑!
# =================================================================================
def apply_burden(text, burden_ratio=0.7):
"""
给一段文本绑上“铅袋”:按一定比例打乱词序。
"""
words = text.split(' ')
# 只有当单词数量大于3时才进行乱序,避免太短的文本失去意义
if len(words) > 3:
num_to_shuffle = int(len(words) * burden_ratio)
# 随机选择一些单词的索引
indices_to_shuffle = random.sample(range(len(words)), num_to_shuffle)
# 只打乱这些被选中的单词
shuffled_subset = [words[i] for i in indices_to_shuffle]
random.shuffle(shuffled_subset)
# 把打乱后的单词放回原位
shuffled_words = list(words) # 创建一个副本
for i, original_index in enumerate(indices_to_shuffle):
shuffled_words[original_index] = shuffled_subset[i]
return ' '.join(shuffled_words)
return text
def formatting_prompts_func(examples):
all_texts = []
for i in range(len(examples["instruction"])):
instruction = examples["instruction"][i]
input_text = examples["input"][i]
# 【魔改】 output 保持原样,是我们的“完美答案”
output_text = examples["output"][i]
# 【魔改】给 instruction 和 input 绑上“铅袋”!
burdened_instruction = apply_burden(instruction)
burdened_input = apply_burden(input_text)
# 【魔改】用“七零八落”的输入,去训练模型得到“规整”的输出
text = alpaca_prompt.format(burdened_instruction, burdened_input, output_text) + EOS_TOKEN
all_texts.append(text)
return {"text": all_texts}
# =================================================================================
print(f"✅ 步骤 3/6: 正在从HF '{local_data_file}' 加载并应用“负重训练”处理...")
dataset = load_dataset("json", data_files=local_data_file, split="train")
dataset = dataset.map(
formatting_prompts_func,
batched=True,
remove_columns=dataset.column_names,
load_from_cache_file=False,
)
print(f"🎉 数据集处理完成!总共生成了 {len(dataset)} 条“负重”训练样本。")
print("来看一个“绑了铅袋”的样本长啥样:\n")
print(dataset[0]['text']) # 打印第一条看看效果
# 4. 配置训练参数并开始训练
print("\n✅ 步骤 4/5: 开始模型微调...")
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
dataset_text_field="text",
max_seq_length=max_seq_length,
dataset_num_proc=8,
packing=False,
args=SFTConfig(
per_device_train_batch_size=4,
gradient_accumulation_steps=2,
dataloader_num_workers=4,
dataloader_pin_memory=True,
warmup_steps=25,
num_train_epochs=10,
learning_rate=2e-5,
fp16=not torch.cuda.is_bf16_supported(),
bf16=torch.cuda.is_bf16_supported(),
logging_steps=5,
optim="paged_adamw_8bit",
lr_scheduler_type="cosine",
warmup_ratio=0.03,
weight_decay=0.01,
seed=3407,
output_dir = f"output/{final_model_path}", # 建议加上输出目录,方便续训
report_to="none",
),
)
trainer.train()
# 5. 保存并测试 (无需更改)
print("\n✅ 步骤 5/5: 微调完成...")
model.save_pretrained(final_model_path)
tokenizer.save_pretrained(final_model_path)
print(f"🎉 “负重训练”版 LoRA 模型已保存到 '{final_model_path}' 文件夹。")