GPT1:语言理解 + 分类任务(fine-tuning) GPT2:语言生成 GPT2没有微调了,都是预训练

由于GPT-2不需要进行微调便可以用于后续任务,因此需要对其他任务的输入进行处理。以文本分类为例,仍然使用与GPT-1相同的数据集。把新闻标题和类别标签组合在一起:​“2030年的未来科技预测:20项技术改变世界|科技”​。用“|”分隔新闻标题和类别标签,从而将文本分类问题转化为语言模型问题。GPT-2的训练代码与GPT-1的类似,只是少了微调阶段。预测阶段只需要将概率最大的词作为Softmax的输出即可。

 

class GPT2(tf.keras.Model):
       def __init__(self, n_layers, d_model, n_heads, diff, target_vocab_size,
                  max_seq_len, drop_rate=0.1):
          super(GPT2, self).__init__()
          self.decoder = Decoder(n_layers, d_model, n_heads, diff,
                             target_vocab_size, max_seq_len, drop_rate)
          self.final_layer = tf.keras.layers.Dense(target_vocab_size)
       def call(self, targets, training, look_ahead_mask):
          decode_out, att_weights = self.decoder(targets, training, look_ahead_mask)
          final_out = self.final_layer(decode_out)
          return final_out, att_weights


# 定义优化器
    learing_rate = CustomSchedule(d_model)
    optimizer = tf.keras.optimizers.Adam(learing_rate, beta_1=0.9,
                                   beta_2=0.98, epsilon=1e-9)
    # 定义目标函数和评估指标
    loss_object = tf.keras.losses.SparseCategoricalCrossentropy(
           from_logits=True, reduction='none')
    train_loss = tf.keras.metrics.Mean(name='train_loss')
    train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')
    # 定义GPT-2模型
    gpt2 = GPT2(num_layers, d_model, num_heads, dff, target_vocab_size,
          max_seq_len, dropout_rate)
    # 定义训练过程
    def train_step(targets):
       tar_inp = targets[:, :-1]
       tar_real = targets[:, 1:]
       # 构造掩码
       combined_mask = create_mask(tar_inp)
       with tf.GradientTape() as tape:
          predictions, _ = gpt2(tar_inp, True, combined_mask)
          loss = loss_fun(tar_real, predictions)
       # 求梯度
       gradients = tape.gradient(loss, gpt2.trainable_variables)
       # 反向传播
       optimizer.apply_gradients(zip(gradients, gpt2.trainable_variables))
       # 记录损失值和准确率
       train_loss(loss)
       train_accuracy(tar_real, predictions)
    # 开始训练
    for epoch in range(EPOCHS):
       # 重置记录项
       train_loss.reset_states()
       train_accuracy.reset_states()
       for batch, all_inputs in enumerate(train_dataset):
          # 训练
          train_step(all_inputs)


		  
# 实现预测功能
    def predict_func(inp_sentence):
       start_token = [tokenizer_title.vocab_size]
       end_token = [tokenizer_title.vocab_size + 1]
       # 增加开始和结束标记
       inp_sentence = start_token + tokenizer_title.encode(inp_sentence) + end_token
       encoder_input = tf.expand_dims(inp_sentence, 0)
       decoder_input = [tokenizer_title.vocab_size]
       output = tf.expand_dims(decoder_input, 0)
       for i in range(MAX_LENGTH):
          combined_mask = create_mask(encoder_input)
          predictions, _ = gpt2(encoder_input, False, combined_mask)
          # 从seq_len维度选择最后一个词
          predictions = predictions[: ,-1:, :]  # (batch_size, 1, vocab_size)
          predicted_id = tf.cast(tf.argmax(predictions, axis=-1), tf.int32)
          # 如果predicted_id等于结束标记,就返回结果
          if predicted_id == tokenizer_title.vocab_size + 1:
             return tf.squeeze(encoder_input, axis=0)
          # 连接predicted_id与输出,作为解码器的输入传递到解码器
          encoder_input = tf.concat([encoder_input, predicted_id], axis=-1)
          output = tf.concat([output, predicted_id], axis=-1)
       return tf.squeeze(encoder_input, axis=0)
    # 解码过程
    def translate(sentence, plot=''):
       result = evaluate(sentence)
       predicted_sentence = tokenizer_title.decode(
              [i for i in result if i < tokenizer_title.vocab_size])
       predicted_sentence = predicted_sentence.replace(" ", "")
       sentence = sentence.replace(" ", "")
       print('输入: {}'.format(sentence))
       print('预测输出: {}'.format(predicted_sentence))
    # 测试用例
    translate("请将下面文本分类:吃什么食物,可以降低血压?")
    print("============================")
    真实数据:吃什么食物,可以降低血压?|健康
    输入:吃什么食物,可以降低血压?
    预测输出:吃什么食物,可以降低血压?|健康


s = " ".join(list(jieba.cut("续写:今天是个好天气")))
    translate(s)
    print("============================")
    s = " ".join(list(jieba.cut("续写:未来10年最伟大的发明")))
    translate(s)
    print("============================")
    s = " ".join(list(jieba.cut("续写:深度学习和机器学习相比,主要区别是")))
    translate(s)
    print("============================")
    输入: 今天是个好天气
    预测输出: 今天是个好天气,适合出去散步或者在户外放松心情。
    ============================
    输入: 未来10年最伟大的发明
    预测输出: 未来10年最伟大的发明可能是全面的可再生能源系统。
    ============================
    输入: 深度学习和机器学习相比,主要
    预测输出: 深度学习和机器学习相比,主要区别在于其模型的复杂性和特征学习的方式。
	

  

 

你现在实际上已经实现了两个非常重要的概念化版本:
👉 一个是 GPT‑like 模型用于分类任务(GPT1),
👉 一个是 GPT‑like 模型用于文本生成任务(GPT2)。

它们虽然名字相似,但在设计意图、训练目标与使用方式上有本质区别。
我们来做一个深入又直观的对比和关联分析 👇


🧩 一、总体定位对比

表格
 
模型GPT1 类GPT2 类
设计目标 语言理解 + 分类任务(fine-tuning) 语言生成(text generation)
模型结构 Decoder 堆叠 + 分类头 Decoder 堆叠(纯语言模型)
输出层 词预测+分类输出 仅词预测(下一个token)
训练目标 语言建模 + 文本分类联合loss 自回归语言建模loss
应用场景 分类任务(如新闻分类、领域识别) 生成任务(如补全文本、续写)

🧠 二、架构上的异同点

✅ 相同点

两者都基于 Transformer Decoder(GPT 核心结构):

  • 由多层 Masked Multi‑Head Attention + FeedForward + LayerNorm 堆叠组成;
  • 都使用掩码(look‑ahead mask)防止模型看到未来词;
  • 都是自回归结构:P(x_t | x_<t)
  • 都具有位置编码、词嵌入等组件。

→ 所以你可以理解为:GPT1 和 GPT2 拥有相同的基石(Decoder Block 结构),
区别在于 输出头(head) 和 任务目标(objective)。


🔄 不同点

表格
 
模块GPT1 实现GPT2 实现
输出层 两个输出:词预测 Dense + 分类 Dense 一个输出:词预测 Dense
任务类型 联合任务(语言建模 + 分类) 纯语言建模(自回归预测)
训练数据 可能包括文本及其分类标签 仅文本数据(无标签)
Loss 设计 loss_fun + loss_fun_fine_tuning 单一 loss_fun
微调方式 特化为分类任务 专注生成(可后续加头 fine-tune)
推理方式 输入 → 分类预测 输入 → 续写输出
输出行为 “预测是哪个类别” “继续写下去”

📚 三、从 GPT1 到 GPT2 的演化关系

真正意义上,OpenAI 的 GPT 系列演化如下:

  • GPT‑1 (2018):用于语言建模 + 下游任务微调;
  • GPT‑2 (2019):增加规模,仅使用语言建模目标(无监督预训练),发现可以零样本学习;
  • GPT‑3 / ChatGPT:扩展参数量 + RLHF + 强化互动。

你写的 GPT1/GPT2 模型,其思想完全吻合这个演进路线:

表格
 
阶段你的实现含义对应真实 GPT 阶段
GPT1 自回归 + 下游任务联合训练 GPT‑1 (联合任务微调)
GPT2 自回归纯语言模型 GPT‑2 (通用预训练大模型)

所以:

你的 GPT1 可以看作一个“小型 GPT1 模型”做分类任务的微调版本,
而 GPT2 则是一个“纯语言生成版本”,更接近真实 GPT‑2。


🔍 四、训练与推理的核心区别

🧩 GPT1

python
 
predictions, predict_fine_tuning, _ = gpt1(tar_inp, True, combined_mask)
  • predictions → 预测下一个词
  • predict_fine_tuning → 分类结果(通过 Flatten + Dense)
  • 模型训练时,会联合优化语言建模 loss 与 分类 loss。

推理时:

python
 
predict_func() + get_cat_name()

→ 输入一句话,输出类别(如 “美食”“科技”)。


🧩 GPT2

python
 
predictions, _ = gpt2(tar_inp, True, combined_mask)
  • 只预测下一个 token;
  • 没有分类分支;
  • 通过循环生成实现"续写"。

推理时:

python
 
translate("续写:未来10年最伟大的发明")

→ 模型逐词预测,串接成完整句子。


✨ 五、可以如何结合使用

你目前其实已经具备了完整 GPT 系列的两个阶段:

表格
 
模块作用
GPT2 通用语言生成(相当于预训练阶段)
GPT1 在预训练模型基础上添加分类任务头(相当于微调阶段)

💡 如果想让 GPT1 真正用到 "预训练知识",你可以:

  1. 先训练好 GPT2
  2. 把 GPT2.decoder 的权重加载到 GPT1.decoder
  3. 再训练分类任务。

这就构成了一个完整的 GPT‑式训练流程(类 GPT‑1 → GPT‑2 → fine‑tune)。


🧭 六、核心总结

表格
 
对比维度GPT1GPT2
任务类型 下游任务(分类) 语言建模(生成)
Loss 语言建模 + 分类联合 语言建模
输出层 两个(token预测 + 分类) 一个(token预测)
应用示例 “新闻分类: 文化/科技/美食” “续写文本: 今天是个好天气…”
是否真正“预训练” 否(自定义任务训练) 是(可以大规模训练)
对应 OpenAI GPT‑1 概念 GPT‑2 概念

posted @ 2025-11-18 12:03  bonelee  阅读(6)  评论(0)    收藏  举报