数据预处理是LLM训练与推理的核心前提,直接决定模型训练效果与推理精度。MindSpore Transformers作为昇思生态下的大模型开发套件,提供了便捷、高效的数据预处理接口,支持Hugging Face数据集、本地文本、MindRecord等多种数据格式,可快速完成数据加载、清洗、分词、格式转换、批量处理等全流程操作,适配Qwen、Llama、DeepSeek等主流LLM。MindSpore Transformers LLM数据预处理的核心流程与实操技巧,搭配完整可执行代码,覆盖预训练与微调两大场景,适配昇腾NPU、CPU、GPU多硬件平台,助力开发者高效完成数据预处理工作。
一、数据预处理核心逻辑与环境准备
LLM数据预处理的核心是将原始文本数据转换为模型可识别的张量格式,核心流程为:数据加载→数据清洗→分词编码→格式适配→批量处理→数据优化。MindSpore Transformers集成了Tokenizer分词工具、Dataset数据处理模块,可灵活适配不同场景需求,前期需完成环境搭建,代码如下:
# 1. 创建虚拟环境并激活
conda create -n ms-llm-preprocess python=3.8
conda activate ms-llm-preprocess
# 2. 安装核心依赖(适配多硬件,昇腾NPU为例)
pip install mindspore-npu==2.3.0 mindspore-transformers==1.8.0 datasets sentencepiece -i https://pypi.tuna.tsinghua.edu.cn/simple
# 3. 验证环境(确保模块正常导入)
python -c "import mindspore; import mindspore_transformers; import datasets; print('环境搭建成功')"
二、核心预处理流程及实操代码
结合LLM预训练与微调的不同需求,分别讲解数据预处理全流程,搭配可直接执行的代码,涵盖主流数据格式与处理技巧,同时融入MindSpore Dataset模块的性能优化特性。
2.1 微调场景数据预处理(指令集数据,以Alpaca为例)
微调场景多采用指令-响应对数据集,需进行格式构造、分词编码、长度截断与填充,代码如下,适配Qwen3-8B模型,兼顾数据质量与处理效率:
from mindspore_transformers import AutoTokenizer
from datasets import load_dataset
import mindspore.dataset as ds
# 1. 加载数据集(在线加载Alpaca指令集,简化版用于演示)
dataset = load_dataset("tatsu-lab/alpaca", split="train[:1000]") # 取前1000条数据
# 2. 加载模型对应的Tokenizer(适配Qwen3-8B)
tokenizer = AutoTokenizer.from_pretrained("qwen3-8b")
tokenizer.pad_token = tokenizer.eos_token # 配置pad_token,避免编码报错
# 3. 数据清洗(过滤无效数据,处理空值)
def clean_data(examples):
# 过滤指令或输出为空的数据
return {
"instruction": [inst.strip() for inst in examples["instruction"] if inst.strip()],
"input": [inp.strip() for inp in examples["input"]],
"output": [out.strip() for out in examples["output"] if out.strip()]
}
# 应用清洗函数,批量处理数据
dataset = dataset.map(clean_data, batched=True)
# 4. 分词编码(构造指令格式,转换为模型可识别的张量)
def preprocess_function(examples):
# 构造指令-响应对格式(适配Qwen模型输入规范)
texts = [
f"### 指令: {inst}\n### 输入: {inp}\n### 输出: {out}"
for inst, inp, out in zip(examples["instruction"], examples["input"], examples["output"])
]
# 分词编码,设置最大长度,自动截断与填充
return tokenizer(
texts,
truncation=True,
max_length=512,
padding="max_length",
return_tensors="ms" # 输出MindSpore张量,适配昇腾硬件
)
# 批量预处理,启用多线程提升效率(根据硬件调整workers数量)
tokenized_dataset = dataset.map(
preprocess_function,
batched=True,
num_parallel_workers=4 # 多线程处理,降低CPU占用
)
# 5. 格式转换与批量处理(适配MindSpore训练接口)
# 转换为MindSpore Dataset格式
ms_dataset = ds.GeneratorDataset(
tokenized_dataset,
column_names=["input_ids", "attention_mask"],
shuffle=True # 训练前打乱数据
)
# 批量处理,设置批次大小
ms_dataset = ms_dataset.batch(batch_size=8, drop_remainder=True)
# 验证预处理结果
for batch in ms_dataset.create_dict_iterator():
print("输入张量形状:", batch["input_ids"].shape) # 输出:(8, 512)
print("注意力掩码形状:", batch["attention_mask"].shape)
break
2.2 预训练场景数据预处理(无标注文本,以WikiText为例)
预训练场景需处理海量无标注文本,核心是文本拼接、分词编码、序列长度对齐,推荐使用Megatron格式或MindRecord格式提升加载效率,代码如下:
# 1. 下载预训练原始文本数据(WikiText简化版)
wget https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-2-v1.zip
unzip wikitext-2-v1.zip && cd wikitext-2
# 2. 文本数据预处理(拼接、去重、过滤)
cat wiki.train.tokens | grep -v "^=" | tr -s ' ' > clean_train.txt # 过滤标题,去重空格
# 3. 转换为Megatron格式(适配MindSpore Transformers预训练)
# 克隆工具脚本
git clone https://gitee.com/mindspore/mindformers.git
cd mindformers
# 4. 执行预处理脚本,生成Megatron BIN格式数据集
python tools/dataset_preprocess/preprocess_indexed_dataset.py \
--input ../wikitext-2/clean_train.txt \
--tokenizer-type PretrainedFromHF \
--tokenizer-name-or-path qwen3-8b \
--output-prefix ../wikitext-2/wiki_megatron \
--max-seq-length 2048 \
--workers 8
# 5. 转换为MindRecord格式(提升大规模数据加载效率)
python tools/dataset_preprocess/llama/llama_preprocess.py \
--dataset_type wiki \
--input_glob ../wikitext-2/clean_train.txt \
--model_file ../qwen3-8b/tokenizer.model \
--seq_length 2048 \
--output_file ../wikitext-2/wiki_mindrecord
# 6. 加载MindRecord格式数据集(适配预训练)
import mindspore.dataset as ds
pretrain_dataset = ds.MindDataset(
dataset_dir="../wikitext-2/wiki_mindrecord",
shuffle=True,
num_parallel_workers=8,
prefetch_size=2 # 优化内存占用
)
pretrain_dataset = pretrain_dataset.batch(batch_size=4)
2.3 关键优化技巧(内存与性能优化)
针对大规模数据预处理的内存占用高、CPU占用异常等问题,结合MindSpore特性进行优化,代码如下,提升处理效率并降低硬件开销:
import mindspore.dataset as ds
import cv2
import os
# 1. 内存优化(降低预处理阶段内存占用)
ds.config.set_prefetch_size(2) # 设置预取大小,减少内存占用
# 批量处理时减少并行线程数(针对内存不足场景)
tokenized_dataset = dataset.map(
preprocess_function,
batched=True,
num_parallel_workers=1
)
# 2. CPU占用优化(解决多线程资源竞争问题)
# 若预处理包含cv2操作,设置cv2全局线程数
cv2.setNumThreads(2)
# 设置numpy线程数,避免资源竞争
os.environ["OPENBLAS_NUM_THREADS"] = "1"
# 3. 数据下沉模式(数据处理与模型训练并行,提升效率)
# 训练时启用数据下沉,构建Pipeline流水线
ms_dataset = ms_dataset.batch(batch_size=8, drop_remainder=True)
ms_dataset = ms_dataset.sink_mode(True) # 启用数据下沉,减少数据传输耗时
# 4. 自定义预处理函数(适配特殊格式数据)
def custom_preprocess(text):
# 自定义文本清洗逻辑(如去除特殊字符、统一大小写)
text = text.replace("\n", " ").replace("\\", "").lower()
# 分词编码
return tokenizer(text, truncation=True, max_length=2048)
# 应用自定义函数
dataset = dataset.map(lambda x: custom_preprocess(x["text"]), batched=False)
三、预处理常见问题与解决方案
1. 分词报错“pad_token is None”:需手动配置tokenizer.pad_token = tokenizer.eos_token,确保pad_token存在;2. 内存溢出:减少batch_size、降低num_parallel_workers数量,启用prefetch_size优化,或采用MindRecord格式分块存储数据;3. 数据加载缓慢:使用Megatron或MindRecord二进制格式,启用多线程加载,减少数据IO耗时;4. 张量格式不匹配:确保分词时指定return_tensors="ms",输出MindSpore张量,适配昇腾NPU训练;5. CPU占用异常:合理设置第三方库线程数,避免多线程资源竞争。