基础认知
为什么用
我们做AI应用开发,可能不太需要去做大模型的预训练,但是模型微调还是离不开的。那什么是模型微调呢?
类似于"站在巨人肩膀上"——预训练模型通过海量数据已学习通用知识(如语言规律、图像特征),微调则像 针对性补习,用少量高质量数据让模型掌握专业场景的特殊技能,最终适应特定任务,如情感分析、命名实体识别等。
Hugging Face
那么问题来了,模型微调的“模型”怎么来的呢?世面上那么多模型,我们去哪找呢? 这里有这样一个网站:Hugging Face(需要tz且节点最好在老美)
我们这里需要关注的是两个:
- Models:模型库
进入模型库,可按需找自己需要的模型:
我们继续进入一个模型的详情页,这里以gpt2-chinese为例:
我们程序员是不看着挺眼熟,你没有看错,就是挺像gitHub的。或者换句话说,Hugging Face就是AI大模型领域的“gitHub”。
- Datasets:公开数据集
这里提供很多可以用于各个领域训练的公开数据。
ModelScope
Hugging Face需要tz才能访问。除了Hugging Face外,国内还有一个平台提供模型和公开数据集的下载:ModelScope
这里Hugging Face就像gitHub,ModelScope就像是Gitee。没有tz环境的可以使用后者。 但是这里📢📢📢:ModelScope资源不如Hugging Face,当ModelScope找不到目标模型时可以试试Hugging。
我们今天以Hugging Face为例,ModelScope就象征性地讲这么多。
撸起袖子就是Coding
工欲善其事
使用Hugging Face,本地需要以下环境:
-
python。Hugging Face生态的官方编程语言,提供统一的API接口和丰富的包管理生态。
- 可以从Python官方网站下载并安装。
-
anacoda。解决Python包版本冲突和环境隔离问题,特别适合需要同时维护多个项目不同版本依赖的AI开发场景
- 下载地址: Anaconda官网
-
PyTorch(或TensorFlow)。模型的计算引擎,提供张量计算和自动微分能力,是模型训练和推理的数学基础。Hugging Face的Transformers库底层完全依赖这些框架的神经网络模块
- 通过pip安装:
pip install torch torchvision torchaudio
- 通过Conda安装:
conda install pytorch torchvision torchaudio cpuonly -c pytorch
4. pycharm。python开发官方IDE,非必选也可使用VSCode等。 * 下载地址: PyCharm官网
- Hugging Face Token。我们本地连接github也需要一个Token的东西,Hugging Face也一样。
- 需要注册账号,支持国内邮箱注册(🌰QQ)
- 登录后,按如下步骤获取。📢📢📢:注意红色文字注意事项!!!
模型API调用
网上看到可以API访问Hugging Face,这里我怎么试都没有成功(目前报404)。大家有成功的可以赐教下。
import requests
#使用Token访问在线模型
API_URL = "https://router.huggingface.co/models/uer/gpt2-chinese-cluecorpussmall"
API_TOKEN = "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"
headers = {"Authorization": f"Bearer {API_TOKEN}"}
response = requests.post(API_URL,headers=headers,json={"inputs":"你好,Hugging face"})
模型下载
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.models.auto.configuration_auto import model_type_to_module_name
# 将模型和分词器下载到本地使用,指定保存路径
model_name = "bert-base-chinese"
cache_dir = "./model/bert-base-chinese"
# 下载模块
AutoModelForCausalLM.from_pretrained(model_name, cache_dir=cache_dir)
# 下载分词工具
AutoTokenizer.from_pretrained(model_name, cache_dir=cache_dir)
print(f"模型已经下载到:{cache_dir}")
简单介绍下几个核心模块:
- AutoModelForCausalLM:作为因果语言建模(Causal Language Modeling)任务的专用接口,基于Transformer解码器架构,实现自回归文本生成
- AutoTokenizer:文本预处理管道的统一抽象层,其核心作用是将人类可读的自然语言文本与模型理解的数字表示(Token ID)进行双向转换
AutoXXX,一般是通用接口,提供模型无关的加载方式。以我们这里的bert模型为例,其还有专用实现。
- lBertModel
- BertTokenizer
一般开发中使用AutoXXX的通用实现即可,你的项目高度稳定,明确只使用BERT架构,并且你希望代码的意图非常清晰明确,那么直接使用BertModel是很好的选择。
模型认知
整体目录:
Config文件:
{
"activation_function": "gelu_new",
"architectures": [
"GPT2LMHeadModel"
],
"attn_pdrop": 0.1,
"embd_pdrop": 0.1,
"gradient_checkpointing": false,
"initializer_range": 0.02,
"layer_norm_epsilon": 1e-05,
"model_type": "gpt2",
"n_ctx": 1024,
"n_embd": 768,
"n_head": 12,
"n_inner": null,
"n_layer": 12,
"n_positions": 1024,
"output_past": true,
"resid_pdrop": 0.1,
"task_specific_params": {
"text-generation": {
"do_sample": true,
"max_length": 320
}
},
"tokenizer_class": "BertTokenizer",
"vocab_size": 21128
}
这里主要注意一个概念:
- vocab_size,模型字典大小。我们可以在vocab.txt中看到其容量正好是vocab_size的值:21128。
Tokenizer原理
-
归一化器(Normalizer) :负责文本清洗和标准化,如统一转为小写、Unicode规范化、清理多余空格。例如,将
"HELLO World"规范为"hello world"。 -
预分词器(Pre-tokenizer) :根据简单规则(如空格、标点)进行初步切分,将文本划分为粗粒度片段。例如,将
"hello world"切分为["hello", " world"]。 -
模型(Model) :这是核心算法层,负责将预切分后的片段进一步细化为最终的子词(Subword)Token。主流算法包括BPE、WordPiece和Unigram。
-
后处理器(Post-processor) :添加模型所需的特殊Token,如序列开始(
<s>)、序列结束(</s>)、填充([PAD])等,构建出模型期待的输入格式。 -
解码器(Decoder) :是编码的逆过程,负责将Token ID序列还原回连贯的文本,并智能地合并子词(如将
"play"和"##ing"合并为"playing")。
模型本地调用
# 本地调用GPT2
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline, AutoConfig
# 设置模型路径,必须是绝对路径
model_dir = r"/Users/chaors/Development/AIProjects/helloHuggingFace/model/uer/gpt2-chinese-cluecorpussmall/models--uer--gpt2-chinese-cluecorpussmall/snapshots/c2c0249d8a2731f269414cc3b22dff021f8e07a3"
# 配置设置,不设置报错:The tied weights mapping and config for this model specifies to tie transformer.wte.weight to lm_head.weight, but both are present in the checkpoints, so we will NOT tie them.
config = AutoConfig.from_pretrained(model_dir)
config.tie_word_embeddings = False
# 加载模型和分词器
model = AutoModelForCausalLM.from_pretrained(model_dir,config=config)
tokenizer = AutoTokenizer.from_pretrained(model_dir)
# model = AutoModelForCausalLM.from_pretrained(model_dir,config=config, trust_remote_code=True)
# tokenizer = AutoTokenizer.from_pretrained(model_dir, trust_remote_code=True)
# 创建生成文本的pipeline
generator = pipeline("text-generation", model=model, tokenizer=tokenizer)
# 生成文本
# output = generator("你好,我是一款语言模型,",max_length=50,num_return_sequences=1)
output = generator(
"天气有点阴沉,猴哥走在水坑里,",#生成文本的输入种子文本(prompt)。模型会根据这个初始文本,生成后续的文本
max_new_tokens=30,#指定生成文本的最大长度。这里的 50 表示生成的文本最多包含 50 个标记(tokens)
num_return_sequences=1,#参数指定返回多少个独立生成的文本序列。值为 1 表示只生成并返回一段文本。
truncation=True,#该参数决定是否截断输入文本以适应模型的最大输入长度。如果 True,超出模型最大输入长度的部分将被截断;如果 False,模型可能无法处理过长的输入,可能会报错。
temperature=0.7,#该参数控制生成文本的随机性。值越低,生成的文本越保守(倾向于选择概率较高的词);值越高,生成的文本越多样(倾向于选择更多不同的词)。0.7 是一个较为常见的设置,既保留了部分随机性,又不至于太混乱。
top_k=50,#该参数限制模型在每一步生成时仅从概率最高的 k 个词中选择下一个词。这里 top_k=50 表示模型在生成每个词时只考虑概率最高的前 50 个候选词,从而减少生成不太可能的词的概率。
top_p=0.6,#该参数(又称为核采样)进一步限制模型生成时的词汇选择范围。它会选择一组累积概率达到 p 的词汇,模型只会从这个概率集合中采样。top_p=0.9 意味着模型会在可能性最强的 90% 的词中选择下一个词,进一步增加生成的质量。
clean_up_tokenization_spaces=True#该参数控制生成的文本中是否清理分词时引入的空格。如果设置为 True,生成的文本会清除多余的空格;如果为 False,则保留原样。默认值即将改变为 False,因为它能更好地保留原始文本的格式。
)
print(output)
print(model)
简单介绍下几个核心模块:
- pipeline,任务流管理器。根据任务名(如
"text-generation")自动组装并管理整个工作流。
运行警告
这里可以运行,但是有警告⚠️:
- generat显式生成参数的调用模式已被标记为废弃
- max_new_tokens与max_length参数同时设置时的优先级冲突,max_new_tokens优先级更高
- 等等之类都是新范式不兼容的警告,一一按提示处理即可
# 新的参数传递范式
# 创建明确的生成配置
generation_config = GenerationConfig(
max_new_tokens=30,#指定生成文本的最大长度。这里的 50 表示生成的文本最多包含 50 个标记(tokens)
num_return_sequences=1, # 参数指定返回多少个独立生成的文本序列。值为 1 表示只生成并返回一段文本。
truncation=True, # 该参数决定是否截断输入文本以适应模型的最大输入长度。如果 True,超出模型最大输入长度的部分将被截断;如果 False,模型可能无法处理过长的输入,可能会报错。
temperature=1.0,
# 该参数控制生成文本的随机性。值越低,生成的文本越保守(倾向于选择概率较高的词);值越高,生成的文本越多样(倾向于选择更多不同的词)。0.7 是一个较为常见的设置,既保留了部分随机性,又不至于太混乱。
top_k=50, # 该参数限制模型在每一步生成时仅从概率最高的 k 个词中选择下一个词。这里 top_k=50 表示模型在生成每个词时只考虑概率最高的前 50 个候选词,从而减少生成不太可能的词的概率。
top_p=0.6, # 该参数(又称为核采样)进一步限制模型生成时的词汇选择范围。它会选择一组累积概率达到 p 的词汇,模型只会从这个概率集合中采样。top_p=0.9 意味着模型会在可能性最强的 90% 的词中选择下一个词,进一步增加生成的质量。
clean_up_tokenization_spaces=True, # 该参数控制生成的文本中是否清理分词时引入的空格。如果设置为 True,生成的文本会清除多余的空格;如果为 False,则保留原样。默认值即将改变为 False,因为它能更好地保留原始文本的格式。
do_sample=True # 新版本temperature、top_p等采样参数需要与do_sample=True配合使用,否则被视为无效
)
# 2. 将文本编码为张量(关键步骤!)
input_text = "天气有点阴沉,猴哥走在水坑里,"
inputs = tokenizer(input_text, return_tensors="pt") # 返回PyTorch张量
output = model.generate(**inputs, generation_config=generation_config) # # 解包字典:input_ids=inputs['input_ids'], attention_mask=inputs['attention_mask']
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
至此,我们的第一个简单的Hugging Face程序就大功告成了。从此为后续的微调打下了坚实的基础。