从零开始构建GPT风格的LLM分类器 微调GPT模型进行垃圾邮件分类

news2024/9/24 14:47:03

在这篇文章中,我想向您展示如何将预训练的大型语言模型(LLM)转变为强大的文本分类器。

为什么专注于分类?

首先,将预训练模型微调为分类器提供了一种温和而有效的微调入门方式。其次,许多现实世界和商业挑战都与文本分类有关:垃圾邮件检测、情感分析、客户反馈分类、主题标注等等。

将GPT模型转变为文本分类器

书籍分享:《从零开始构建大型语言模型》已经由Manning出版社出版。这本书会引导你完成整个过程,从实现数据输入到用指令数据进行微调。在你阅读完这本书后,你会对LLM的工作原理有深刻、详细和全面的理解。

本文将涵盖的内容

为了庆祝新书发布,我将分享其中一个章节的节选,带领你了解如何将预训练的LLM微调为垃圾邮件分类器。

重要提示

关于分类微调的章节长达35页——对一篇文章来说太长了。因此,在这篇文章中,我将集中在一个约10页的子集,介绍分类微调的背景和核心概念。

此外,我还将分享一些不包含在书中的额外实验见解,并回答读者可能有的常见问题。(请注意,下面的节选基于我的个人草稿,未经过Manning的专业文本编辑和最终图形设计。)

该节选的完整代码可以在GitHub上找到。

https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb

此外,我还会解答你关于训练LLM分类器的7个问题:

  1. 我们需要训练所有层吗?

  2. 为什么微调最后一个token,而不是第一个token?

  3. BERT在性能上与GPT相比如何?

  4. 是否应该禁用因果掩码?

  5. 增加模型规模会带来什么影响?

  6. LoRA能带来哪些改进?

  7. 使用填充或不填充?

这本《从零开始构建大型语言模型》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

PDF书籍: 完整版本链接获取

👉[CSDN大礼包🎁:《从零开始构建大型语言模型》免费分享(安全链接,放心点击)]👈

不同类别的微调

最常见的语言模型微调方法是指令微调和分类微调。指令微调通过对模型进行特定任务的训练,提升它理解和执行自然语言提示中描述任务的能力,如下图1所示。图1:指令微调的两种场景。上方模型的任务是判断文本是否为垃圾邮件;下方模型的任务是将英文句子翻译成德语。

下一章将讨论指令微调,如上图1所示。而本章将集中于分类微调。如果你有机器学习背景,可能对这个概念已经很熟悉了。

在分类微调中,模型被训练来识别特定的类别标签,如“垃圾邮件”和“非垃圾邮件”。分类任务不仅限于大型语言模型和电子邮件过滤;它还包括从图像中识别不同的植物物种、将新闻文章分类为体育、政治或科技等主题,或者在医学成像中区分良性和恶性肿瘤。

关键的一点是,分类微调模型只能预测它在训练中遇到的类别。例如,它可以判断某文本是“垃圾邮件”还是“非垃圾邮件”,但除此之外无法提供更多信息,如下图2所示。图2:一个使用LLM进行垃圾邮件分类的示例。与指令微调模型不同,这类模型不需要附带额外的指令,只能返回“垃圾邮件”和“非垃圾邮件”。

与图2所示的分类微调模型不同,指令微调的模型通常能够执行更广泛的任务。可以将分类微调的模型视为高度专业化的模型,一般来说,开发一个专用模型比开发一个在各种任务上表现良好的通用模型更容易。

选择合适的微调方法

指令微调提高了模型基于特定用户指令理解和生成响应的能力。它适用于需要处理各种任务的模型,改善了模型的灵活性和交互质量。而分类微调则适用于需要精确将数据分类到预定义类别中的项目,如情感分析或垃圾邮件检测。

虽然指令微调更为通用,但它需要更大的数据集和更多的计算资源来开发能够在各种任务中表现出色的模型。而分类微调需要的数据和计算资源较少,但其使用范围局限于模型已经训练过的特定类别。

使用预训练权重初始化模型

因为这是节选内容,我们将跳过数据准备和模型初始化部分,这些内容已经在前几章中实现和预训练完成。与阅读实体书相比,阅读长篇幅的数字文章会更难保持注意力。因此,我会尽量将本文紧紧围绕该章的一个关键内容。

为了提供一些上下文,本节内容集中于将通用的预训练LLM转变为专用LLM用于分类任务所需的修改,如下图3所示。图3:本文跳过步骤1-5,直接进入步骤6(将在下一节开始)。

在进入图3中提到的LLM修改之前,先简要回顾一下我们正在使用的预训练LLM。

为了简单起见,我们假设代码已经设置好以加载模型,如下所示:

model = GPTModel(BASE_CONFIG)
load_weights_into_gpt(model, params)
model.eval()  

在将模型权重加载到GPTModel后,我们使用前几章中的文本生成工具函数来确保模型生成连贯的文本:

from chapter04 import generate_text_simple
from chapter05 import text_to_token_ids, token_ids_to_text

text_1 = "Every effort moves you"

token_ids = generate_text_simple(
    model=model,
    idx=text_to_token_ids(text_1, tokenizer),
    max_new_tokens=15,
    context_size=BASE_CONFIG["context_length"]
)

print(token_ids_to_text(token_ids, tokenizer)) 

如我们从以下输出中看到,模型生成了连贯的文本,这表明模型权重已正确加载:

Every effort moves you forward.
The first step is to understand the importance of your work

在开始将模型微调为垃圾邮件分类器之前,让我们看看模型是否已经能够通过提示指令来分类垃圾邮件:

text_2 = (
    "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.'"
)

token_ids = generate_text_simple(
    model=model,
    idx=text_to_token_ids(text_2, tokenizer),
    max_new_tokens=23,
    context_size=BASE_CONFIG["context_length"]
)

print(token_ids_to_text(token_ids, tokenizer))

模型输出如下:

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

从输出中可以看出,模型在执行指令时有些挣扎。

这是可以预料的,因为它只经过了预训练,缺乏指令微调。我们将在后续章节中探讨指令微调。

添加分类头

在这一部分,我们将修改预训练的大型语言模型,准备进行分类微调。为此,我们将原始的输出层(将隐藏表示映射到50257个唯一词汇的词表)替换为较小的输出层,映射到两个类别:0(“非垃圾邮件”)和1(“垃圾邮件”),如下图4所示。图4:将GPT模型用于垃圾邮件分类时修改其架构。最初模型的线性输出层将768个隐藏单元映射到50257个词汇。为了进行垃圾邮件检测,这一层被替换为新的输出层,将相同的768个隐藏单元映射到两个类别:“垃圾邮件”和“非垃圾邮件”。

如上图4所示,除了替换输出层之外,我们使用与前几章相同的模型。

输出层节点

技术上,我们可以只使用一个输出节点,因为这是一个二元分类任务。然而,这需要修改损失函数,正如在附录B参考部分的文章中讨论的。因此,我们选择更通用的方法,即输出节点的数量与类别数匹配。例如,对于一个三类问题(如将新闻文章分类为“科技”、“体育”或“政治”),我们将使用三个输出节点。

在尝试图4中所示的修改之前,让我们通过print(model)来打印模型架构,输出如下:

GPTModel(
  (tok_emb): Embedding(50257, 768)
  (pos_emb): Embedding(1024, 768)
  (drop_emb): Dropout(p=0.0, inplace=False)
  (trf_blocks): Sequential(
...
    (11): TransformerBlock(
      (att): MultiHeadAttention(
        (W_query): Linear(in_features=768, out_features=768, bias=True)
        (W_key): Linear(in_features=768, out_features=768, bias=True)
        (W_value): Linear(in_features=768, out_features=768, bias=True)
        (out_proj): Linear(in_features=768, out_features=768, bias=True)
        (dropout): Dropout(p=0.0, inplace=False)
      )
      (ff): FeedForward(
        (layers): Sequential(
          (0): Linear(in_features=768, out_features=3072, bias=True)
          (1): GELU()
          (2): Linear(in_features=3072, out_features=768, bias=True)
        )
      )
      (norm1): LayerNorm()
      (norm2): LayerNorm()
      (drop_resid): Dropout(p=0.0, inplace=False)
    )
  )
  (final_norm): LayerNorm()
  (out_head): Linear(in_features=768, out_features=50257, bias=False)
)

上面展示了我们在第4章中实现的架构。正如第4章讨论的那样,GPTModel包含嵌入层,接着是12个相同的transformer块(只展示了最后一个块以简洁为主),之后是最终的LayerNorm层和输出层out_head

接下来,我们将out_head替换为图4所示的新输出层,并对其进行微调。

微调选定层与所有层

由于我们从一个预训练模型开始,因此没有必要微调所有模型层。因为基于神经网络的语言模型的低层通常捕获基本的语言结构和语义,这些结构和语义适用于广泛的任务和数据集。因此,只需微调最后的层(靠近输出的层),这些层更侧重于细微的语言模式和任务特定的特征,通常就足以将模型适应新任务。一个附带的好处是,只微调少量层在计算上更高效。感兴趣的读者可以在本章附录B的参考部分找到更多信息和实验,了解应微调哪些层。

为了准备进行分类微调,首先我们冻结模型,即将所有层设置为不可训练:

for param in model.parameters():
    param.requires_grad = False

然后,如图4所示,我们替换输出层model.out_head,该层最初将输入层映射为50257维(词汇大小):

torch.manual_seed(123)

num_classes = 2

model.out_head = torch.nn.Linear(
    in_features=BASE_CONFIG["emb_dim"],
    out_features=num_classes
)

注意,在上述代码中,我们使用了BASE_CONFIG["emb_dim"],它在“gpt2-small(124M)”模型中等于768,以保持下面的代码更加通用。这意味着我们也可以使用相同的代码来处理更大的GPT-2模型变体。

新的model.out_head输出层的requires_grad属性默认设置为True,这意味着这是模型中唯一会在训练期间更新的层。

技术上,只训练刚才添加的输出层就足够了。然而,正如我在实验中发现的那样,微调额外的层可以显著提高微调模型的预测性能。(有关更多详细信息,请参阅附录C中的参考文献。)

此外,我们还将最后一个transformer块和连接此块到输出层的最终LayerNorm模块设置为可训练的,如下图5所示。图5:我们之前开发并加载的GPT模型包含12个重复的transformer块。除了输出层之外,我们还将最终LayerNorm层和最后一个transformer块设置为可训练,而其余11个transformer块和嵌入层保持不可训练状态。

为了使图5中所示的最终LayerNorm层和最后一个transformer块可训练,我们将它们的requires_grad设置为True:

for param in model.trf_blocks[-1].parameters():
    param.requires_grad = True

for param in model.final_norm.parameters():
    param.requires_grad = True

即使我们添加了一个新的输出层,并将某些层设置为可训练或不可训练,我们仍然可以像前几章一样使用这个模型。例如,我们可以将一个示例文本输入该模型,如下所示:

inputs = tokenizer.encode("Do you have time")
inputs = torch.tensor(inputs).unsqueeze(0)

print("Inputs:", inputs)
print("Inputs dimensions:", inputs.shape)

输出如下所示:

Inputs: tensor([[5211,  345,  423,  640]])
Inputs dimensions: torch.Size([1, 4])

然后,我们可以将编码后的token ID传递给模型:

with torch.no_grad():
    outputs = model(inputs)

print("Outputs:\n", outputs)
print("Outputs dimensions:", outputs.shape)

输出tensor如下:

Outputs:
 tensor([[[-1.5854,  0.9904],
          [-3.7235,  7.4548],
          [-2.2661,  6.6049],
          [-3.5983,  3.9902]]])
Outputs dimensions: torch.Size([1, 4, 2])

在第4章和第5章中,相似的输入会产生一个形状为[1, 4, 50257]的输出tensor,其中50257表示词汇大小。与前几章一样,输出行的数量对应于输入tokens的数量(在本例中为4个)。然而,由于我们替换了模型的输出层,每个输出的嵌入维度(列数)现在减少为2,而不是50257。

记住,我们的目标是微调此模型,使其返回一个类标签,用以指示模型输入是垃圾邮件还是非垃圾邮件。为此,我们不需要微调所有4个输出行,而可以专注于单个输出token。特别是,我们将专注于最后一行,对应于最后一个输出token,如下图6所示。图6:GPT模型的4个token示例输入和输出的示意图。输出tensor包含2列,由于输出层的修改。我们在微调模型进行垃圾邮件分类时只关注最后一行对应的最后一个token。

要从输出tensor中提取图6所示的最后一个输出token,我们可以使用以下代码:

print("Last output token:", outputs[:, -1, :])

输出如下:

Last output token: tensor([[-3.5983,  3.9902]])

在进入下一节之前,让我们回顾一下我们的讨论。我们将重点放在将这些值转换为类标签预测。但首先,让我们理解为什么我们特别关注最后一个输出token,而不是第1、第2或第3个。

在第3章中,我们探讨了注意力机制,它在每个输入token与所有其他输入token之间建立关系。随后,我们引入了因果注意力掩码的概念,通常用于GPT风格的模型。该掩码限制了token只能关注当前及之前的位置,确保每个token只能受自身和前面的token影响,如下图7所示。
图7:因果注意力机制的示意图。显示了输入tokens之间的注意力得分矩阵。空白单元格表示由于因果注意力掩码而屏蔽的部分,防止tokens关注未来的tokens。单元格中的值代表注意力得分,最后一个token“time”是唯一一个可以计算所有前面tokens注意力得分的token。

鉴于上图7所示的因果注意力掩码设置,序列中的最后一个token累积了最多的信息,因为它是唯一一个能够访问所有之前token数据的token。因此,在我们的垃圾邮件分类任务中,微调时我们关注的就是这个最后的token。

在修改模型之后,下一部分将详细介绍将最后一个token转换为分类标签预测的过程,并计算模型的初始预测准确率。接下来,我们将在后续部分微调模型以完成垃圾邮件分类任务。

针对所有自学遇到困难的同学们,我帮大家系统梳理大模型学习脉络,将这份 LLM大模型资料 分享出来:包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

👉[CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)]()👈


评估模型性能

由于这部分内容已经很长,我不会详细讨论模型评估的细节。不过,我至少想分享一下显示训练集和验证集分类准确率的图表,以展示模型确实学得很好。图8:训练集准确率(实线)和验证集准确率(虚线)在早期训练过程中显著提高,然后趋于平稳,几乎达到了完美的准确率1.0,对应100%。两条线在整个训练过程中始终非常接近,表明模型并没有过拟合训练数据太多。

正如我们在上面的图8中所见,模型在验证集上达到了大约97%的准确率。而测试集准确率(未显示)约为96%。此外,我们可以看到模型略有过拟合,因为训练集的准确率稍微高一些。不过,总体而言,该模型表现非常好:96%的测试集准确率意味着它能够正确识别100条消息中的96条为垃圾邮件或非垃圾邮件。(我们在这个片段中没有讨论数据集,但它是一个平衡的数据集,包含50%的垃圾邮件和50%的非垃圾邮件,这意味着随机或训练不佳的分类器大约只能达到50%的分类准确率。)

额外实验的见解

此时你可能对某些设计选择有很多疑问,所以我想分享一些我进行的额外实验的结果,这些结果可能会回答你的一些问题或疑虑。复现这些实验的代码可以在GitHub上找到。

https://github.com/rasbt/LLMs-from-scratch/tree/main/ch06/02_bonus_additional-experiments

免责声明:这些实验大多只在1个数据集上运行,未来应在其他数据集上重复进行测试,以验证这些发现是否具有普遍性。

1) 我们需要训练所有层吗?

在上面的章节摘录中,为了提高效率,我们只训练了输出层和最后一个Transformer模块。正如之前解释的那样,对于分类微调来说,不必更新大型语言模型(LLM)的所有层。(我们更新的权重越少,训练速度就越快,因为在反向传播中我们不需要计算这些权重的梯度。)

然而,你可能想知道,不更新所有层会影响多少预测性能。因此,我在下表中进行了比较,分别对所有层进行微调,只微调最后一个Transformer模块(加上最后一层)和只微调最后一层。表1:训练所有层与只训练最后一个Transformer模块(包括最后一层)与只训练最后一层的对比。

如表1所示,训练所有层带来了略微更好的性能:96.67% 对比 95.00%。(然而,这也使得运行时间增加了大约2.5倍。)

完整的实验集可以在GitHub上找到。

https://github.com/rasbt/LLMs-from-scratch/tree/main/ch06/02_bonus_additional-experiments

2) 为什么微调最后一个token,而不是第一个token?

如果你熟悉像BERT这样的编码器风格语言模型(BERT: Deep Bidirectional Transformers for Language Understanding, Devlin等,2018年),你可能知道它们有一个指定的分类token作为第一个token,如下图所示。来自原始BERT论文的注解图,https://arxiv.org/abs/1810.04805

与BERT不同,GPT是一个带有因果注意力掩码的解码器风格模型(参见之前的图7)。这意味着第一个token没有其他输入token的上下文信息。只有最后一个token包含了所有其他token的信息。

因此,如果我们想使用像GPT这样的模型进行分类微调,我们应该关注最后一个token,以捕捉所有输入token的上下文信息。

以下是更多的实验证据,我们可以看到,使用第一个token微调GPT模型进行分类会导致更差的性能。表2:微调GPT模型中的最后一个token与第一个token的对比。

总的来说,我仍然觉得令人惊讶的是,第一个token居然能包含如此多的信息,以至于能够以75%的准确率判断消息是否是垃圾邮件。(请注意,这是一个平衡数据集,随机分类器的准确率为50%。)

3) BERT在性能上如何与GPT对比?

谈到BERT,你可能想知道它在分类任务中与GPT风格的模型相比表现如何。

简而言之,在垃圾邮件分类数据集上,小型GPT-2模型和BERT表现得同样好,如下表所示。表3. GPT-2与BERT在垃圾邮件分类中的对比。

请注意,BERT模型的性能略好(测试集准确率高出1%),但它的体积也几乎大了3倍。此外,数据集可能过于简单和小,因此我还使用IMDB电影评论数据集进行了情感分类(即预测评论者是否喜欢这部电影)。表4:GPT-2与BERT在电影评论分类中的对比。(代码可以在GitHub上找到。)

https://github.com/rasbt/LLMs-from-scratch/tree/main/ch06/03_bonus_imdb-classification

如我们所见,在这个更大的数据集上(包含2.5万条训练和2.5万条测试记录),这两种模型,GPT-2和BERT,的预测性能也相当接近。

通常情况下,编码器风格的BERT和其他模型被认为在分类任务中优于解码器风格的模型。然而,正如上面的实验所示,编码器风格的BERT和解码器风格的GPT模型之间并没有太大的差异。

此外,如果你对更多的基准比较以及改进解码器风格模型的分类性能的技巧感兴趣,你可能会喜欢以下两篇近期论文:

  • Label Supervised LLaMA Finetuning (2023), Li等

  • LLM2Vec: Large Language Models Are Secretly Powerful Text Encoders (2024), BehnamGhader等

https://arxiv.org/abs/2310.01208 https://arxiv.org/abs/2404.05961

例如,正如上述论文讨论的那样,在分类微调过程中移除因果掩码可以进一步提高解码器风格模型的分类性能。

4) 我们应该禁用因果掩码吗?

由于我们在下一个词预测任务上训练了GPT类模型,因果注意力掩码是GPT架构的核心特性之一(与BERT模型或原始Transformer架构不同)。

然而,我们实际上可以在分类微调过程中移除因果掩码,这样我们就可以微调第一个token,而不是最后一个token,因为将不再屏蔽未来的token,第一个token可以看到所有其他token。有因果掩码和无因果掩码的注意力权重矩阵对比。

禁用GPT类大型语言模型中的因果注意力掩码,幸运的是只需要修改两行代码:

class MultiheadAttention(nn.Module):
    def __init__(self, d_in, d_out, context_length, dropout, num_heads):
        super().__init__()
        # ...

    def forward(self, x):
        b, num_tokens, d_in = x.shape
        keys = self.W_key(x)  # 形状: (b, num_tokens, d_out)
        queries = self.W_query(x)
        values = self.W_value(x)

        # ...

        attn_scores = queries @ keys.transpose(2, 3)

        # 注释掉因果注意力掩码部分
        # mask_bool = self.mask.bool()[:num_tokens, :num_tokens]
        # attn_scores.masked_fill_(mask_bool, -torch.inf)

        attn_weights = torch.softmax(
             attn_scores / keys.shape[-1]**0.5, dim=-1
        )
        context_vec = (attn_weights @ values).transpose(1, 2)
        context_vec = context_vec.contiguous().view(
            b, num_tokens, self.d_out
        )
        context_vec = self.out_proj(context_vec)
        return context_vec

表5显示了这个修改对垃圾邮件分类任务性能的影响。表5:使用和不使用因果注意力掩码微调的GPT-2分类器对比。

正如我们在表5的结果中所见,当我们在微调过程中禁用因果掩码时,确实可以获得一些小的改进。

5) 增大模型规模会带来什么影响?

到目前为止,我们只看了最小的GPT-2模型(124百万参数)的性能。它与更大的版本(分别为355百万、774百万和1.5亿参数)相比,表现如何?结果总结在表6中。表6:不同GPT-2模型规模的分类微调对比。

如我们所见,随着模型规模的增大,预测准确率显著提高(不过,GPT-2 medium 是一个例外,我在其他数据集上也注意到了这个模型表现不佳,我怀疑该模型的预训练可能不够充分)。

然而,尽管GPT-2 XL模型显示出了明显更好的分类准确率,但它的微调时间也比最小模型长了7倍。

6) 使用LoRA的改进效果如何?

在第一个问题"1) 我们需要训练所有层吗?"中,我们发现只对最后一个Transformer模块进行微调,几乎可以匹配对整个模型进行微调的分类性能。只微调最后一个模块的优势在于训练速度更快,因为并不是所有的权重参数都需要更新。

一个后续问题是,这与Low-Rank Adaptation(LoRA)这种参数高效的微调技术相比表现如何。(LoRA在附录E中有详细介绍。)表7:全量微调(所有层)与LoRA的参数高效微调对比。

如表7所示,在这个数据集上,全量微调(所有层)与LoRA的测试集性能相同。

对于小模型来说,LoRA的速度略慢,因为添加LoRA层的额外开销可能超过了好处,但在训练更大的1.5亿参数模型时,LoRA的训练速度快了1.53倍。

7) 使用填充还是不使用填充?

如果我们想在训练或推理过程中以批次处理数据(这涉及一次处理多个输入序列),我们需要插入填充token以确保训练样本的长度相等。上图展示了如何将一个批次中的输入文本填充至相同长度。

在常规的文本生成任务中,填充不会影响模型的响应,因为填充token通常会添加到右侧,由于前面讨论的因果掩码,这些填充token不会影响其他token。

然而,记住我们之前讨论的,我们是对最后一个token进行微调的。由于填充token位于这个最后token的左侧,这些填充token可能会影响结果。

如果我们使用批大小为1,其实不需要填充输入。当然,这在计算上效率较低(因为我们一次只能处理一个输入样本)。但批大小为1可以作为一种测试手段,用来检验不使用填充是否会改善结果。(另一种解决方案是添加自定义掩码以在注意力得分计算中忽略填充token,但由于这需要更改GPT的实现,这属于另一个主题。)表8:训练时使用填充(常规)和不对输入进行填充的对比。

如我们所见,避免填充token确实可以为模型带来显著提升!(请注意,我使用梯度累积模拟了批大小为8的情况,以匹配默认实验的批大小,并使其成为公平的对比。)

希望你对这些额外实验感兴趣。我还有一些额外的实验作为GitHub上的补充材料。

https://github.com/rasbt/LLMs-from-scratch/tree/main/ch06/02_bonus_additional-experiments


如何学习AI大模型?

大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。 “AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。

不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!

想正式转到一些新兴的 AI 行业,不仅需要系统的学习AI大模型。同时也要跟已有的技能结合,辅助编程提效,或上手实操应用,增加自己的职场竞争力。

但是LLM相关的内容很多,现在网上的老课程老教材关于LLM又太少。所以现在小白入门就只能靠自学,学习成本和门槛很高

那么针对所有自学遇到困难的同学们,我帮大家系统梳理大模型学习脉络,将这份 LLM大模型资料 分享出来:包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

👉[CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)]()👈

学习路线

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈

• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2160627.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot技术栈的网上超市开发实践

2 系统开发技术 这部分内容主要介绍本系统使用的技术,包括使用的工具,编程的语言等内容。 2.1 Java语言 Java语言自公元1995年至今,已经超过25年了,依然在软件开发上面有很大的市场占有率。当年Sun公司发明Java就是为了发展一门跨…

python类的call方法与init方法

1. call方法 在对象被调用了的时候就会调用call方法a(666) class A:def __call__(self, args):print(call 方法被调用了,args) aA() a(666) 2.init方法 创建对象的时候 init 方法被调用 class A:def __init__(self,args):print(创建对象的时候 init 方法被调用了,args) aA(…

shardingjdbc-读写分离配置

文章目录 1、application.yml2、shardingsphere.yaml3、创建实体类 User4、创建 UserMapper5、添加依赖6、读写分离测试7、事务测试 我们的主从复制已经提前搭建好: mysql-搭建主从复制:https://blog.csdn.net/m0_65152767/article/details/142214434 1…

使用 Python 模拟光的折射,反射,和全反射

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

【一句话点破】【C++重要题目】基类与派生类的成员变量值被对象调用的结果(二)

【一句话点破】基类/派生类的成员变量由哪个对象初始化的&#xff0c;哪个对象调用该成员变量时就用由它初始化的值 [尤其找准是基类对象or派生类对象的值] 【重要例题】15浙工大卷二读程序5题 可运行代码如下 #include "bits/stdc.h" #include<iostream> u…

畅阅读微信小程序

畅阅读微信小程序 weixin051畅阅读微信小程序ssm 摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用j…

CVE-2024-1112 Resource Hacker 缓冲区溢出分析

漏洞简述 CVE-2024-1112 是 Resource Hacker 软件的一个缓冲区溢出漏洞。该漏洞存在于版本 3.6.0.92 中。由于软件在处理命令行中的文件路径时未对文件字符串长度进行限制&#xff0c;过长的字符串参数导致内存被过度写入&#xff0c;从而引发缓冲区溢出。 漏洞复现 构造长度…

简单的评论系统【JavaScript】

这段代码实现了一个简单的评论系统&#xff0c;用户可以输入评论并提交&#xff0c;评论会显示在页面上&#xff0c;同时可以通过点击“删除”按钮来删除相应的评论。 实现效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"zh"><head…

Excel名字查重筛选,查找重复内容原来这么简单

大家好&#xff0c;这里是效率办公指南&#xff01; &#x1f50d; 在处理大量数据时&#xff0c;尤其是人员名单或客户信息时&#xff0c;确保没有重复的名字是非常重要的。在Excel中&#xff0c;有几种方法可以帮助我们快速查找和处理重复的名字。今天&#xff0c;我们将介绍…

2024年9月24日历史上的今天大事件早读

1550年9月24日 明代戏剧家汤显祖出生 1852年9月24日 法国人吉法尔制造的用蒸汽机推进的飞船试飞成功 1884年9月24日 中国近代化学的先驱徐寿逝世 1905年9月24日 吴樾壮炸五大臣&#xff0c;身殉革命 1909年9月24日 京张铁路通车 1910年9月24日 剧作家曹禺诞生 1930年9月2…

Python基础练习题‌100道电子版及源码文件

Python基础练习题‌&#xff0c;旨在帮助学习者巩固和提升Python编程技能。以下是一些精选的练习题目&#xff0c;包括但不限于&#xff1a; 基础语法练习‌&#xff1a;涉及变量定义、数据类型、运算符、条件语句、循环等基础语法结构的应用。例如&#xff0c;编写程序来处理数…

使用Adobe XD进行制作SVG字体

制作SVG字体的办法有很多&#xff0c;我这里选择了Adobe XD进行制作。 1.选择画布尺寸 2 输入文本 设置字体样式 3 设置画布背景 4 转换字体&#xff08;物件&#xff09;路径 5 设置组 复制SVG代码 6 放入到Html中 <!DOCTYPE html> <html lang"zh">&l…

稀疏向量 milvus存储检索RAG使用案例

参考&#xff1a; https://milvus.io/docs/hybrid_search_with_milvus.md milvus使用不方便&#xff1a; 1&#xff09;离线计算向量很慢BGEM3EmbeddingFunction 2&#xff09;milvus安装环境支持很多问题&#xff0c;不支持windows、centos等 在线demo&#xff1a; https://co…

基于单片机的智能窗帘控制系统-设计说明书

设计摘要&#xff1a; 智能窗帘控制系统是一种利用单片机技术实现的智能化控制系统&#xff0c;可以实现窗帘的自动开合和定时控制功能。本系统的设计基于单片机技术&#xff0c;结合传感器、电机和执行器等硬件设备&#xff0c;实现对窗帘的智能化控制。通过传感器采集环境信…

同一网络下两台电脑IP一样吗?探究局域网内的IP分配机制

在日常生活和工作中&#xff0c;我们经常会在同一网络环境下使用多台电脑。这时&#xff0c;一个常见的问题就会浮现&#xff1a;同一网络下两台电脑IP一样吗&#xff1f;这个问题看似简单&#xff0c;但实际上涉及到局域网内的IP分配机制。本文将深入探讨这一问题&#xff0c;…

JDBC PreparedStatement解决SQL注入方案

文章目录 获取PreparedStatement对象PreparedStatement是如何解决SQL注入问题的PreparedStatement的 应用上述如何解决sql注入的问题呢&#xff1f; 获取PreparedStatement对象 PreparedStatement是Statement的子接口&#xff0c;可以防止sql注入问题。可以通过Connection接口…

AI最大的应用是什么,如何成为初代AGI产品经理?

❝ 在当今这个由数据驱动的时代&#xff0c;AI技术正以前所未有的速度发展&#xff0c;它不仅改变了我们与数字世界的互动方式&#xff0c;更在物理世界中掀起了一场革命。阿里巴巴集团CEO吴泳铭在2024云栖大会上的演讲&#xff0c;为我们描绘了AI技术未来的巨大潜力。他指出&a…

【浙江工业大学主办 | EI检索稳定】HCIVR 二轮截稿 时间

二轮截稿日期&#xff1a;2024年10月15日 收录检索&#xff1a;EI Compendex&#xff0c;Scopus 征稿主题&#xff1a; 光学手势识别系统、生物识别、眼动追踪和表情识别、光势行为分析、传感器技术、光学传感与虚拟现实交互、光学跟踪与定位系统、声光传感融合系统、基于VR的…

在WordPress中使用Simple Custom CSS and JS插件美化页面

目录 一、插件安装 二、添加代码 三、使用案例 1、图片居中 2、段落前空两格 3、添加版权声明 四、代码编写简述 WordPress是目前使用最广泛的开源建站框架&#xff0c;其主要功能就是“主题”&#xff08;Theme&#xff09;系统&#xff0c;该功能可以让用户自定义主题…

【网络协议栈】传输层的意义 和 UDP协议结构的解析(内含逻辑图解通俗易懂)

绪论​ “六年之约—jack”。本章是网络协议栈第二个主要模块 传输层&#xff0c;传输层在网络层中是非常重要的&#xff0c;他主要通过储存双方的端口记录数据的来源以及数据最终的去处&#xff0c;并且能一定的保证数据传输到达&#xff0c;以及快速高效的传递。本章主要讲到…