从零成功大模型
从零成功大模型-BERT预训练
从零成功大模型-BERT微调
咱们在BERT微调那篇文章中提到,许多NLP义务(如情感剖析和问答)都依赖于高低文了解才干。而像BERT这种双向模型具备较强的高低文了解才干,因此十分适宜用于义务微调,即针对某个详细义务启动微调。
从零成功大模型-GPT2预训练
从零成功大模型-GPT2指令微调
从零成功大模型-GPT2 RLHF
而像GPT这种自回归模型,在预训练成功后会启动一个指令微调环节,用于追随人类指令,而后经过指令去成功不同的义务(翻译,总结)。
那GPT是否像BERT那样,间接微调用于成功某个详细义务呢?只管BERT更适宜,但GPT确实也可以。
当天咱们就基于之前的GPT2预训练模型,经常使用一个渣滓邮件数据集,来微调一个邮件分类模型。
1.渣滓邮件识别
传统ML方法
当然,也可以经过传统的机器学习方法成功渣滓邮件分类,例如,贝叶斯分类,或许基于统计学,事前设定一些敏感词汇,假设邮件中产生了这些敏感词汇,就以为是渣滓邮件。
但传统机器学习方法依赖人类阅历,既然咱们正在写大模型的文章,就得入乡随俗。
咱们经过Embedding成功文本分类,详细来说就是计算邮件内容的Embedding,而后计算“spam”和“none spam”的Embedding,最后经过计算余弦相似度来判别邮件类型。
指令微调模型
其实,还有比计算Embedding更便捷的方法,假设大模型曾经经过预训练、指令微调以及RLHF环节,那么就可以间接应用这种指令追随才干来成功渣滓邮件分类。
例如,咱们结构上方的prompt输入给chatGPT。
"Is the following text 'spam'? Answer with 'yes' or 'no':"" 'You are a winner you have been specially"" selected to receive $1000 cash or a $2000 award.'"
以下是GPT4-o给出的答案,不只准确识别出了渣滓邮件,还遵照了人类指令输入了“yes”。
假设只经常使用预训练模型,没有经过指令微调,前面咱们也测试过,模型只管有输入,但输入只是便捷的拷贝输入。
输入:Is the following text 'spam'? Answer with 'yes' or 'no': 'You are a winner you have been specially selected to receive $1000 cash or a $2000 award.'输入:The following text 'spam'? Answer with 'yes' or 'no': 'You are a winner
2.义务微调
本文完整代码如下,倡导联合代码阅读文本。
在经过Embedding成功文本分类时,Embedding是经过调用openAI的API获取的,其实,这个Embedding也可以看作是GPT模型输入隐形态的一局部。
除了用Embedding计算余弦相似度来成功文分类外,还可以基于隐形态成功一个分类模型,也就是在模型的输入端加一个分类头。
预备数据
训练数据来自地下的渣滓邮件数据集,包含文本和标签两列,标签列中spam代表是渣滓邮件。
由于数据集中渣滓邮件数量少于反常邮件,所以要平衡正负样本数量。
# Examine class distributionsprint(df["Label"].value_counts())
Labelham4825spam747Name: count, dtype: int64
def create_balanced_dataset(df):num_spam = df[df["Label"] == "spam"].shape[0]ham_subset = df[df["Label"] == "ham"].sample(num_spam, random_state=123)balanced_df = pd.concat([ham_subset, df[df["Label"] == "spam"]])return balanced_dfbalanced_df = create_balanced_dataset(df)print(balanced_df["Label"].value_counts())
Labelham747spam747Name: count, dtype: int64
接上去划分训练集,验证机和测试集。
接上去是tokenization,padding或许截断到最大长度。
最后结构Dataloader。
加载预训练模型
加载gpt2预训练模型。
CHOOSE_MODEL = "gpt2-small (124M)"INPUT_PROMPT = "Every effort moves"BASE_CONFIG = {"vocab_size": 50257,# Vocabulary size"context_length": 1024,# Context length"drop_rate": 0.0,# Dropout rate"qkv_bias": True# Query-key-value bias}model_configs = {"gpt2-small (124M)": {"emb_dim": 768, "n_layers": 12, "n_heads": 12},"gpt2-medium (355M)": {"emb_dim": 1024, "n_layers": 24, "n_heads": 16},"gpt2-large (774M)": {"emb_dim": 1280, "n_layers": 36, "n_heads": 20},"gpt2-xl (1558M)": {"emb_dim": 1600, "n_layers": 48, "n_heads": 25},}BASE_CONFIG.update(model_configs[CHOOSE_MODEL])assert train_dataset.max_length <= BASE_CONFIG["context_length"], (f"Dataset length {train_dataset.max_length} exceeds model's context "f"length {BASE_CONFIG['context_length']}. Reinitialize>