数据受限语言模型大规模扩展
本库提供了论文《数据受限语言模型大规模扩展》中的所有组件概述。
我们研究了在数据受限环境下对语言模型进行扩展。我们进行了大量实验,改变数据重复的程度和计算预算,最高达到9000亿个训练标记和90亿参数的模型。基于我们的运行结果,我们提出并实证验证了一种计算最优化的扩展法则,该法则考虑了重复标记和多余参数价值的递减。我们还尝试了缓解数据稀缺的方法,包括用代码数据增强训练数据集、困惑度过滤和去重。我们的400次训练运行中的模型和数据集可通过本库获得。
数据
重复
我们在 C4 和未去重的英文 OSCAR 分集上进行数据重复实验。对于每个数据集,我们下载数据并将其转换为单个 jsonl 文件,分别为 c4.jsonl
和 oscar_en.jsonl
。
然后我们决定需要的数据的独特标记数和相应的样本数。请注意,使用 GPT2Tokenizer 时,C4 每个样本有 478.625834583
个标记,而 OSCAR 有 1312.0951072
个标记。这是通过对整个数据集进行标记并将标记数除以样本数得出的。我们使用这些数字来计算所需的样本数。
例如,对于 19 亿个独特标记,我们需要 1.9B / 478.625834583 = 3969697.96178
个 C4 样本和 1.9B / 1312.0951072 = 1448065.76107
个 OSCAR 样本。要对数据进行标记,我们首先需要克隆 Megatron-DeepSpeed 库并按照其设置指南进行操作。然后我们选择这些样本并对其进行如下标记:
C4:
head -n 3969698 c4.jsonl > c4_1b9.jsonl
python Megatron-DeepSpeed/tools/preprocess_data_many_cores.py \
--input c4_1b9.jsonl \
--output-prefix gpt2tok_c4_en_1B9 \
--dataset-impl mmap \
--tokenizer-type PretrainedFromHF \
--tokenizer-name-or-path gpt2 \
--append-eod \
--workers 64
OSCAR:
head -n 1448066 oscar_en.jsonl > oscar_1b9.jsonl
python Megatron-DeepSpeed/tools/preprocess_data_many_cores.py \
--input oscar_1b9.jsonl \
--output-prefix gpt2tok_oscar_en_1B9 \
--dataset-impl mmap \
--tokenizer-type PretrainedFromHF \
--tokenizer-name-or-path gpt2 \
--append-eod \
--workers 64
其中 gpt2
指向包含 https://huggingface.co/gpt2/tree/main 中所有文件的文件夹。通过使用 head
我们确保不同子集具有重叠的样本以减少随机性。
在训练期间和最终评估时,我们使用 C4 的验证集:
from datasets import load_dataset
load_dataset("c4", "en", split="validation").to_json("c4-en-validation.json")
python Megatron-DeepSpeed/tools/preprocess_data_many_cores.py \
--input c4-en-validation.jsonl \
--output-prefix gpt2tok_c4validation_rerun \
--dataset-impl mmap \
--tokenizer-type PretrainedFromHF \
--tokenizer-name-or-path gpt2 \
--append-eod \
--workers 2
对于没有官方验证集的 OSCAR,我们通过 tail -364608 oscar_en.jsonl > oscarvalidation.jsonl
从训练集中提取一部分,然后按如下方式对其进行标记:
python Megatron-DeepSpeed/tools/preprocess_data_many_cores.py --input oscarvalidation.jsonl --output-prefix gpt2tok_oscarvalidation --dataset-impl mmap --tokenizer-type PretrainedFromHF --tokenizer-name-or-path gpt2 --append-eod --workers 2
我们上传了几个预处理过的子集用于 Megatron:
- C4: https://huggingface.co/datasets/datablations/c4-subsets
- OSCAR: https://huggingface.co/datasets/datablations/oscar-subsets
由于某些 bin 文件过大而不能上传到 git,因此我们使用 split --number=l/40 gpt2tok_c4_en_1B9.bin gpt2tok_c4_en_1B9.bin.
和 split --number=l/40 gpt2tok_oscar_en_1B9.bin gpt2tok_oscar_en_1B9.bin.
将其拆分。要将其用于训练,需要使用 cat gpt2tok_c4_en_1B9.bin.* > gpt2tok_c4_en_1B9.bin
和 cat gpt2tok_oscar_en_1B9.bin.* > gpt2tok_oscar_en_1B9.bin
重新合并。
代码
我们使用 the-stack-dedup 中的 Python 分集将代码与自然语言数据混合进行实验。我们下载数据,将其转换为单个 jsonl 文件,并使用上述相同的方法进行预处理。
我们上传了预处理版本供 Megatron 使用:https://huggingface.co/datasets/datablations/python-megatron。我们使用 split --number=l/40 gpt2tok_python_content_document.bin gpt2tok_python_content_document.bin.
拆分了 bin 文件,因此需要使用 cat gpt2tok_python_content_document.bin.* > gpt2tok_python_content_document.bin
重新合并进行训练。
过滤
我们创建了包含困惑度和去重相关元数据的 C4 和 OSCAR 版本:
- C4: https://huggingface.co/datasets/datablations/c4-filter
- OSCAR: https://huggingface.co/datasets/datablations/oscar-filter
要重新创建这些元数据数据集,请参见 filtering/README.md
中的说明。
我们提供了可用于 Megatron 训练的标记版本:
- C4: https://huggingface.co/datasets/datablations/c4-filter-megatron
- OSCAR: https://huggingface.co/datasets/datablations/oscar-filter-megatron
.bin
文件使用类似 split --number=l/10 gpt2tok_oscar_en_perplexity_25_text_document.bin gpt2tok_oscar_en_perplexity_25_text_document.bin.
的命令拆分,因此需要通过 cat gpt2tok_oscar_en_perplexity_25_text_document.bin.* > gpt2tok_oscar_en_perplexity_25_text_document.bin
重新合并。
要根据元数据数据集重新创建标记版本,
- OSCAR:
- 去重:见
filtering/deduplication/filter_oscar_jsonl.py
- 困惑度:见下文。
- 去重:见
- C4:
- 去重:见下文。
- 困惑度:见下文。
困惑度
要创建困惑度百分点,请按照以下说明操作。
C4:
from datasets import load_dataset
import numpy as np
ds = load_dataset("datablations/c4-filter", streaming=False, num_proc=128)
p_25 = np.percentile(ds["train"]["perplexity"], 25)
p_50 = np.percentile(ds["train"]["perplexity"], 50)
p_75 = np.percentile(ds["train"]["perplexity"], 75)
# 25th - 75th percentile
ds["train"].filter(lambda x: p_25 < x["perplexity"] < p_75, num_proc=128).to_json("c4_perplexty2575.jsonl", num_proc=128, force_ascii=False)
# 25th percentile
ds["train"].filter(lambda x: x["perplexity"] < p_25, num_proc=128).to_json("c4_perplexty25.jsonl", num_proc=128, force_ascii=False)
# 50th percentile
ds["train"].filter(lambda x: x["perplexity"] < p_50, num_proc=128).to_json("c4_perplexty50.jsonl", num_proc=128, force_ascii=False)
OSCAR:
from datasets import load_dataset
import numpy as np
ds = load_dataset("datablations/oscar-filter", use_auth_token=True, streaming=False, num_proc=128)
p_25 = np.percentile(ds["train"]["perplexity_score"], 25)
p_50 = np.percentile(ds["train"]["perplexity_score"], 50)
# 25th percentile
ds["train"].filter(lambda x: x["perplexity_score"] < p_25, num_proc=128).remove_columns(['meta', 'perplexity_score', 'text_length', 'url', 'domain', 'dup_ratio', 'pairs', 'repetitions', 'included_in_dedup', 'cluster', 'id']).to_json("oscar_perplexity25.jsonl", num_proc=128, force_ascii=False)
# 50th percentile
ds["train"].filter(lambda x: x["perplexity_score"] < p_50, num_proc=128).remove_columns(['meta', 'perplexity_score', 'text_length', 'url', 'domain', 'dup_ratio', 'pairs', 'repetitions', 'included_in_dedup', 'cluster', 'id']).to_json("oscar_perplexity50.jsonl", num_proc=128, force_ascii=False)
然后你可以按照重复部分中描述的方法对生成的 jsonl 文件进行训练前的标记。
去重
C4:
对于 C4,只需删除所有 repetitions
字段被填充的样本,例如:
from datasets import load_dataset
ds = load_dataset("datablations/c4-dedup", use_auth_token=True, streaming=False, num_proc=128)
ds.filter(lambda x: not x["repetitions"]).to_json('c4_dedup.jsonl', num_proc=128, force_ascii=False)
OSCAR:
对于 OSCAR,我们提供一个脚本 filtering/filter_oscar_jsonl.py
来根据过滤元数据集创建去重数据集。
然后你可以按照重复部分中描述的方法对生成的 jsonl 文件进行训练前的标记。
模型
下载
所有模型可从 https://huggingface.co/datablations 下载。
模型通常按照以下方式命名:lm1-{参数}-{令牌}-{唯一令牌}
,具体到文件夹中的单个模型命名为:{参数}{令牌}{唯一令牌}{可选说明}
,例如 1b12b8100m
表示 11 亿参数,28 亿令牌,1 亿唯一令牌。xby
(1b1
,2b8
等)命名方法带来了一些歧义,数字可能属于参数或令牌,但你可以随时检查相应文件夹中的 sbatch 脚本以查看确切的参数/令牌/唯一令牌。
最简单单个模型的下载方法如:
GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/datablations/lm1-misc
cd lm1-misc; git lfs pull --include 146m14b400m/global_step21553
如果这太耗时,可以使用 wget
直接从文件夹下载单个文件,例如:
wget https://huggingface.co/datablations/lm1-misc/resolve/main/146m14b400m/global_step21553/bf16_zero_pp_rank_0_mp_rank_00_optim_states.pt
关于论文中的试验模型,请参考以下库:
- 附录中的 IsoLoss 试验和双重下降数据:
- https://huggingface.co/datablations/lm1-misc
- 用于附录中的 1 亿唯一令牌去重比较的
lm1-misc/*dedup*
- IsoFLOP 试验:
- C4:
- https://huggingface.co/datablations/lm1-8b7-178b-c4-repetitions
- https://huggingface.co/datablations/lm1-4b2-84b-c4-repetitions
- https://huggingface.co/datablations/lm1-4b2-84b-c4seeds
- https://huggingface.co/datablations/lm1-2b8-55b-c4-repetitions
- https://huggingface.co/datablations/lm1-2b8-55b-c4seeds
- OSCAR:
- https://huggingface.co/datablations/lm1-8b7-178b-oscar-repetitions
- https://huggingface.co/datablations/lm1-4b2-84b-oscar-repetitions
- https://huggingface.co/datablations/lm1-4b2-84b-oscarseeds
- https://huggingface.co/datablations/lm1-2b8-55b-oscar-repetitions
- https://huggingface.co/datablations/lm1-2b8-55b-oscarseeds
- C4:
- 代码增量:
- 困惑度过滤:
- C4:
- OSCAR:
- 去重:
- ROOTS 过滤
- muP(附录):
论文中未分析的其他模型:
- UL2:https://huggingface.co/datablations/lm5-2b8-55b-c4
- 所有训练了 1 个纪元的 c4 8b7 模型检查点:https://huggingface.co/datablations/lm1-8b7-176b-c4-ckpts
- Adam beta2 消融:https://huggingface.co/datablations/lm1-8b7-12b-beta
- 预热消融:https://huggingface.co/datablations/lm1-83m-20b-nowarmup
- 仅预训练在指令数据集上的试验:https://huggingface.co/datablations/lm1-2b8-55b-realtasky
- The Pile 上的杂项运行:https://huggingface.co/datablations/lm1-misc-pile
- OSCAR 上的杂项运行:https://huggingface.co/datablations/lm1-misc-oscar
- C4 上的 11 亿 IsoFLOP:https://huggingface.co/datablations/lm1-1b1-21b-c4 & https://huggingface.co/datablations/lm1-1b1-21b-c4-repetitions & https://huggingface.co/datablations/lm1-1b1-21b-c4seeds
训练
常规模型
我们使用修改版的 Megatron-DeepSpeed 训练模型,该版本支持 AMD GPU(通过 ROCm):https://github.com/TurkuNLP/Megatron-DeepSpeed 若要使用 NVIDIA GPU(通过 cuda),可以使用原版库:https://github.com/bigscience-workshop/Megatron-DeepSpeed
你需要按照任一库的设置说明创建环境(我们针对 LUMI 的设置详见 training/megdssetup.md
)。
每个模型文件夹包含一个用于训练模型的 sbatch 脚本。你可以参考这些脚本来训练自己的模型,调整必要的环境变量。sbatch 脚本引用了一些附加文件:
- 指定数据路径的
*txt
文件,可以在utils/datapaths/*
找到,但你可能需要调整路径以指向你的数据集。 - 包含架构预设的
model_params.sh
在utils/model_params.sh
。 - 包含我们特定设置命令的
launch.sh
在training/launch.sh
。你可能需要移除。
训练后,你可以例如使用 python Megatron-DeepSpeed/tools/convert_checkpoint/deepspeed_to_transformers.py --input_folder global_step52452 --output_folder transformers --target_tp 1 --target_pp 1
将模型转换为 transformers 格式。
对于重复模型,我们在训练后上传其 tensorboards,例如 tensorboard dev upload --logdir tensorboard_8b7178b88boscar --name "tensorboard_8b7178b88boscar"
,方便在论文中进行可视化使用。
muP
附录中的 muP 消融使用 training_scripts/mup.py
中的脚本。里面包含设置说明。
参数拟合
你可以使用我们公式计算给定参数、数据和唯一令牌的预期损失,如下所示:
import numpy as np
func = r"$L(N,D,R_N,R_D)=E + \frac{A}{(U_N + U_N * R_N^* * (1 - e^{(-1*R_N/(R_N^*))}))^\alpha} + \frac{B}{(U_D + U_D * R_D^* * (1 - e^{(-1*R_D/(R_D^*))}))^\beta}$"
a, b, e, alpha, beta, rd_star, rn_star = [6.255414, 7.3049974, 0.6254804, 0.3526596, 0.3526596, 15.387756, 5.309743]
A = np.exp(a)
B = np.exp(b)
E = np.exp(e)
G = ((alpha*A)/(beta*B))**(1/(alpha+beta))
def D_to_N(D):
return (D * G)**(beta/alpha) * G
def scaling_law(N, D, U):
"""
N:参数数量
D:训练令牌总数
U:唯一训练令牌数量
"""
assert U <= D, "唯一令牌不能多于总令牌"
RD = np.maximum((D / U) - 1, 0)
UN = np.minimum(N, D_to_N(U))
RN = np.maximum((N / UN ) - 1, 0)
L = E + A/(UN + UN*rn_star*(1-np.exp(-1*RN/rn_star)))**alpha + B / (U + U * rd_star * (1 - np.exp(-1*RD/(rd_star))))**beta
return L
# 图 1(右)中的模型:
print(scaling_law(6.34e9, 242e9, 25e9)) # 2.2256440889984477 # <- 这个更好
print(scaling_law(8.67e9, 178e9, 25e9)) # 2.2269634075087867
请注意,实际损失值可能用处不大,而是 e.g. 参数数量增加时的损失趋势或者如上例对比两个模型。要计算最优分配,可以使用简单的网格搜索:
def optimal_allocation(N_BASE, D_BASE, U_BASE):
min_l = float("inf")
for i in np.linspace(1.0001, 3, 500):
D = D_BASE*i
U = min(U_BASE, D)
N = N_BASE/i
new_l = scaling_law(N, D, U)
if new_l < min_l:
min_l, min_t, min_s = new_l, D, N
D = D_BASE/i
U = min(U_BASE, D)
N = N_BASE*i
new_l = scaling_law(N, D, U)
if new_l < min_l:
min_l, min_t, min_s = new_l, D, N
return min_l, min_t, min_s
_, min_t, min_s = optimal_allocation(8.67e9, 178e9, 25e9)
print(f"最优配置:{min_t} 令牌,{min_t/25e9} 纪元,{min_s} 参数")
# -> 227B 令牌,9.1 纪元,6.8B 参数
# 我们在图 1 中更极端地测试了“多个纪元,较少参数”的预测
如果你推导出最优分配的闭合形式表达式而不是上述网格搜索,请告知我们 :) 我们使用 utils/parametric_fit.ipynb
中的代码等效于 此 colab 来拟合数据限制的扩展定律和 C4 扩展系数。
下游评估
Rank Eval / 准确性
- 按照
Training
>Regular models
部分中的说明设置训练环境。 - 安装评估工具:
pip install git+https://github.com/EleutherAI/lm-evaluation-harness.git
。我们使用的是0.2.0版本,但是更新的版本应该也可以使用。 - 运行
sbatch utils/eval_rank.sh
,首先修改脚本中的必要变量。 - 运行后,使用
python Megatron-DeepSpeed/tasks/eval_harness/report-to-csv.py outfile.json
将每个文件转换为csv格式。
生成 / Rouge
- 克隆评估工具的
addtasks
分支:git clone -b addtasks https://github.com/Muennighoff/lm-evaluation-harness.git
。 - 设置环境:
cd lm-evaluation-harness; pip install -e ".[dev]"; pip uninstall -y promptsource; pip install git+https://github.com/Muennighoff/promptsource.git@tr13
,即除 promptsource 外的所有需求,promptsource 从一个带有正确提示的 fork 中安装。 - 确保你的检查点路径是 transformers 的检查点路径。
- 运行
sbatch utils/eval_generative.sh
,首先修改脚本中的必要变量。 - 运行后,使用
python utils/merge_generative.py
合并生成的文件,然后用python utils/csv_generative.py merged.json
将其转换为 csv 格式。
bAbI / 精确匹配
- 克隆评估工具的
babi
分支:git clone -b babi https://github.com/Muennighoff/lm-evaluation-harness.git
(请注意,这个分支与生成任务的addtasks
分支不兼容,因为它来源于EleutherAI/lm-evaluation-harness
,而addtasks
是基于bigscience/lm-evaluation-harness
的)。 - 设置环境:
cd lm-evaluation-harness; pip install -e ".[dev]"
。 - 确保你的检查点路径是带有分词器文件的 transformers 检查点(如果你像本文中的所有模型一样训练了一个 gpt2 模型,只需从这里下载文件:https://huggingface.co/gpt2)。
- 运行
sbatch utils/eval_babi.sh
,首先修改脚本中的必要变量。
图表与表格
图表
- 图1:
plotstables/return_alloc.pdf
,plotstables/return_alloc.ipynb
, colab。 - 图2:
plotstables/dataset_setup.pdf
,plotstables/dataset_setup.ipynb
, colab。 - 图3:
plotstables/contours.pdf
,plotstables/contours.ipynb
, colab。 - 图4:
plotstables/isoflops_training.pdf
,plotstables/isoflops_training.ipynb
, colab。 - 图5:
plotstables/return.pdf
,plotstables/return.ipynb
, colab。 - 图6(左):
plotstables/strategies.pdf
,plotstables/strategies.drawio
。 - 图6(右):
plotstables/beyond.pdf
,plotstables/beyond.ipynb
, colab。 - 图7:
plotstables/cartoon.pdf
,plotstables/cartoon.pptx
。 - 图8:
plotstables/isoloss_400m1b5.pdf
& 与图3相同的colab。 - 图9到图11:
plotstables/mup.pdf
,plotstables/dd.pdf
,plotstables/dedup.pdf
,plotstables/mup_dd_dd.ipynb
, colab。 - 图12:
plotstables/isoloss_alphabeta_100m.pdf
& 与图3相同的colab。 - 图13:
plotstables/galactica.pdf
,plotstables/galactica.ipynb
, colab。 - 图14到图17:
training_c4.pdf
,validation_c4oscar.pdf
,training_oscar.pdf
,validation_epochs_c4oscar.pdf
& 与图4相同的colab。 - 图18:
plotstables/perplexity_histogram.pdf
,plotstables/perplexity_histogram.ipynb
。 - 图19到图20:
plotstabls/validation_c4py.pdf
,plotstables/training_validation_filter.pdf
,plotstables/beyond_losses.ipynb
& colab。 - 图21到图39:手册。
表格
- 表1到表3:手册;表1的实验在
utils/parametric_fit.ipynb
中,与此colab 等同。 - 表4到表9:
plotstables/repetition.ipynb
& colab。 - 表10到表11:
plotstables/python.ipynb
& colab。 - 表12:手册。
- 表13到表14:
plotstables/filtering.ipynb
& colab。 - 表15:手册。
许可证
所有模型和代码都使用Apache 2.0许可证。经过筛选的数据集以其来源数据集相同的许可证发布。
引用
@article{muennighoff2023scaling,
title={Scaling Data-Constrained Language Models},
author={Muennighoff, Niklas and Rush, Alexander M and Barak, Boaz and Scao, Teven Le and Piktus, Aleksandra and Tazi, Nouamane and Pyysalo, Sampo and Wolf, Thomas and Raffel, Colin},
journal={arXiv preprint arXiv:2305.16264},
year={2023}
}