探索Qwen2ForCausalLM 架构上进行微调

简述

试验参考了mini_qwen 的开源实现

GitHub - qiufengqijun/mini_qwen: 这是一个从头训练大语言模型的项目,包括预训练、微调和直接偏好优化,模型拥有1B参数,支持中英文。这是一个从头训练大语言模型的项目,包括预训练、微调和直接偏好优化,模型拥有1B参数,支持中英文。. Contribute to qiufengqijun/mini_qwen development by creating an account on GitHub.https://github.com/qiufengqijun/mini_qwen

分词器使用Qwen/Qwen2.5-0.5B-Instruct,通过扩充模型隐藏状态层数、嵌入层维度和注意力头数,增加参数量到1B,使用flash_attention_2进行加速

主要特点:

  • 低资源需求:预训练和微调仅需 12GB 显存,DPO 训练需要 14GB 显存

  • 训练数据:使用来自 BAAI(北京智源人工智能研究院)的数据集,包括用于预训练的 160 亿 tokens、用于微调的 900 万条样本,以及用于偏好优化的 6 万条样本。

数据集

魔塔社区 BAAI/IndustryCorpus2 数据集,根据需要下载


# 下载预训练数据集
modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'film_entertainment/*/high*' --local_dir 'data/pt' # 数据量较大,英文文件选择前3个文件


modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'computer_programming_code/*/high*' --local_dir 'data/pt'
modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'computer_communication/*/high*' --local_dir 'data/pt' # 数据量较大,英文文件选择前3个文件


modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'tourism_geography/*/high*' --local_dir 'data/pt'
modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'artificial_intelligence_machine_learning/*/high*' --local_dir 'data/pt'
modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'news_media/*/high*' --local_dir 'data/pt'
modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'literature_emotion/*/high*' --local_dir 'data/pt' # 数据量较大,英文文件选择前3个文件


modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'accommodation_catering_hotel/*/high*' --local_dir 'data/pt'
modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'current_affairs_government_administration/*/high*' --local_dir 'data/pt' # 数据量较大,英文文件选择前3个文件


modelscope download --dataset 'BAAI/IndustryCorpus2' --include 'mathematics_statistics/*/high*' --local_dir 'data/pt'

查看下数据

dataset = load_dataset("parquet", data_files="mini_data/pt/accommodation_catering_hotel/chinese/high/rank_00000.parquet", split="train")
print(dataset[0])

# 大概这么个结构
{
  "text": "马亮:如何破解外卖骑手的\"生死劫\"\n在消费至上的今天,企业不应道德绑架消费者,让消费者为企业的伪善埋单。。。。。。",
  "alnum_ratio": 0.9146919431,
  "avg_line_length": 158.25,
  "char_rep_ratio": 0.044444444400000005,
  "flagged_words_ratio": 0.0,
  "max_line_length": 223,
  "num_words": 404,
  "perplexity": 858.6,
  "quality_score": 4.0625,
  "special_char_ratio": 0.1000526593,
  "word_rep_ratio": 0.088772846,
  "_id": 200200005357,
  "industry_type": "住宿_餐饮_酒店"
}

这个结构是一个经过质量分析或过滤的训练样本的 JSON 表示,用于语言模型训练前的数据评估或筛选阶段。它除了包含原始文本(text)外还包含了一系列用来衡量数据质量的统计特征指标,用于判断该样本是否值得保留用于训练。

🔹 质量指标字段说明:

字段名说明
alnum_ratio字母数字字符所占比例。用于判断文本是否主要为自然语言(而非乱码或表格类数据)
avg_line_length平均每行字符数。可能反映文本结构是否合理(过长/过短)
char_rep_ratio字符重复率。例如“哈哈哈哈哈哈”这种重复率就很高
flagged_words_ratio敏感词或不良词汇占比(0 表示未检测到敏感词)
max_line_length最长一行的字符数。可用于过滤极端异常格式文本
num_words词数总计。用于衡量样本长度
perplexity使用某个语言模型评估的困惑度(perplexity)。数值越低,表示文本越“正常”或模型越容易预测它
quality_score综合质量评分。可能是上述特征加权后的结果,衡量样本是否值得用于训练
special_char_ratio特殊字符(如 #¥%&* 等)在文本中的占比
word_rep_ratio单词重复率(如“外卖外卖外卖平台”)

训练逻辑

加载数据集

# 加载数据集并进行预处理
directories = [
    "accommodation_catering_hotel",
    "artificial_intelligence_machine_learning",
    "computer_communication",
    "computer_programming_code",
    "film_entertainment",
    "literature_emotion",
    "news_media",
    "tourism_geography",
    "current_affairs_government_administration",
    "mathematics_statistics",
]
data_files = find_files(directories)
dataset = load_dataset("parquet", data_files=data_files, split="train", columns=["text"]) # 只保留text字段
dataset = dataset.shuffle(seed=42)

数据清洗,将原始文本 → 添加结束符 → 分词 → 拼接成一长串 → 按 block_size 切成多个训练用的样本块(每块长度一致),给每条文本加上自定义的“结束符” <|im_end|>,把所有样本的 token 串接在一起(例如把多个 [101,102] 合并为 [101,102,103,104,...]),这是因为 GPT 模型的预训练目标是连续预测序列,所以训练输入是一个“连续的 token 流”。

计算总长度并对齐

  • 得到拼接后 token 总长度(例如 10,356)

  • 只保留整除 block_size(1024)的部分,截断掉尾部多余部分,例如:10356 → 10240(保留完整的 10 块)切成 1024 个 token 一块的样本,每隔 1024 个 token 分一块,生成多个训练样本,输出结构:

{
  "input_ids": [[token1...token1024], [token1025...token2048], ...],
  "attention_mask": 同理
}

参考预训练代码

def preprocess_dataset(examples):
    """预处理预训练数据集,将文本分词并分块"""
    eos_token = "<|im_end|>"
    text_examples = [text + eos_token for text in examples["text"]]  # 添加结束符
    tokenized_examples = tokenizer(text_examples, add_special_tokens=False)

    # 将分词结果拼接并分块
    concatenated_examples = {
        k: list(chain(*tokenized_examples[k])) for k in tokenized_examples.keys()
    }
    total_length = len(concatenated_examples[list(concatenated_examples.keys())[0]])
    block_size = 1024  # 分块大小
    total_length = (total_length // block_size) * block_size  # 对齐块大小

    result = {
        k: [t[i : i + block_size] for i in range(0, total_length, block_size)]
        for k, t in concatenated_examples.items()
    }
    return result


# 应用预处理函数
train_dataset = dataset.map(
    preprocess_dataset,
    batched=True,
    batch_size=5000,
    remove_columns=dataset.column_names,
    num_proc=16,
)

,原来有很多条文本,现在经过这段预处理函数:

  • 文本 → 拼接 → 分词 → 连续 token 序列 → 按块切分

  • 输出的每个样本都是 1024 个 token 的一段,可直接送入语言模型进行训练(如 GPT)

数据预处理

训练配置

预训练

accelerate_config.yaml 文件包含了用于配置训练环境的参数。以下是各个配置项的含义:

  • compute_environment: 指定计算环境,这里为本地机器 (LOCAL_MACHINE)。
  • debug: 调试模式,设置为 false 表示不启用调试。
  • deepspeed_config: 包含与 DeepSpeed 相关的配置:
    • gradient_accumulation_steps: 梯度累积步数,这里设置为 16。
    • gradient_clipping: 梯度裁剪值,防止梯度过大,这里为 1.0。
    • offload_optimizer_device: 优化器的卸载设备,这里为 none 表示不卸载。
    • offload_param_device: 参数的卸载设备,这里为 none
    • zero3_init_flag: 是否启用 ZeRO-3 初始化,这里为 false
    • zero_stage: ZeRO 优化的阶段,这里设置为 2。
  • distributed_type: 分布式训练类型,这里为 DEEPSPEED
  • downcast_bf16: 是否降低 bf16 精度,这里设置为 'no'。
  • enable_cpu_affinity: 是否启用 CPU 亲和性,设置为 false
  • machine_rank: 当前机器在分布式训练中的排名,这里为 0。
  • main_training_function: 主训练函数的名称,这里为 main
  • mixed_precision: 混合精度训练,这里使用 bf16。
  • num_machines: 参与训练的机器数量,这里为 1。
  • num_processes: 每台机器上的进程数量,这里为 2。
  • rdzv_backend: rendezvous 后端,这里为 static
  • same_network: 是否在同一网络中,设置为 true
  • tpu_env: TPU 环境配置,这里为空。
  • tpu_use_cluster: 是否使用 TPU 集群,设置为 false
  • tpu_use_sudo: 是否使用 sudo 权限,设置为 false
  • use_cpu: 是否使用 CPU 进行训练,设置为 false

这些配置项帮助用户设置和优化模型训练过程,尤其是在使用 DeepSpeed 进行分布式训练时, 配置参考

compute_environment: LOCAL_MACHINE
debug: false
deepspeed_config:
  gradient_accumulation_steps: 16
  gradient_clipping: 1.0
  offload_optimizer_device: none
  offload_param_device: none
  zero3_init_flag: false
  zero_stage: 2
distributed_type: DEEPSPEED
downcast_bf16: 'no'
enable_cpu_affinity: false
machine_rank: 0
main_training_function: main
mixed_precision: bf16
num_machines: 1
num_processes: 2
rdzv_backend: static
same_network: true
tpu_env: []
tpu_use_cluster: false
tpu_use_sudo: false
use_cpu: false

训练逻辑

# 已经下载了Qwen2.5-0.5B-Instruct地址
model_path = "./models/Qwen2.5-0.5B-Instruct"
config = AutoConfig.from_pretrained(model_path)

# 调整模型配置
config.num_attention_heads = 16
config.num_key_value_heads = 4
config.hidden_size = 1024
config.num_hidden_layers = 48

# 加载模型
model = AutoModelForCausalLM.from_config(config, torch_dtype=torch.bfloat16, attn_implementation="flash_attention_2")

# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_path)


# 训练参数配置
training_args = TrainingArguments(
    output_dir=output_path,
    overwrite_output_dir=True,
    learning_rate=1e-4,
    warmup_ratio=0.1,
    lr_scheduler_type="cosine",
    num_train_epochs=1,
    per_device_train_batch_size=12,
    gradient_accumulation_steps=16,
    save_steps=100_000,
    save_total_limit=3,
    bf16=True,
    # save_only_model=True,
    logging_steps=20,
)

# 初始化Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=collator,
    train_dataset=train_dataset,
)

使用accelerate 加速训练

模型参数量: 576851712
表示模型总共有 576,851,712 个参数,也就是约 5.77 亿参数(≈ 577M)。

和之前用的MiniMind架构的模型比训练速度要慢很多,所以直接跳过预训练使用基座进行微调

SFT微调

 trl 配置

# 训练参数配置
training_args = SFTConfig(
    output_dir=output_path,                 # 训练完成后模型保存的目录
    overwrite_output_dir=True,             # 如果目录已存在则覆盖原模型
    learning_rate=1e-5,                    # 学习率,SFT阶段建议小一点
    warmup_ratio=0.1,                      # 热身步数比例,用于逐渐增加学习率
    lr_scheduler_type="cosine",            # 学习率调度策略:余弦退火
    num_train_epochs=3,                    # 训练轮数
    per_device_train_batch_size=12,        # 每张显卡的batch大小(显存不够就调小)
    gradient_accumulation_steps=16,        # 梯度累计步数,总batch大小 = 12 × 16 = 192
    save_strategy="epoch",                 # 每轮结束保存一次模型
    save_total_limit=3,                    # 最多保存3个checkpoint,旧的自动删掉
    bf16=True,                             # 使用 bfloat16 进行训练(比 fp16 更稳定,NVIDIA A100/H100 支持)
    logging_steps=20,                      # 每20步打印一次日志
)

# 初始化Trainer
trainer = SFTTrainer(
    model=model,                           # 使用的模型(已初始化)
    args=training_args,                    # 上面定义的训练参数
    train_dataset=dataset,                 # 训练数据集
    tokenizer=tokenizer,                   # 分词器
    formatting_func=formatting_prompts_func, # 格式化数据的函数,把样本转换成 prompt + completion
    data_collator=collator,               # 数据整理器(例如自动填充、构建input_ids等)
)

<think>嗯,用户给了一段日志信息,需要我帮忙介绍里面的内容。首先,我需要仔细看看这些日志的结构和内容。看起来是加载了一个模型的配置文件,还有Unsloth的提示信息。用户可能是在进行模型微调,遇到了相关日志,想了解具体配置或者优化工具的作用。 首先,日志显示加载了DeepSeek-R1-Distill-Qwen-1.5B的配置文件config.json。这个模型属于Qwen2ForCausalLM架构,可能是一个用于因果语言模型的生成式模型。我需要解释配置文件中的各个参数,比如hidden_size、num_hidden_layers这些,帮助用户理解模型的结构。 然后,注意到模型配置中有一些关键参数,比如hidden_size是1536,层数是28,注意力头数是12,中间层大小是8960。这些参数决定了模型的复杂度和能力。另外,max_position_embeddings是131072,说明上下文窗口很大,可能适合处理长文本任务。不过sliding_window设置为4096,可能使用了滑动窗口机制来优化长序列处理,但use_sliding_window却是false,这有点矛盾,可能需要进一步确认是否正确配置。 接下来是Unsloth的提示,说能加速微调。用户可能在使用这个工具来提升训练速度。需要解释Unsloth的作用,比如通过优化内存使用、内核优化等技术,让微调过程更快,可能兼容Hugging Face的库,对用户来说是否容易使用。 然后要考虑用户的潜在需求。用户可能在微调这个DeepSeek模型,遇到了配置问题,或者想了解模型结构是否适合他们的任务。比如vocab_size是151936,词汇量很大,可能支持多语言或者大量专业术语。另外,模型使用了bfloat16的torch数据类型,可能在节省内存的同时保持数值稳定性。 用户可能还关心如何利用这些配置优化他们的训练,比如调整超参数,或者理解滑动窗口和rope_theta这样的参数对模型的影响。需要确保解释清晰,帮助他们做出调整。 最后,确保回答结构清晰,分点解释模型配置和Unsloth工具,可能还需要提醒用户注意配置中的矛盾点,比如sliding_window和use_sliding_window的设置是否冲突,建议检查。同时,提供进一步帮助的建议,让用户知道可以继续提问。</think>我来为您解读这个模型加载日志: 1. **模型基本信息** - 模型名称:DeepSeek-R1-Distill-Qwen-1.5B - 架构类型:Qwen2ForCausalLM(因果语言模型) - 模型类型:qwen2 - 参数规模:约15亿参数(通过hidden_size=1536,num_hidden_layers=28估算) 2. **核心架构参数** $$ \begin{aligned} &\text{隐藏层维度} &= 1536 \\ &\text{中间层维度} &= 8960 \\ &\text{注意力头数} &= 12 \\ &\text{关键值头数} &= 2 \\ &\text{层数} &= 28 \\ &\text{词表大小} &= 151,936 \end{aligned} $$ 3. **关键特性** - **长上下文支持**:通过`max_position_embeddings=131072`支持最长131k tokens的上下文 - **窗口注意力**:配置了`sliding_window=4096`的滑动窗口机制,但实际未启用(`use_sliding_window=false`) - **高效训练**:使用`bfloat16`数据类型节省显存,保持数值稳定性 - **旋转位置编码**:采用RoPE(Rotary Position Embedding)技术,基础频率$\theta=10000$ 4. **Unsloth优化提示** - 检测到使用`Unsloth`优化库,该工具通过以下方式提升微调速度: - 内存优化(减少约50%显存占用) - 内核加速(提速约30%) - 自动梯度检查点 - 与Hugging Face生态无缝兼容 5. **特殊配置说明** - 使用非对称注意力头配置(12个注意力头 vs 2个关键值头) - 采用RMSNorm归一化(`rms_norm_eps=1e-6`) - 禁用词嵌入共享(`tie_word_embeddings=false`) 这个配置展示了一个经过蒸馏优化的中文大语言模型,适合在消费级GPU上进行高效微调。如需进一步了解具体参数作用或优化建议,可以告诉我您的具体使用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CHEN_RUI_2200

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值