Edit model card

Phi2-Chinese-0.2B 从0开始训练自己的Phi2中文小模型

本项目为实验项目,开源代码及模型权重,预训练数据较少,如果需要效果更好的中文小模型,可以参考项目ChatLM-mini-Chinese

Github仓库地址:Phi2-mini-Chinese

1. ⚗️数据清洗

代码:dataset.ipynb
比如句末添加句号、繁体转简体、全角转半角、删除重复的标点符号(比如有些对话语料非常多"。。。。。")等等。
具体的数据清洗过程请参考项目ChatLM-mini-Chinese

2. 🗨️tokenizer训练

代码:tokeinzer.ipynb 本项目使用byte levelBPE分词器。共提供的两种分词器char levelbyte level的训练代码。

训练完的tokenizer记得检查词表中是否有常见的特殊符号,如\t\n等,可以尝试编一句包含特殊字符的文本encodedecode看看能不能还原。如果不包含这些特殊字符,通过add_tokens函数添加。使用len(tokenizer)获取词表大小,tokenizer.vocab_size不统计自己通过add_tokens函数添加的字符。

tokenizer训练非常吃内存:

  • byte level训练1亿个字符至少需要32G内存(其实32G还是不太够,会频繁触发swap),13600k训练时长大概1个小时。

  • char level训练6.5亿个字符(刚好是中文wiki百科的数据量)至少需要32G内存,因为多次触发了swap,实际使用量远不止32G,13600K训练时长约半个小时。

所以大数据集时(GB级别),建议训练tokenizer时从数据集中进行采样。

3. ⛏️CLM因果模型预训练

代码:pretrain.ipynb

用大量文本进行无监督预训练,主要使用bell open source的数据集BELLE

数据集格式:一个样本一句话,太长的可以截断分为多个样本。

CLM预训练过程中,模型输入和输出是一样的,计算交叉熵损失的时候,要错开一位(shift)。

预训练时可以不添加EOSBOS等特殊标记。

4. ⚒️SFT指令微调

代码:sft.ipynb

主要使用bell open source的数据集。感谢大佬BELLE

SFT训练的数据格式如下:

text = f"##提问:\n{example['instruction']}\n##回答:\n{example['output'][EOS]"

模型计算损失时会忽略标记"##回答:"之前的部分("##回答:"也会被忽略),从"##回答:"后面开始。

记得添加EOS句子结束特殊标记,否则模型decode的时候不知道要什么时候停下来。BOS句子开始标记可填可不填。

5. 📝RLHF优化

本项目使用dpo优化方法 代码:dpo.ipynb

根据个人喜好对SFT模型微调,数据集要构造三列promptchosenrejectedrejected这一列有部分数据我是从sft阶段初级模型(比如sft训练4个epoch,取0.5个epoch检查点的模型)生成,如果生成的rejectedchosen相似度在0.9以上,则不要这条数据。

DPO过程中要有两个模型,一个是要训练的模型,一个是参考的模型,在加载的时候其实是同一个模型,只不过参考模型不参与参数更新。

6. 📑本项目模型使用方法

模型权重huggingface仓库:Phi2-Chinese-0.2B

from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig
import torch

device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")

tokenizer = AutoTokenizer.from_pretrained('charent/Phi2-Chinese-0.2B')
model = AutoModelForCausalLM.from_pretrained('charent/Phi2-Chinese-0.2B').to(device)


txt = '感冒了要怎么办?'
prompt = f"##提问:\n{txt}\n##回答:\n"

# greedy search
gen_conf = GenerationConfig(
    num_beams=1,
    do_sample=False,
    max_length=320,
    max_new_tokens=256,
    no_repeat_ngram_size=4,
    eos_token_id=tokenizer.eos_token_id,
    pad_token_id=tokenizer.pad_token_id,
)

tokend = tokenizer.encode_plus(text=prompt)
input_ids, attention_mask = torch.LongTensor([tokend.input_ids]).to(device), \
    torch.LongTensor([tokend.attention_mask]).to(device)

outputs = model.generate(
    inputs=input_ids,
    attention_mask=attention_mask,
    generation_config=gen_conf,
)

outs = tokenizer.decode(outputs[0].cpu().numpy(), clean_up_tokenization_spaces=True, skip_special_tokens=True,)
print(outs)
##提问:
感冒了要怎么办?
##回答:
感冒是由病毒引起的,感冒一般由病毒引起,以下是一些常见感冒的方法:
- 洗手,特别是在接触其他人或物品后。
- 咳嗽或打喷嚏时用纸巾或手肘遮住口鼻。
- 用手触摸口鼻,特别是喉咙和鼻子。
- 如果咳嗽或打喷嚏,可以用纸巾或手绢来遮住口鼻,但要远离其他人。
- 如果你感冒了,最好不要触摸自己的眼睛、鼻子和嘴巴。
- 在感冒期间,最好保持充足的水分和休息,以缓解身体的疲劳。
- 如果您已经感冒了,可以喝一些温水或盐水来补充体液。
- 另外,如果感冒了,建议及时就医。

7、🎓引用

如果你觉得本项目对你有所帮助,欢迎引用。

@misc{Charent2023,
    author={Charent Chen},
    title={A small Chinese causal language model with 0.2B parameters base on Phi2},
    year={2023},
    publisher = {GitHub},
    journal = {GitHub repository},
    howpublished = {\url{https://github.com/charent/Phi2-mini-Chinese}},
}

8、🤔其他事项

本项目不承担开源模型和代码导致的数据安全、舆情风险或发生任何模型被误导、滥用、传播、不当利用而产生的风险和责任。

Downloads last month
37
Safetensors
Model size
194M params
Tensor type
F32
·
Inference Examples
This model does not have enough activity to be deployed to Inference API (serverless) yet. Increase its social visibility and check back later, or deploy to Inference Endpoints (dedicated) instead.

Dataset used to train charent/Phi2-Chinese-0.2B