论坛首页 逆向工程技术区 阅读主题

[原创]大模型微调分享

88 浏览 0 回复
#1 楼主 2026-06-01 21:09:16
前言
由于在针对单片机和freertos类系统做逆向分析时,IDA中完全看不到任何符号,所以我想到了使用现有的qwen3-coder模型做微调以适应垂类任务
本文章全部基于我自己上传的unsloth项目制作,固如有不同架构,请另寻不同方法
开始
准备工作
本地需要安装docker,但是PGX上已经集成好了所有的环境,所以第一步应该是使用 apt 等命令更新所有可以更新的包,由于PGX机器的系统是NVIDIA定制的,所以源用的也是NVIDIA的软件源
代码部分
完整的微调代码很长,我放到最后了,这里只讲重要的部分
基座模型选择
选择基座模型时,我选择的是 unsloth/Qwen3-Coder-30B-A3B-Instruct 
# =========================
# 1) 选择Qwen3 Coder基座模型
# 说明:你可以改成你要微调的Qwen3 Coder具体型号
# 常见:Qwen/Qwen3-Coder-7B / 14B / 32B 等(以HF实际存在为准)
# =========================
base_model = "unsloth/Qwen3-Coder-30B-A3B-Instruct" # ← 按需修改
output_dir = "./qwen3-coder-decompilebench-lora"

主要是因为在我做微调的时候,unsloth在huggingface上还没有上传qwen3其他的coder模型,我的目标是针对IDA的伪代码进行符号表的还原,这类任务基本来说就是对代码进行审计,所以使用coder模型的效果应当是最好的
基座模型之间的区别简单来说:base < instruction < thinking
base模型只是做了预训练
instruction在base的基础上做了指令对齐,学会了结构化输出
thinking在instruction的基础上加入了思考模式,使得模型可以做更复杂的推理
数据选择
对于所有AI训练,数据都是最重要的,这里我只使用了一个开源的数据集并随机截取了其中15k条数据
# =========================
# 4) 加载数据集:LLM4Binary/decompile-bench
# 说明:该数据集的字段名可能会随版本变化
# 这里先拉取并查看列名,然后做自适配映射
# =========================
ds = load_dataset("LLM4Binary/decompile-bench")

print(ds)
print("Train columns:", ds["train"].column_names if "train" in ds else None)
# 有些数据集只有一个split,比如 "test" 或 "validation"
# 你可以按实际情况选择split
split_name = "train" if "train" in ds else list(ds.keys())[0]
raw_train = ds[split_name]

# =========================
# 4.1) 关键优化:先抽样/截取到 10k~15k,再做 map/filter
# 避免对全量大数据做 format_sft/tokenize/filter,节省时间和CPU
# =========================
TARGET_N = 15000 # 你希望保留的样本数量(建议 10000~15000 之间)
SHUFFLE = True # True:先打乱再取子集(更推荐,样本分布更随机)
SEED = 42 # shuffle 随机种子,保证可复现

n_total = len(raw_train)
n_take = min(TARGET_N, n_total)

if SHUFFLE:
# 先洗牌再取前 n_take 条
# 优点:相比直接取前N条更不容易出现“数据按来源/难度排序导致的偏差”
raw_train_small = raw_train.shuffle(seed=SEED).select(range(n_take))
else:
# 直接取前 n_take 条(速度最快,但可能存在顺序偏差)
raw_train_small = raw_train.select(range(n_take))


由于我们使用Lora做微调,所以数据不用太多,10k~15k就很完美,具体多少可以在训练时参考loss下降的速度
训练参数
# =========================
# 7) 训练参数
# 说明:GB10显存/统一内存很大,但仍建议从保守配置开始
# =========================
training_args = TrainingArguments(
output_dir=output_dir,
per_device_train_batch_size=8,
gradient_accumulation_steps=4, # 等效batch=8
learning_rate=2e-4,
warmup_ratio=0.03,
num_train_epochs=1, # 先跑通流程;再加大到 2-3
lr_scheduler_type="cosine",
logging_steps=10,
save_steps=200,
save_total_limit=2,
bf16=torch.cuda.is_available() and torch.cuda.is_bf16_supported(),
fp16=torch.cuda.is_available() and (not torch.cuda.is_bf16_supported()),
optim="paged_adamw_8bit", # bitsandbytes 8bit优化器,省显存
weight_decay=0.0,
report_to="none",
dataloader_num_workers=16, # 按CPU核心数调大,例如 8/16/32
dataloader_pin_memory=True, # GPU拷贝(通常有帮助)

这里有几个参数非常重要
per_device_train_batch_size=8 这个参数代表了每次训练时喂进去的数据量,由于使用的PGX有128G统一内存,所以这里可以设置高一些
gradient_accumulation_steps=4 这个参数代表了梯度下降的速度,这里设置的效果会在后续训练时通过loss观察到,建议4或者8
learning_rate=2e-4 这个参数代表学习率,步长小会导

...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-291250.htm

暂无回复,快来抢沙发吧!

请登录后参与讨论

立即登录 注册账号