从代码的角度理解Transformer 【附代码】

此前,我通过文字+图解+手推公式的方式介绍了Transformer模型,今天我们从代码的角度再次带你理解Transformer模型~

Transformer 的简短介绍

Transformer架构最初由谷歌研究人员于2017年在论文《注意力就是你所需要的一切》("Attention Is All You Need")中提出。这一架构的诞生标志着自然语言处理领域的一次重大突破,因为它彻底颠覆了传统的序列到序列学习模型的设计思路。在此之前,基于循环神经网络(RNN)的模型在机器翻译、语音识别等任务中占据主导地位,但RNN的串行处理方式使其计算效率低下,时间复杂度为O(n),且难以捕捉长距离依赖关系。

Transformer通过引入自注意力机制(Self-Attention),彻底改变了这一局面。它不再需要逐个处理序列中的元素,而是能够同时关注整个输入序列,从而实现了并行计算。这种设计将时间复杂度从O(n)降低到接近O(1),大幅提升了模型的训练和推理速度,同时显著增强了对长距离依赖关系的建模能力。自注意力机制的核心思想是通过计算序列中每个元素与其他元素的相关性,动态地捕捉全局上下文信息,从而实现高效的并行处理。

图片

Transformer的提出不仅解决了RNN的计算瓶颈,还为深度学习模型的设计提供了全新的思路。它迅速成为自然语言处理领域的主流架构,并在计算机视觉、语音处理等多个领域展现出强大的适应性和扩展性。如今,Transformer已经成为现代人工智能技术的基石之一,推动了语言模型、多模态学习等领域的飞速发展,深刻改变了深度学习的研究与应用格局。


Transformer的整体架构是一种基于编码器-解码器(Encoder-Decoder)结构的模型,专为处理序列到序列(seq2seq)任务而设计,例如机器翻译、文本生成等。它的核心创新在于引入了自注意力机制(Self-Attention),使得模型能够并行处理整个输入序列,而不是像传统的循环神经网络(RNN)那样逐个处理序列元素。以下是Transformer的整体架构的详细描述:

图片

1. 总体结构

Transformer由两部分组成:

  • 编码器(Encoder):负责处理输入序列,并将其转换为上下文相关的表示。
  • 解码器(Decoder):负责根据编码器的输出生成输出序列。

编码器和解码器都由多个相同的层(通常为6层)堆叠而成,每层包含不同的模块。

2. 编码器(Encoder)

编码器由以下模块组成:

  1. 输入嵌入(Input Embedding)
  2. 将输入序列中的每个词或符号映射到固定维度的向量(词嵌入)。
  3. 通常会加上位置编码(Positional Encoding),以保留序列中元素的顺序信息。
  4. 多头自注意力机制(Multi-Head Self-Attention)
  5. 这是Transformer的核心模块,用于捕捉输入序列中元素之间的全局依赖关系。
  6. 通过将输入向量分解为多个“头”(head),模型可以并行计算不同子空间的注意力,从而增强表达能力。
  7. 前馈神经网络(Feed-Forward Network)
  8. 每个编码器层包含一个全连接的前馈神经网络,用于进一步处理自注意力机制的输出。
  9. 网络的结构是相同的,但参数独立。
  10. 残差连接归一化(Residual Connections & Layer Normalization)
  11. 每个模块(自注意力和前馈网络)的输出都会与输入相加(残差连接),然后通过层归一化(LayerNorm)进行稳定化。

3. 解码器(Decoder)

解码器的结构与编码器类似,但增加了以下模块:

  1. 掩码多头自注意力(Masked Multi-Head Self-Attention)
  2. 与编码器的自注意力机制类似,但会引入掩码(masking),以确保在生成输出序列时,每个位置的预测只能依赖于前面的词,而不能看到未来的词。
  3. 编码器-解码器注意力(Encoder-Decoder Attention)
  4. 这一模块允许解码器从编码器的输出中获取上下文信息,从而更好地生成输出序列。
  5. 前馈神经网络(Feed-Forward Network)
  6. 与编码器中的前馈网络结构相同,用于进一步处理注意力机制的输出。
  7. 输出层(Output Layer)
  8. 解码器的最后一层是一个线性层,将模型的输出映射到目标词汇表的大小,并通过Softmax计算每个词的概率分布。

4. 位置编码(Positional Encoding)

由于Transformer不依赖于RNN的顺序处理,它需要一种方法来保留输入序列中元素的顺序信息。位置编码通过将位置信息嵌入到输入向量中,使得模型能够感知序列的顺序。位置编码可以是固定的(如正弦函数)或通过学习得到。

5. 并行化优势

Transformer的一个显著特点是它的并行化能力。由于自注意力机制可以同时处理整个输入序列,模型的训练和推理速度远快于基于RNN的模型。这种并行化能力使得Transformer在大规模数据集上的表现尤为突出。

多头注意力机制

我们将要实现的第一个块实际上是 Transformer 中最重要的部分,称为多头注意力。让我们看看它在整体架构中的位置。

图片

Attention 实际上并不是 Transformer 特有的机制,它已经在 RNN 序列到序列模型中使用。

图片

图片

Transformer 中的注意力机制

import torch
import torch.nn as nn
import math


class MultiHeadAttention(nn.Module):
    def __init__(self, hidden_dim=256, num_heads=4):
        """
        input_dim: Dimensionality of the input.
        num_heads: The number of attention heads to split the input into.
        """
        super(MultiHeadAttention, self).__init__()
        self.hidden_dim = hidden_dim
        self.num_heads = num_heads
        assert hidden_dim % num_heads == 0, "Hidden dim must be divisible by num heads"
        self.Wv = nn.Linear(hidden_dim, hidden_dim, bias=False) # the Value part
        self.Wk = nn.Linear(hidden_dim, hidden_dim, bias=False) # the Key part
        self.Wq = nn.Linear(hidden_dim, hidden_dim, bias=False) # the Query part
        self.Wo = nn.Linear(hidden_dim, hidden_dim, bias=False) # the output layer
        
        
    def check_sdpa_inputs(self, x):
        assert x.size(1) == self.num_heads, f"Expected size of x to be ({-1, self.num_heads, -1, self.hidden_dim // self.num_heads}), got {x.size()}"
        assert x.size(3) == self.hidden_dim // self.num_heads
        
        
    def scaled_dot_product_attention(
            self, 
            query, 
            key, 
            value, 
            attention_mask=None, 
            key_padding_mask=None):
        """
        query : tensor of shape (batch_size, num_heads, query_sequence_length, hidden_dim//num_heads)
        key : tensor of shape (batch_size, num_heads, key_sequence_length, hidden_dim//num_heads)
        value : tensor of shape (batch_size, num_heads, key_sequence_length, hidden_dim//num_heads)
        attention_mask : tensor of shape (query_sequence_length, key_sequence_length)
        key_padding_mask : tensor of shape (sequence_length, key_sequence_length)
        
    
        """
        self.check_sdpa_inputs(query)
        self.check_sdpa_inputs(key)
        self.check_sdpa_inputs(value)
        
        
        d_k = query.size(-1)
        tgt_len, src_len = query.size(-2), key.size(-2)

        
        # logits = (B, H, tgt_len, E) * (B, H, E, src_len) = (B, H, tgt_len, src_len)
        logits = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k) 
        
        # Attention mask here
        if attention_mask is not None:
            if attention_mask.dim() == 2:
                assert attention_mask.size() == (tgt_len, src_len)
                attention_mask = attention_mask.unsqueeze(0)
                logits = logits + attention_mask
            else:
                raise ValueError(f"Attention mask size {attention_mask.size()}")
        
                
        # Key mask here
        if key_padding_mask is not None:
            key_padding_mask = key_padding_mask.unsqueeze(1).unsqueeze(2) # Broadcast over batch size, num heads
            logits = logits + key_padding_mask
        
        
        attention = torch.softmax(logits, dim=-1)
        output = torch.matmul(attention, value) # (batch_size, num_heads, sequence_length, hidden_dim)
        
        return output, attention

    
    def split_into_heads(self, x, num_heads):
        batch_size, seq_length, hidden_dim = x.size()
        x = x.view(batch_size, seq_length, num_heads, hidden_dim // num_heads)
        
        return x.transpose(1, 2) # Final dim will be (batch_size, num_heads, seq_length, , hidden_dim // num_heads)

    def combine_heads(self, x):
        batch_size, num_heads, seq_length, head_hidden_dim = x.size()
        return x.transpose(1, 2).contiguous().view(batch_size, seq_length, num_heads * head_hidden_dim)
        
    
    def forward(
            self, 
            q, 
            k, 
            v, 
            attention_mask=None, 
            key_padding_mask=None):
        """
        q : tensor of shape (batch_size, query_sequence_length, hidden_dim)
        k : tensor of shape (batch_size, key_sequence_length, hidden_dim)
        v : tensor of shape (batch_size, key_sequence_length, hidden_dim)
        attention_mask : tensor of shape (query_sequence_length, key_sequence_length)
        key_padding_mask : tensor of shape (sequence_length, key_sequence_length)
       
        """
        q = self.Wq(q)
        k = self.Wk(k)
        v = self.Wv(v)

        q = self.split_into_heads(q, self.num_heads)
        k = self.split_into_heads(k, self.num_heads)
        v = self.split_into_heads(v, self.num_heads)
        
        # attn_values, attn_weights = self.multihead_attn(q, k, v, attn_mask=attention_mask)
        attn_values, attn_weights  = self.scaled_dot_product_attention(
            query=q, 
            key=k, 
            value=v, 
            attention_mask=attention_mask,
            key_padding_mask=key_padding_mask,
        )
        grouped = self.combine_heads(attn_values)
        output = self.Wo(grouped)
        
        self.attention_weigths = attn_weights
        
        return output

我们需要解释几个概念:

  1. 查询(Query)、键(Key)和值(Value)
    想象一下,这就像使用一个Python字典:当你查询的键不在字典中时,字典不会返回任何结果。但如果我们希望字典能够返回与查询“接近”的信息,而不是完全匹配的结果呢?
    例如,假设我们有这样的场景:
  2. 如果查询与键不完全匹配,我们是否可以返回一个“接近”的结果?
  3. 或者,是否可以返回多个值的“混合”信息,而不是单一的精确匹配?
  4. 查询(Query):是你试图查找的信息。
  5. 键(Key)和值(Value):是存储的数据。

这种机制正是注意力机制(Attention Mechanism)的核心思想:通过计算查询与键之间的相似性,动态地从值中提取相关信息,而不需要完全匹配。

d = {"panther": 1, "bear": 10, "dog":3}
d["wolf"] = 0.2*d["panther"] + 0.7*d["dog"] + 0.1*d["bear"]

这段代码的核心在于计算查询(query)与键(keys)之间的注意力权重,这些权重决定了哪些部分的信息对回答查询更重要。通过这种方式,模型可以动态地从数据中提取相关信息,而不需要逐个检查所有部分。

logits = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k) # we compute the weights of attention

注意力机制的核心在于通过计算查询(query)与键(keys)之间的相似性,生成注意力权重,然后将这些权重应用于值(values),以提取与查询最相关的信息。

attention = torch.softmax(logits, dim=-1)
output = torch.matmul(attention, value) # (batch_size, num_heads, sequence_length, hidden_dim)

2) 注意力掩码与填充(Attention Masking and Padding)

在处理序列输入时,我们希望注意力机制能够专注于相关的信息,而忽略无用或禁止的信息。

1. 无用信息(Padding)

无用信息的一个典型例子是填充(padding)。为了对齐一个批次中所有序列的长度,我们通常会使用填充符号(如<PAD>)将较短的序列扩展到与最长序列相同的长度。然而,这些填充符号并不包含任何有意义的信息,因此模型在计算注意力时需要忽略它们。

为了实现这一点,我们通常会引入一个填充掩码(Padding Mask),将填充位置的注意力权重设置为零,从而确保模型不会关注这些无用信息。填充掩码的具体实现会在最后一节中详细讨论。

2. 禁止信息(Forbidden Information)

禁止信息的处理稍微复杂一些。在训练过程中,模型需要学习如何将输入序列编码为上下文表示,并将目标序列与输入对齐。然而,在推理阶段(如文本生成任务中),模型需要根据之前生成的词来预测下一个词,而不能看到未来的词。

为了模拟这种推理过程,我们在训练时也需要对模型施加相同的限制。具体来说,我们会使用一个因果掩码(Causal Mask),确保在每个时间步中,目标序列只能访问过去的信息(即之前的时间步),而不能访问未来的信息(即之后的时间步)。

if attention_mask is not None:
    if attention_mask.dim() == 2:
        assert attention_mask.size() == (tgt_len, src_len)
        attention_mask = attention_mask.unsqueeze(0)
        logits = logits + attention_mask

位置编码

它对应Transformer的如下部分:

图片

在接收和处理输入时,Transformer 没有顺序感,因为它将序列视为一个整体,这与 RNN 的做法相反。因此,我们需要添加一点时间顺序,以便 Transformer 能够学习依赖关系。

# Taken from https://pytorch.org/tutorials/beginner/transformer_tutorial.html#define-the-model
class PositionalEncoding(nn.Module):

    def __init__(self, d_model, dropout=0.1, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)
        
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(max_len, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
        
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0)
        
        self.register_buffer('pe', pe)

    def forward(self, x):
        """
        Arguments:
            x: Tensor, shape ``[batch_size, seq_len, embedding_dim]``
        """
        x = x + self.pe[:, :x.size(1), :]
        return x

编码器

编码器是 Transformer 的左侧部分。

图片

先在代码中添加一小部分,即前馈部分:

class PositionWiseFeedForward(nn.Module):
    def __init__(self, d_model: int, d_ff: int):
        super(PositionWiseFeedForward, self).__init__()
        self.fc1 = nn.Linear(d_model, d_ff)
        self.fc2 = nn.Linear(d_ff, d_model)
        self.relu = nn.ReLU()

    def forward(self, x):
        return self.fc2(self.relu(self.fc1(x)))

将各个部分组合在一起,得到了一个编码器模块!

class EncoderBlock(nn.Module):
    def __init__(self, n_dim: int, dropout: float, n_heads: int):
        super(EncoderBlock, self).__init__()
        self.mha = MultiHeadAttention(hidden_dim=n_dim, num_heads=n_heads)
        self.norm1 = nn.LayerNorm(n_dim)
        self.ff = PositionWiseFeedForward(n_dim, n_dim)
        self.norm2 = nn.LayerNorm(n_dim)
        self.dropout = nn.Dropout(dropout)
        
    def forward(self, x, src_padding_mask=None):
        assert x.ndim==3, "Expected input to be 3-dim, got {}".format(x.ndim)
        att_output = self.mha(x, x, x, key_padding_mask=src_padding_mask)
        x = x + self.dropout(self.norm1(att_output))
        
        ff_output = self.ff(x)
        output = x + self.norm2(ff_output)
       
        return output

编码器实际上包含 N 个编码器块或层,以及用于输入的嵌入层。因此,通过添加嵌入、位置编码和编码器块来创建一个编码器:

class Encoder(nn.Module):
    def __init__(
            self, 
            vocab_size: int, 
            n_dim: int, 
            dropout: float, 
            n_encoder_blocks: int,
            n_heads: int):
        
        super(Encoder, self).__init__()
        self.n_dim = n_dim

        self.embedding = nn.Embedding(
            num_embeddings=vocab_size, 
            embedding_dim=n_dim
        )
        self.positional_encoding = PositionalEncoding(
            d_model=n_dim, 
            dropout=dropout
        )    
        self.encoder_blocks = nn.ModuleList([
            EncoderBlock(n_dim, dropout, n_heads) for _ in range(n_encoder_blocks)
        ])
        
        
    def forward(self, x, padding_mask=None):
        x = self.embedding(x) * math.sqrt(self.n_dim)
        x = self.positional_encoding(x)
        for block in self.encoder_blocks:
            x = block(x=x, src_padding_mask=padding_mask)
        return x

解码器

解码器部分是左边的部分。

图片

Masked Multi-Head Attention 是一种特殊的注意力机制,主要用于防止模型在训练或推理过程中访问未来的信息。这种机制在序列生成任务(如文本生成、机器翻译等)中尤为重要,因为它确保模型在生成每个词时只能依赖于之前的信息,而不是未来的上下文。

# Stuff before

self.self_attention = MultiHeadAttention(hidden_dim=n_dim, num_heads=n_heads)
masked_att_output = self.self_attention(
    q=tgt, 
    k=tgt, 
    v=tgt, 
    attention_mask=tgt_mask, <-- HERE IS THE CAUSAL MASK
    key_padding_mask=tgt_padding_mask)

# Stuff after

第二个注意力机制称为交叉注意力机制。它将使用解码器的查询来匹配编码器的键和值!注意:它们在训练期间可能具有不同的长度,因此通常最好明确定义输入的预期形状。

def scaled_dot_product_attention(
            self, 
            query, 
            key, 
            value, 
            attention_mask=None, 
            key_padding_mask=None):
        """
        query : tensor of shape (batch_size, num_heads, query_sequence_length, hidden_dim//num_heads)
        key : tensor of shape (batch_size, num_heads, key_sequence_length, hidden_dim//num_heads)
        value : tensor of shape (batch_size, num_heads, key_sequence_length, hidden_dim//num_heads)
        attention_mask : tensor of shape (query_sequence_length, key_sequence_length)
        key_padding_mask : tensor of shape (sequence_length, key_sequence_length)
    
        """

下面是我们将编码器的输出(称为内存)与解码器输入一起使用的部分:

# Stuff before
self.cross_attention = MultiHeadAttention(hidden_dim=n_dim, num_heads=n_heads)
cross_att_output = self.cross_attention(
        q=x1, 
        k=memory, 
        v=memory, 
        attention_mask=None,  <-- NO CAUSAL MASK HERE
        key_padding_mask=memory_padding_mask) <-- WE NEED TO USE THE PADDING OF THE SOURCE
# Stuff after

把这些部分放在一起,最终得到了解码器:

class DecoderBlock(nn.Module):
    def __init__(self, n_dim: int, dropout: float, n_heads: int):
        super(DecoderBlock, self).__init__()
        
        # The first Multi-Head Attention has a mask to avoid looking at the future
        self.self_attention = MultiHeadAttention(hidden_dim=n_dim, num_heads=n_heads)
        self.norm1 = nn.LayerNorm(n_dim)
        
        # The second Multi-Head Attention will take inputs from the encoder as key/value inputs
        self.cross_attention = MultiHeadAttention(hidden_dim=n_dim, num_heads=n_heads)
        self.norm2 = nn.LayerNorm(n_dim)
        
        self.ff = PositionWiseFeedForward(n_dim, n_dim)
        self.norm3 = nn.LayerNorm(n_dim)
        # self.dropout = nn.Dropout(dropout)
        
        
    def forward(self, tgt, memory, tgt_mask=None, tgt_padding_mask=None, memory_padding_mask=None):
        
        masked_att_output = self.self_attention(
            q=tgt, k=tgt, v=tgt, attention_mask=tgt_mask, key_padding_mask=tgt_padding_mask)
        x1 = tgt + self.norm1(masked_att_output)
        
        cross_att_output = self.cross_attention(
            q=x1, k=memory, v=memory, attention_mask=None, key_padding_mask=memory_padding_mask)
        x2 = x1 + self.norm2(cross_att_output)
        
        ff_output = self.ff(x2)
        output = x2 + self.norm3(ff_output)

        
        return output

class Decoder(nn.Module):
    def __init__(
        self, 
        vocab_size: int, 
        n_dim: int, 
        dropout: float, 
        n_decoder_blocks: int,
        n_heads: int):
        
        super(Decoder, self).__init__()
        
        self.embedding = nn.Embedding(
            num_embeddings=vocab_size, 
            embedding_dim=n_dim,
            padding_idx=0
        )
        self.positional_encoding = PositionalEncoding(
            d_model=n_dim, 
            dropout=dropout
        )
          
        self.decoder_blocks = nn.ModuleList([
            DecoderBlock(n_dim, dropout, n_heads) for _ in range(n_decoder_blocks)
        ])
        
        
    def forward(self, tgt, memory, tgt_mask=None, tgt_padding_mask=None, memory_padding_mask=None):
        x = self.embedding(tgt)
        x = self.positional_encoding(x)

        for block in self.decoder_blocks:
            x = block(
                x, 
                memory, 
                tgt_mask=tgt_mask, 
                tgt_padding_mask=tgt_padding_mask, 
                memory_padding_mask=memory_padding_mask)
        return x

Padding 与 Masking

在多头注意力机制中,我们提到过在计算注意力时需要排除输入序列中的某些部分。这在处理不同长度的序列时尤为重要。

1. 序列对齐与填充(Padding)

在训练过程中,我们通常会将多个输入和目标序列组合成一个批次进行处理。然而,每个序列的长度可能各不相同。为了能够将它们作为一个批次处理,我们需要将所有序列对齐到最长序列的长度。这通常是通过添加一个特殊的填充符号(如PAD)来实现的。

例如,假设我们有一个批次包含四个单词:bananawatermelonpearblueberry。为了将它们作为一个批次处理,我们需要将所有单词的长度对齐到最长单词(watermelon)的长度。我们通过在较短的单词末尾添加PAD符号来实现这一点。

2. 填充掩码(Padding Mask)

在注意力计算中,我们希望模型忽略这些填充符号,因为它们不包含任何有意义的信息。为了实现这一点,我们使用一个填充掩码(Padding Mask),将填充位置的注意力权重设置为零。这样,模型在计算注意力时就不会关注这些无用的信息。

图片

在上面的例子中,希望从正在计算的注意力权重中排除填充索引。因此,可以按如下方式计算源数据和目标数据的掩码:

padding_mask = (x == PAD_IDX)

那么因果掩码现在怎么样了?如果希望模型在每个时间步骤中只能关注过去的步骤,这意味着对于每个时间步骤 T,模型只能关注 1…T 中的每个步骤 t。这是一个双 for 循环,因此可以使用矩阵来计算:

图片

def  generate_square_subsequent_mask ( size: int ): 
      """生成一个三角形 (size, size) 掩码。来自 PyTorch 文档。"""
       mask = ( 1 - torch.triu(torch.ones(size, size), diagonal= 1 )). bool () 
      mask = mask. float ().masked_fill(mask == 0 , float ( '-inf' )).masked_fill(mask == 1 , float ( 0.0 )) 
      return mask

现在将各个部分组合在一起来构建我们的 Transformer!

 这份《AI产品经理学习资料包》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以在文末CSDN官方认证二维码免费领取【保证100%免费】
资料包: CSDN大礼包:《对标阿里黑客&网络安全入门&进阶学习资源包》免费分享


AI产品经理,0基础小白入门指南
作为一个零基础小白,如何做到真正的入局AI产品?

什么才叫真正的入局?

是否懂 AI、是否懂产品经理,是否具备利用大模型去开发应用能力,是否能够对大模型进行调优,将会是决定自己职业前景的重要参数。

你是否遇到这些问题:
1、传统产品经理

不懂Al无法对AI产品做出判断,和技术沟通丧失话语权
不了解 AI产品经理的工作流程、重点
2、互联网业务负责人/运营
对AI焦虑,又不知道怎么落地到业务中想做定制化AI产品并落地创收缺乏实战指导
3、大学生/小白
就业难,不懂技术不知如何从事AI产品经理想要进入AI赛道,缺乏职业发展规划,感觉遥不可及
为了帮助开发者打破壁垒,快速了解AI产品经理核心技术原理,学习相关AI产品经理,及大模型技术。从原理出发真正入局AI产品经理。

这里整理了一些AI产品经理学习资料包给大家
📖AI产品经理经典面试八股文
📖大模型RAG经验面试题
📖大模型LLMS面试宝典
📖大模型典型示范应用案例集99个
📖AI产品经理入门书籍
📖生成式AI商业落地白皮书

🔥作为AI产品经理,不仅要懂行业发展方向,也要懂AI技术,可以帮助大家:
✅深入了解大语言模型商业应用,快速掌握AI产品技能
✅掌握AI算法原理与未来趋势,提升多模态AI领域工作能力
✅实战案例与技巧分享,避免产品开发弯路

这份《AI产品经理学习资料包》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】
资料包: CSDN大礼包:《对标阿里黑客&网络安全入门&进阶学习资源包》免费分享

AI大模型学习福利
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

大模型&AI产品经理如何学习
求大家的点赞和收藏,我花2万买的大模型学习资料免费共享给你们,来看看有哪些东西。

1.学习路线图


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

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

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

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

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

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

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

2.视频教程
网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己整理的大模型视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

(都打包成一块的了,不能一一展开,总共300多集)

因篇幅有限,仅展示部分资料,需要点击CSDN大礼包:《对标阿里黑客&网络安全入门&进阶学习资源包》免费分享前往获取

3.技术文档和电子书
这里主要整理了大模型相关PDF书籍、行业报告、文档,有几百本,都是目前行业最新的。


4.LLM面试题和面经合集
这里主要整理了行业目前最新的大模型面试题和各种大厂offer面经合集。


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

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

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

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


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

👉获取方式:
😝有需要的小伙伴,可以CSDN大礼包:《对标阿里黑客&网络安全入门&进阶学习资源包》免费分享免费领取【保证100%免费】🆓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值