万字长文教你从零实现百万参数LLM训练

BIGO技术 | 万亿模型参数的训练 ​一、推荐场景特征稀疏性 推荐场景通常由于引入了大量的ID类特征从而导致存在海量稀疏参数,例如下图经典YouTube DNN模型中,使用用户观看过的视频以及用户历史search tokens作为主要Embedded特征。根据论文中论述,YouTube DNN中candidate video以及search tokens均有百万之巨。在此基础上如果再使用交叉特征,就会使参数爆炸问题进一步加剧。 图1 YouTube DNN 在BIGO推荐场景主模型的稀疏参数也已经近万亿,即使按照FP16存储.. 阅读详情

01.引言

制作自己的大型语言模型(LLM)是一件很酷的事情,谷歌、Twitter 和 Facebook 等许多大公司都在这样做。他们会发布不同版本的模型,如 70 亿、130 亿或 700 亿。即使是较小的社区也在这样做。你可能读过关于创建自己的 LLM 的博客或看过相关视频,但它们通常只谈理论,对实际步骤和代码涉及不多。

在这篇文章中,我们将尝试制作一个只有 230 万个参数的 LLM,有趣的是,我们不需要特别多的 GPU。我们将以 LLaMA 1 论文方法为指导。别担心,我们会保持简单并使用一个基本数据集,这样你就能看到创建自己的百万参数 LLM 有多么容易。

闲话少说,我们直接开始吧!

02.了解LLama结构

在使用 LLaMA 方法创建我们自己的 LLM 之前,有必要了解一下 LLaMA 的架构。下面是原始Transformer结构和 LLaMA结构 的对比图。

img

以下我们来逐章节介绍一下 LLaMA 结构中的改进点。

03.使用RMSNorm进行前归一化

在 LLaMA 结构中,采用了一种名为 RMSNorm 的技术,对每个Transformer子层的输入进行归一化处理。这种方法受到 GPT-3 的启发,旨在优化与LayerNorm相关的计算成本。RMSNorm 的性能与 LayerNorm 相似,但运行时间大大缩短(7%∼64%)。

img

为此,RMSNorm强调重新缩放不变性,并根据均方根(RMS)统计量调节输入总和。其主要动机是通过去除均方根统计量来简化 LayerNorm。

04.采用SwiGLU激活函数

LLaMA 从 PaLM结构中汲取灵感,引入了 SwiGLU 激活函数。要理解 SwiGLU,首先必须掌握 Swish 激活函数。SwiGLU 对 Swish 进行了扩展,包括一个带有密集网络的自定义层,用于对输入激活进行拆分和乘法运算。

img

其目的是通过引入更复杂的激活函数来增强模型的表现力。有关 SwiGLU 的更多详情,请参阅相关论文。

论文链接:https://arxiv.org/pdf/2002.05202v1

05.采用RoPE位置编码

旋转位置编码RoPE 是 LLaMA 中使用的一种位置嵌入。它使用旋转矩阵对绝对位置信息进行编码,并在自注意公式中自然地包含明确的相对位置依赖性。RoPE 具有多种优势,例如可扩展到各种序列长度,并且随着相对距离的增加,Token间的依赖性会逐渐减弱。

这是通过与旋转矩阵相乘对相对位置进行编码来实现的,从而产生衰减的相对距离–这是自然语言编码的理想特性。对数学细节感兴趣的人可以参阅 RoPE 论文。

论文:https://arxiv.org/pdf/2104.09864v4

除这些概念外,LLaMA 论文还介绍了其他重要方法,包括使用带有特定参数的 AdamW 优化器、高效实现(如 xformers 库中的因果多头注意力算子),以及手动实现Transformer层的后向传播函数,以优化后向传播过程中的计算。

06.导入基本库

在简单介绍了基本理论后,我们接着来编写代码,首先导入我们的基本依赖库:

# PyTorch for implementing LLM (No GPU)import torch# Neural network modules and functions from PyTorchfrom torch import nnfrom torch.nn import functional as F# NumPy for numerical operationsimport numpy as np# Matplotlib for plotting Loss etc.from matplotlib import pyplot as plt# Time module for tracking execution timeimport time# Pandas for data manipulation and analysisimport pandas as pd# urllib for handling URL requests (Downloading Dataset)import urllib.request

此外,我们创建一个存储模型参数配置的字典对象。

# Configuration object for model parametersMASTER_CONFIG = {    # Adding parameters later}

这种方法保持了灵活性,允许在未来根据需要添加更多参数配置。

07.下载数据集

在最初的 LLaMA 论文中,他们采用了多种开源数据集来训练和评估模型。

img

遗憾的是,对于小型项目来说,利用大量数据集可能并不现实。因此,在我们的实施过程中,我们将采取一种更为温和的方法,创建一个大幅缩减的 LLaMA 版本。

考虑到无法获取海量数据的限制,我们将重点使用 TinyShakespeare 数据集训练简化版的 LLaMA。

链接:https://github.com/karpathy/char-rnn/blob/master/data/tinyshakespeare/input.txt

该开源数据集可在上述链接获取,包含约 40,000 行来自莎士比亚各种作品的文本。

LLaMA 是在一个包含 1.4 万亿个字符的庞大数据集上进行训练的,而我们的数据集 TinyShakespeare 包含约 100 万个字符。首先,让我们下载数据集:

# The URL of the raw text file on GitHuburl = "https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt"
# The file name for local storagefile_name = "tinyshakespeare.txt"
# Execute the downloadurllib.request.urlretrieve(url, file_name)

该 Python 脚本从指定的 URL 获取 tinyshakespeare 数据集,并以文件名 "tinyshakespeare.txt "保存到本地。

接下来,让我们确定词汇量的大小,它代表了数据集中唯一的字符数。下面是统计代码片段:

# Read the content of the datasetlines = open("tinyshakespeare.txt", 'r').read()# Create a sorted list of unique characters in the datasetvocab = sorted(list(set(lines)))
# Display the first 10 characters in the vocabulary listprint('Printing the first 10 characters of the vocab list:', vocab[:10])# Output the total number of characters in our dataset (Vocabulary Size)print('Total number of characters in our dataset (Vocabulary Size):', len(vocab))

img

接着,我们要在整数到字符 (itos) 和字符到整数 (stoi) 之间创建映射。代码如下:

# Mapping integers to characters (itos)itos = {i: ch for i, ch in enumerate(vocab)}# Mapping characters to integers (stoi)stoi = {ch: i for i, ch in enumerate(vocab)}

img

08.定义编解码函数

在最初的 LLaMA 论文中,使用了谷歌的 SentencePiece 字节对编码Tokenizer。不过,为了简单起见,我们将选择基本的字符级Tokenizer。让我们创建编码和解码函数,随后将其应用于我们的数据集:

# Encode function: Converts a string to a list of integers using the mapping stoidef encode(s):    return [stoi[ch] for ch in s]# Decode function: Converts a list of integers back to a string using the mapping itosdef decode(l):    return ''.join([itos[i] for i in l])# Example: Encode the string "hello" and then decode the resultdecode(encode("morning"))

最后一行将输出单词moning,以确认编码函数和解码函数的正常运行。

现在,我们将数据集转换为 torch 张量,指定其数据类型,以便使用 PyTorch 进行进一步操作:

# Convert the dataset into a torch tensor with specified data type (dtype)dataset = torch.tensor(encode(lines), dtype=torch.int8)# Display the shape of the resulting tensorprint(dataset.shape)

输出结果 torch.Size([1115394])显示,我们的数据集包含约一百万个Tokens。值得注意的是,这比包含 1.4 万亿个Tokens的 LLaMA 数据集要小得多。

09.拆分数据集

接着,我们将创建一个函数,负责将数据集拆分为训练集、验证集或测试集。在机器学习或深度学习项目中,这种拆分对于开发和评估模型至关重要,同样的原则也适用于大型语言模型(LLM)的训练过程:

# Function to get batches for training, validation, or testingdef get_batches(data, split, batch_size, context_window, config=MASTER_CONFIG):    # Split the dataset into training, validation, and test sets    train = data[:int(.8 * len(data))]    val = data[int(.8 * len(data)): int(.9 * len(data))]    test = data[int(.9 * len(data)):]    # Determine which split to use    batch_data = train    if split == 'val':        batch_data = val    if split == 'test':        batch_data = test    # Pick random starting points within the data    ix = torch.randint(0, batch_data.size(0) - context_window - 1, (batch_size,))    # Create input sequences (x) and corresponding target sequences (y)    x = torch.stack([batch_data[i:i+context_window] for i in ix]).long()    y = torch.stack([batch_data[i+1:i+context_window+1] for i in ix]).long()    return x, y

既然我们已经定义了切分函数,那么让我们来确定两个对这一过程至关重要的参数:

# Update the MASTER_CONFIG with batch_size and context_window parametersMASTER_CONFIG.update({    'batch_size': 8,          # Number of batches to be processed at each random split    'context_window': 16      # Number of characters in each input (x) and target (y) sequence of each batch})

batch_size 决定每次随机切分处理多少个批次,而 context_window 则指定每个批次的每个输入 (x) 和目标 (y) 序列中的字符数。

让我们以数据集的第 8 个批次和上下文窗口为16的训练集中打印一个随机样本:

# Obtain batches for training using the specified batch size and context windowxs, ys = get_batches(dataset, 'train', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Decode the sequences to obtain the corresponding text representationsdecoded_samples = [(decode(xs[i].tolist()), decode(ys[i].tolist())) for i in range(len(xs))]# Print the random sampleprint(decoded_samples)

结果如下:

img

10.评估策略

现在,我们将创建一个函数,专门用于评估我们自创的 LLaMA 架构。之所以要在定义实际模型方法之前这样做,是为了在训练过程中进行持续评估。

@torch.no_grad()  # Don't compute gradients for this functiondef evaluate_loss(model, config=MASTER_CONFIG):    # Placeholder for the evaluation results    out = {}
    # Set the model to evaluation mode    model.eval()    # Iterate through training and validation splits    for split in ["train", "val"]:        # Placeholder for individual losses        losses = []        # Generate 10 batches for evaluation        for _ in range(10):            # Get input sequences (xb) and target sequences (yb)            xb, yb = get_batches(dataset, split, config['batch_size'], config['context_window'])
            # Perform model inference and calculate the loss            _, loss = model(xb, yb)
            # Append the loss to the list            losses.append(loss.item())        # Calculate the mean loss for the split and store it in the output dictionary        out[split] = np.mean(losses)
    # Set the model back to training mode    model.train()
    return out

在训练迭代过程中,我们使用损失作为评估模型性能的指标。我们的函数迭代训练和验证集,计算每次拆分 10 次的平均损失,最后返回结果。然后使用 model.train() 将模型设置回训练模式。

11.建立基础神经网络

首先我们来构建一个基本的神经网络,稍后将利用 LLaMA 技术对其进行改进。

# Definition of a basic neural network classclass SimpleBrokenModel(nn.Module):    def __init__(self, config=MASTER_CONFIG):        super().__init__()        self.config = config        # Embedding layer to convert character indices to vectors (vocab size: 65)        self.embedding = nn.Embedding(config['vocab_size'], config['d_model'])        # Linear layers for modeling relationships between features        # (to be updated with SwiGLU activation function as in LLaMA)        self.linear = nn.Sequential(            nn.Linear(config['d_model'], config['d_model']),            nn.ReLU(),  # Currently using ReLU, will be replaced with SwiGLU as in LLaMA            nn.Linear(config['d_model'], config['vocab_size']),        )        # Print the total number of model parameters        print("Model parameters:", sum([m.numel() for m in self.parameters()]))

在当前的架构中,嵌入层的词汇量为 65 个,代表了我们数据集中的字符数目。由于这是我们的基础模型,我们在线性层中使用 ReLU 作为激活函数;不过,稍后将用 LLaMA 中使用的 SwiGLU 代替。

要为基础模型创建前向传递,我们必须在 NN 模型中定义一个forward函数。

# Definition of a basic neural network classclass SimpleBrokenModel(nn.Module):    def __init__(self, config=MASTER_CONFIG):        # Rest of the code                ...         # Forward pass function for the base model        def forward(self, idx, targets=None):            # Embedding layer converts character indices to vectors            x = self.embedding(idx)
            # Linear layers for modeling relationships between features            a = self.linear(x)
            # Apply softmax activation to obtain probability distribution            logits = F.softmax(a, dim=-1)            # If targets are provided, calculate and return the cross-entropy loss            if targets is not None:                # Reshape logits and targets for cross-entropy calculation                loss = F.cross_entropy(logits.view(-1, self.config['vocab_size']), targets.view(-1))                return logits, loss            # If targets are not provided, return the logits            else:                return logits        # Print the total number of model parameters        print("Model parameters:", sum([m.numel() for m in self.parameters()]))

这个前向传递函数将字符索引(idx)作为输入,应用嵌入层,将结果传递给线性层,应用 softmax 激活以获得概率分布(logits)。如果提供了目标,它会计算交叉熵损失,并同时返回 logits 和损失。如果没有提供目标,则只返回预测logits。

要实例化该模型,我们可以直接调用该类,并打印 "简单神经网络模型 "中的参数总数。我们将线性层的维数设置为 128,并在配置对象中指定了这一数值:

# Update MASTER_CONFIG with the dimension of linear layers (128)MASTER_CONFIG.update({    'd_model': 128,})# Instantiate the SimpleBrokenModel using the updated MASTER_CONFIGmodel = SimpleBrokenModel(MASTER_CONFIG)# Print the total number of parameters in the modelprint("Total number of parameters in the Simple Neural Network Model:", sum([m.numel() for m in model.parameters()]))

img

可以看到,我们的简单神经网络模型包含约 33,000 个参数。

12.训练基础神经网络

在定义了基本的神经网络结构后,为了计算损失,我们只需将拆分后的数据集输入模型即可:

# Obtain batches for training using the specified batch size and context windowxs, ys = get_batches(dataset, 'train', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Calculate logits and loss using the modellogits, loss = model(xs, ys)

为了训练该基础模型并记录其性能,我们需要指定一些参数。我们总共要训练 1000 个epoch。将batchsize从 8 增加到 32,并将 log_interval 设置为 10,表示代码将每 10 个批次打印或记录一次训练进度信息。在优化方面,我们将使用 Adam 优化器。

# Update MASTER_CONFIG with training parametersMASTER_CONFIG.update({    'epochs': 1000,          # Number of training epochs    'log_interval': 10,      # Log information every 10 batches during training    'batch_size': 32,        # Increase batch size to 32})# Instantiate the SimpleBrokenModel with updated configurationmodel = SimpleBrokenModel(MASTER_CONFIG)# Define the Adam optimizer for model parametersoptimizer = torch.optim.Adam(    model.parameters(),      # Pass the model parameters to the optimizer)

让我们执行训练过程,记录该基础模型的损失,包括参数总数。此外,为清晰起见,每一行都有注释:

# Function to perform trainingdef train(model, optimizer, scheduler=None, config=MASTER_CONFIG, print_logs=False):    # Placeholder for storing losses    losses = []
    # Start tracking time    start_time = time.time()    # Iterate through epochs    for epoch in range(config['epochs']):        # Zero out gradients        optimizer.zero_grad()        # Obtain batches for training        xs, ys = get_batches(dataset, 'train', config['batch_size'], config['context_window'])        # Forward pass through the model to calculate logits and loss        logits, loss = model(xs, targets=ys)        # Backward pass and optimization step        loss.backward()        optimizer.step()        # If a learning rate scheduler is provided, adjust the learning rate        if scheduler:            scheduler.step()        # Log progress every specified interval        if epoch % config['log_interval'] == 0:            # Calculate batch time            batch_time = time.time() - start_time
            # Evaluate loss on validation set            x = evaluate_loss(model)
            # Store the validation loss            losses += [x]
            # Print progress logs if specified            if print_logs:                print(f"Epoch {epoch} | val loss {x['val']:.3f} | Time {batch_time:.3f} | ETA in seconds {batch_time * (config['epochs'] - epoch)/config['log_interval'] :.3f}")
            # Reset the timer            start_time = time.time()            # Print learning rate if a scheduler is provided            if scheduler:                print("lr: ", scheduler.get_lr())    # Print the final validation loss    print("Validation loss: ", losses[-1]['val'])
    # Plot the training and validation loss curves    return pd.DataFrame(losses).plot()# Execute the training processtrain(model, optimizer)

img

训练前的初始交叉熵损失为 4.17,100 个epoch后基本收敛降至 3.93。

我们的基础模型在logits 后面加入了一个 softmax 层,将数字向量转换为概率分布。此外,我们在使用内置的 F.cross_entropy 函数时可以直接输入非规范化的 logits。因此,我们将对模型进行相应修改。

# Modified SimpleModel class without softmax layerclass SimpleModel(nn.Module):    def __init__(self, config):
       # Rest of the code       ...    def forward(self, idx, targets=None):        # Embedding layer converts character indices to vectors        x = self.embedding(idx)
        # Linear layers for modeling relationships between features        logits = self.linear(x)        # If targets are provided, calculate and return the cross-entropy loss        if targets is not None:            # Rest of the code            ...

让我们重新创建更新后的 SimpleModel,并对其进行 1000个 epoch训练,以观察其变化:

# Create the updated SimpleModelmodel = SimpleModel(MASTER_CONFIG)# Obtain batches for trainingxs, ys = get_batches(dataset, 'train', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Calculate logits and loss using the modellogits, loss = model(xs, ys)# Define the Adam optimizer for model parametersoptimizer = torch.optim.Adam(model.parameters())# Train the model for 100 epochstrain(model, optimizer)

img

100个epoch后将损失减小到 2.51 后,让我们来探索一下拥有约 33,000 个参数的语言模型如何在推理过程中生成文本。我们将创建一个 "generate "函数,代码如下:

# Generate function for text generation using the trained modeldef generate(model, config=MASTER_CONFIG, max_new_tokens=30):    idx = torch.zeros(5, 1).long()    for _ in range(max_new_tokens):        # Call the model        logits = model(idx[:, -config['context_window']:])        last_time_step_logits = logits[            :, -1, :        ]  # all the batches (1), last time step, all the logits        p = F.softmax(last_time_step_logits, dim=-1)  # softmax to get probabilities        idx_next = torch.multinomial(            p, num_samples=1        )  # sample from the distribution to get the next token        idx = torch.cat([idx, idx_next], dim=-1)  # append to the sequence    return [decode(x) for x in idx.tolist()]# Generate text using the trained modelgenerate(model)

img

我们的基本模型大约有 33K 个参数,生成的文本看起来并不出色。不过,既然我们已经为这个简单的模型奠定了基础,下一节我们将继续构建 LLaMA 架构。

13.复现LLama结构

在本文的前半部分,我们介绍了基本概念,现在,我们将把这些概念整合到我们的基础模型中。LLaMA 在原有 Transformer 的基础上引入了三项架构修改:

  • 用于前归一化的 RMSNorm
  • 旋转位置编码
  • SwiGLU 激活函数

我们将把这些修改逐一纳入基础模型,并在此基础上不断迭代和完善。

  • RMSNorm 用于前归一化:

我们正在定义一个具有以下功能的 RMSNorm 函数:

class RMSNorm(nn.Module):    def __init__(self, layer_shape, eps=1e-8, bias=False):        super(RMSNorm, self).__init__()        # Registering a learnable parameter 'scale' as a parameter of the module        self.register_parameter("scale", nn.Parameter(torch.ones(layer_shape)))    def forward(self, x):        """        Assumes shape is (batch, seq_len, d_model)        """        # Calculating the Frobenius norm, RMS = 1/sqrt(N) * Frobenius norm        ff_rms = torch.linalg.norm(x, dim=(1,2)) * x[0].numel() ** -.5        # Normalizing the input tensor 'x' with respect to RMS        raw = x / ff_rms.unsqueeze(-1).unsqueeze(-1)        # Scaling the normalized tensor using the learnable parameter 'scale'        return self.scale[:x.shape[1], :].unsqueeze(0) * raw

我们定义了 RMSNorm 类。在初始化过程中,它会注册一个scale参数。在前向传递过程中,它会对张量进行归一化处理。最后,根据注册的scale参数对张量进行缩放。该函数设计用于 LLaMA,以取代 LayerNorm 操作。

现在是时候将 LLaMA 的第一个实现概念 RMSNorm 融入我们的简单 NN 模型了。下面是更新后的代码:

# Define the SimpleModel_RMS with RMSNormclass SimpleModel_RMS(nn.Module):    def __init__(self, config):        super().__init__()        self.config = config        # Embedding layer to convert character indices to vectors        self.embedding = nn.Embedding(config['vocab_size'], config['d_model'])        # RMSNorm layer for pre-normalization        self.rms = RMSNorm((config['context_window'], config['d_model']))        # Linear layers for modeling relationships between features        self.linear = nn.Sequential(            # Rest of the code            ...        )        # Print the total number of model parameters        print("Model parameters:", sum([m.numel() for m in self.parameters()]))    def forward(self, idx, targets=None):        # Embedding layer converts character indices to vectors        x = self.embedding(idx)        # RMSNorm pre-normalization        x = self.rms(x)        # Linear layers for modeling relationships between features        logits = self.linear(x)        if targets is not None:            # Rest of the code            ...

让我们使用 RMSNorm 执行修改后的 NN 模型,并观察模型中更新的参数数量和损失:

# Create an instance of SimpleModel_RMSmodel = SimpleModel_RMS(MASTER_CONFIG)# Obtain batches for trainingxs, ys = get_batches(dataset, 'train', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Calculate logits and loss using the modellogits, loss = model(xs, ys)# Define the Adam optimizer for model parametersoptimizer = torch.optim.Adam(model.parameters())# Train the modeltrain(model, optimizer)

img

100个epoch后验证损失略有减少,更新后的 LLM 参数总数约为 55 000 个。

14.RoPE效果验证

接下来,我们将实现旋转位置嵌入。在 RoPE 中,作者建议通过旋转嵌入来嵌入序列中Token的位置信息,并在每个位置应用不同的旋转。让我们创建一个函数,模仿论文中 RoPE 的实际实现:

def get_rotary_matrix(context_window, embedding_dim):    # Initialize a tensor for the rotary matrix with zeros    R = torch.zeros((context_window, embedding_dim, embedding_dim), requires_grad=False)
    # Loop through each position in the context window    for position in range(context_window):        # Loop through each dimension in the embedding        for i in range(embedding_dim // 2):            # Calculate the rotation angle (theta) based on the position and embedding dimension            theta = 10000. ** (-2. * (i - 1) / embedding_dim)            # Calculate the rotated matrix elements using sine and cosine functions            m_theta = position * theta            R[position, 2 * i, 2 * i] = np.cos(m_theta)            R[position, 2 * i, 2 * i + 1] = -np.sin(m_theta)            R[position, 2 * i + 1, 2 * i] = np.sin(m_theta)            R[position, 2 * i + 1, 2 * i + 1] = np.cos(m_theta)    return R

我们根据指定的上下文窗口和嵌入维度,按照建议的 RoPE 实现方法生成旋转矩阵。

大家可能对Transformer的架构并不陌生,其中涉及注意力头,因此在实现 LLaMA 时,我们同样需要创建注意力头。此外,为了清晰起见,每一行都有注释:

class RoPEAttentionHead(nn.Module):    def __init__(self, config):        super().__init__()        self.config = config        # Linear transformation for query        self.w_q = nn.Linear(config['d_model'], config['d_model'], bias=False)        # Linear transformation for key        self.w_k = nn.Linear(config['d_model'], config['d_model'], bias=False)        # Linear transformation for value        self.w_v = nn.Linear(config['d_model'], config['d_model'], bias=False)        # Obtain rotary matrix for positional embeddings        self.R = get_rotary_matrix(config['context_window'], config['d_model'])    def get_rotary_matrix(context_window, embedding_dim):        # Generate rotational matrix for RoPE        R = torch.zeros((context_window, embedding_dim, embedding_dim), requires_grad=False)        for position in range(context_window):            for i in range(embedding_dim//2):
                # Rest of the code                ...        return R    def forward(self, x, return_attn_weights=False):        # x: input tensor of shape (batch, sequence length, dimension)        b, m, d = x.shape  # batch size, sequence length, dimension        # Linear transformations for Q, K, and V        q = self.w_q(x)        k = self.w_k(x)        v = self.w_v(x)        # Rotate Q and K using the RoPE matrix        q_rotated = (torch.bmm(q.transpose(0, 1), self.R[:m])).transpose(0, 1)        k_rotated = (torch.bmm(k.transpose(0, 1), self.R[:m])).transpose(0, 1)        # Perform scaled dot-product attention        activations = F.scaled_dot_product_attention(            q_rotated, k_rotated, v, dropout_p=0.1, is_causal=True        )        if return_attn_weights:            # Create a causal attention mask            attn_mask = torch.tril(torch.ones((m, m)), diagonal=0)            # Calculate attention weights and add causal mask            attn_weights = torch.bmm(q_rotated, k_rotated.transpose(1, 2)) / np.sqrt(d) + attn_mask            attn_weights = F.softmax(attn_weights, dim=-1)            return activations, attn_weights        return activations

现在,我们有了一个返回注意力权重的单头屏蔽注意力头,下一步就是创建一个多头注意力机制。

class RoPEMaskedMultiheadAttention(nn.Module):    def __init__(self, config):        super().__init__()        self.config = config        # Create a list of RoPEMaskedAttentionHead instances as attention heads        self.heads = nn.ModuleList([            RoPEMaskedAttentionHead(config) for _ in range(config['n_heads'])        ])        self.linear = nn.Linear(config['n_heads'] * config['d_model'], config['d_model'])  # Linear layer after concatenating heads        self.dropout = nn.Dropout(.1)  # Dropout layer    def forward(self, x):        # x: input tensor of shape (batch, sequence length, dimension)        # Process each attention head and concatenate the results        heads = [h(x) for h in self.heads]        x = torch.cat(heads, dim=-1)
        # Apply linear transformation to the concatenated output        x = self.linear(x)
        # Apply dropout        x = self.dropout(x)        return x

原论文在较小的 7b LLM 变体中使用了 32 个head,但由于条件限制,我们的方法将使用 8 个head。

# Update the master configuration with the number of attention headsMASTER_CONFIG.update({    'n_heads': 8,})

现在我们已经实现了旋转位置嵌入和多头注意力,让我们用更新后的代码重新编写 RMSNorm 神经网络模型。我们将测试其性能、计算损失并检查参数数量。我们将把更新后的模型称为 “RopeModel”。

class RopeModel(nn.Module):    def __init__(self, config):        super().__init__()        self.config = config        # Embedding layer for input tokens        self.embedding = nn.Embedding(config['vocab_size'], config['d_model'])
        # RMSNorm layer for pre-normalization        self.rms = RMSNorm((config['context_window'], config['d_model']))
        # RoPEMaskedMultiheadAttention layer        self.rope_attention = RoPEMaskedMultiheadAttention(config)        # Linear layer followed by ReLU activation        self.linear = nn.Sequential(            nn.Linear(config['d_model'], config['d_model']),            nn.ReLU(),        )        # Final linear layer for prediction        self.last_linear = nn.Linear(config['d_model'], config['vocab_size'])        print("model params:", sum([m.numel() for m in self.parameters()]))    def forward(self, idx, targets=None):        # idx: input indices        x = self.embedding(idx)        # One block of attention        x = self.rms(x)  # RMS pre-normalization        x = x + self.rope_attention(x)        x = self.rms(x)  # RMS pre-normalization        x = x + self.linear(x)        logits = self.last_linear(x)        if targets is not None:            loss = F.cross_entropy(logits.view(-1, self.config['vocab_size']), targets.view(-1))            return logits, loss        else:            return logits

让我们使用 RMSNorm、旋转位置嵌入和多头注意力来执行修改后的 NN 模型,以观察模型中参数数量的更新情况以及损失情况:

# Create an instance of RopeModel (RMSNorm, RoPE, Multi-Head)model = RopeModel(MASTER_CONFIG)# Obtain batches for trainingxs, ys = get_batches(dataset, 'train', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Calculate logits and loss using the modellogits, loss = model(xs, ys)# Define the Adam optimizer for model parametersoptimizer = torch.optim.Adam(model.parameters())# Train the modeltrain(model, optimizer)

img

100个epoch后验证损失再次出现小幅下降,更新后的 LLM 参数总数约为 55 000。让我们对模型进行更多的epoch训练,看看重新创建的 LLaMA LLM 的损失是否会继续减少。

# Updating training configuration with more epochs and a logging intervalMASTER_CONFIG.update({    "epochs": 5000,    "log_interval": 10,})# Training the model with the updated configurationtrain(model, optimizer)

img

500个epoch后验证损失继续减少,这表明进行更多的epoch训练可以进一步减少损失,尽管减少的幅度不大。

15.采用SwiGLU激活函数

如前所述,LLaMA 的创建者使用 SwiGLU 而不是 ReLU,因此我们将在代码中实现 SwiGLU 方程。

img

代码实现如下:

class SwiGLU(nn.Module):    """ Paper Link -> https://arxiv.org/pdf/2002.05202v1.pdf """    def __init__(self, size):        super().__init__()        self.config = config  # Configuration information        self.linear_gate = nn.Linear(size, size)  # Linear transformation for the gating mechanism        self.linear = nn.Linear(size, size)  # Linear transformation for the main branch        self.beta = torch.randn(1, requires_grad=True)  # Random initialization of the beta parameter        # Using nn.Parameter for beta to ensure it's recognized as a learnable parameter        self.beta = nn.Parameter(torch.ones(1))        self.register_parameter("beta", self.beta)    def forward(self, x):        # Swish-Gated Linear Unit computation        swish_gate = self.linear_gate(x) * torch.sigmoid(self.beta * self.linear_gate(x))        out = swish_gate * self.linear(x)  # Element-wise multiplication of the gate and main branch        return out

接着我们需要将其集成到修改后的 LLaMA 语言模型(RopeModel)中。

class RopeModel(nn.Module):    def __init__(self, config):        super().__init__()        self.config = config        # Embedding layer for input tokens        self.embedding = nn.Embedding(config['vocab_size'], config['d_model'])
        # RMSNorm layer for pre-normalization        self.rms = RMSNorm((config['context_window'], config['d_model']))
        # Multi-head attention layer with RoPE (Rotary Positional Embeddings)        self.rope_attention = RoPEMaskedMultiheadAttention(config)        # Linear layer followed by SwiGLU activation        self.linear = nn.Sequential(            nn.Linear(config['d_model'], config['d_model']),            SwiGLU(config['d_model']),  # Adding SwiGLU activation        )        # Output linear layer        self.last_linear = nn.Linear(config['d_model'], config['vocab_size'])        # Printing total model parameters        print("model params:", sum([m.numel() for m in self.parameters()]))    def forward(self, idx, targets=None):        x = self.embedding(idx)        # One block of attention        x = self.rms(x)  # RMS pre-normalization        x = x + self.rope_attention(x)        x = self.rms(x)  # RMS pre-normalization        x = x + self.linear(x)  # Applying SwiGLU activation        logits = self.last_linear(x)        if targets is not None:            # Calculate cross-entropy loss if targets are provided            loss = F.cross_entropy(logits.view(-1, self.config['vocab_size']), targets.view(-1))            return logits, loss        else:            return logits

让我们使用 RMSNorm、旋转嵌入、多头注意力和 SwiGLU 来执行修改后的 NN 模型,以观察模型中参数数量的更新情况以及损失情况:

# Create an instance of RopeModel (RMSNorm, RoPE, Multi-Head, SwiGLU)model = RopeModel(MASTER_CONFIG)# Obtain batches for trainingxs, ys = get_batches(dataset, 'train', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Calculate logits and loss using the modellogits, loss = model(xs, ys)# Define the Adam optimizer for model parametersoptimizer = torch.optim.Adam(model.parameters())# Train the modeltrain(model, optimizer)

img

在训练500个epoch后,验证损失再次出现小幅下降,更新后的 LLM 参数总数约为 60,000 个。

到目前为止,我们已经成功实现了本文的关键部分,即 RMSNorm、RoPE 和 SwiGLU。我们注意到,这些实施方法使损失减少到最低程度。

16.扩大模型规模

现在,我们将为 LLaMA 增加层数,以检验其对损失的影响。原论文的 7b 版本使用了 32 个Transformer Block Layer,但我们将只使用 4 个。让我们相应地调整模型设置。

# Update model configurations for the number of layersMASTER_CONFIG.update({    'n_layers': 4,  # Set the number of layers to 4})

让我们先创建一个Transformer Block,了解它的影响。

# add RMSNorm and residual connectionclass LlamaBlock(nn.Module):    def __init__(self, config):        super().__init__()        self.config = config        # RMSNorm layer        self.rms = RMSNorm((config['context_window'], config['d_model']))        # RoPE Masked Multihead Attention layer        self.attention = RoPEMaskedMultiheadAttention(config)        # Feedforward layer with SwiGLU activation        self.feedforward = nn.Sequential(            nn.Linear(config['d_model'], config['d_model']),            SwiGLU(config['d_model']),        )    def forward(self, x):        # one block of attention        x = self.rms(x) # RMS pre-normalization        x = x + self.attention(x)  # residual connection        x = self.rms(x) # RMS pre-normalization        x = x + self.feedforward(x)  # residual connection        return x

创建 LlamaBlock 类的实例,并将其应用于随机张量。

# Create an instance of the LlamaBlock class with the provided configurationblock = LlamaBlock(MASTER_CONFIG)# Generate a random tensor with the specified batch size, context window, and model dimensionrandom_input = torch.randn(MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'], MASTER_CONFIG['d_model'])# Apply the LlamaBlock to the random input tensoroutput = block(random_input)

在成功创建了单层之后,我们现在可以用它来构建多层。此外,我们将把模型类从 "ropemodel "更名为 “Llama”,因为我们已经实现了 LLaMA 语言模型的每个组件。

class Llama(nn.Module):    def __init__(self, config):        super().__init__()        self.config = config        # Embedding layer for token representations        self.embeddings = nn.Embedding(config['vocab_size'], config['d_model'])        # Sequential block of LlamaBlocks based on the specified number of layers        self.llama_blocks = nn.Sequential(            OrderedDict([(f"llama_{i}", LlamaBlock(config)) for i in range(config['n_layers'])])        )        # Feedforward network (FFN) for final output        self.ffn = nn.Sequential(            nn.Linear(config['d_model'], config['d_model']),            SwiGLU(config['d_model']),            nn.Linear(config['d_model'], config['vocab_size']),        )        # Print total number of parameters in the model        print("model params:", sum([m.numel() for m in self.parameters()]))    def forward(self, idx, targets=None):        # Input token indices are passed through the embedding layer        x = self.embeddings(idx)        # Process the input through the LlamaBlocks        x = self.llama_blocks(x)        # Pass the processed input through the final FFN for output logits        logits = self.ffn(x)        # If targets are not provided, return only the logits        if targets is None:            return logits        # If targets are provided, compute and return the cross-entropy loss        else:            loss = F.cross_entropy(logits.view(-1, self.config['vocab_size']), targets.view(-1))            return logits, loss

让我们使用 RMSNorm、旋转嵌入、多头注意力、SwiGLU 和 N_layers 执行修改后的 LLaMA 模型,以观察模型中更新的参数数量和损失:

# Create an instance of RopeModel (RMSNorm, RoPE, Multi-Head, SwiGLU, N_layers)llama = Llama(MASTER_CONFIG)# Obtain batches for trainingxs, ys = get_batches(dataset, 'train', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Calculate logits and loss using the modellogits, loss = llama(xs, ys)# Define the Adam optimizer for model parametersoptimizer = torch.optim.Adam(llama.parameters())# Train the modeltrain(llama, optimizer)

img

虽然存在过拟合的可能性,但关键是要探索延长epoch数目是否会进一步减少损失。此外,请注意我们目前的 LLM 有 200 多万个参数。

让我们用更多的epoch来训练它。

# Update the number of epochs in the configurationMASTER_CONFIG.update({    'epochs': 10000,})# Train the LLaMA model for the specified number of epochstrain(llama, optimizer, scheduler=None, config=MASTER_CONFIG

img

这里的损失为 1.08,我们可以获得更低的损失,而不会遇到明显的过拟合。这表明该模型表现良好。

17.推理验证

到目前为止,我们已经在自定义数据集上成功实现了 LLaMA 架构的缩小版。现在,让我们检查一下 200 万参数语言模型的生成输出。

# Generate text using the trained LLM (llama) with a maximum of 500 tokensgenerated_text = generate(llama, MASTER_CONFIG, 500)[0]print(generated_text)

img

尽管生成的一些单词可能不是完美的英语,但我们的 LLM 仅用 200 万个参数就显示出了对英语的基本理解。

现在,让我们看看我们的模型在测试集上的表现如何。

# Get batches from the test setxs, ys = get_batches(dataset, 'test', MASTER_CONFIG['batch_size'], MASTER_CONFIG['context_window'])# Pass the test data through the LLaMA modellogits, loss = llama(xs, ys)# Print the loss on the test setprint(loss)

测试集的计算损失约为 1.236。

18.超参数实验

超参数调整是训练神经网络的关键步骤。在最初的 Llama 论文中,作者使用了余弦退火学习策略。然而,在我们的实验中,它的表现并不理想。下面是一个使用不同学习策略进行超参数实验的例子:

# Update configurationMASTER_CONFIG.update({    "epochs": 1000})# Create Llama model with Cosine Annealing learning schedulellama_with_cosine = Llama(MASTER_CONFIG)# Define Adam optimizer with specific hyperparametersllama_optimizer = torch.optim.Adam(    llama.parameters(),    betas=(.9, .95),    weight_decay=.1,    eps=1e-9,    lr=1e-3)# Define Cosine Annealing learning rate schedulerscheduler = torch.optim.lr_scheduler.CosineAnnealingLR(llama_optimizer, 300, eta_min=1e-5)# Train the Llama model with the specified optimizer and schedulertrain(llama_with_cosine, llama_optimizer, scheduler=scheduler)

19.保存模型

大家可以使用以下方法保存整个 LLM :

# Save the entire modeltorch.save(llama, 'llama_model.pth')# If you want to save only the model parameterstorch.save(llama.state_dict(), 'llama_model_params.pth')

要为 Hugging Face 的 Transformers 库保存 PyTorch 模型,可以使用 save_pretrained 方法。下面是一个例子:

from transformers import GPT2LMHeadModel, GPT2Config# Assuming Llama is your PyTorch modelllama_config = GPT2Config.from_dict(MASTER_CONFIG)llama_transformers = GPT2LMHeadModel(config=llama_config)llama_transformers.load_state_dict(llama.state_dict())# Specify the directory where you want to save the modeloutput_dir = "llama_model_transformers"# Save the model and configurationllama_transformers.save_pretrained(output_dir)

GPT2Config 用于创建与 GPT-2 兼容的配置对象。然后,创建 GPT2LMHeadModel 并加载 Llama 模型的权重。最后,调用 save_pretrained 将模型和配置保存在指定目录中。

然后就可以使用Transformer库加载模型了:

from transformers import GPT2LMHeadModel, GPT2Config# Specify the directory where the model was savedoutput_dir = "llama_model_transformers"# Load the model and configurationllama_transformers = GPT2LMHeadModel.from_pretrained(output_dir)

20.结论

在本文中,我们逐步介绍如何采用 LLaMA 方法来构建自己的小型语言模型 (LLM)。作为建议,您可以考虑将模型扩展到 1,500 万个参数左右,因为 1,000 万到 2,000 万个参数范围内的小型模型往往能更好地理解英语。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范
  • …

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署
  • …

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建
  • …

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案
  • …

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费】

在这里插入图片描述

PyTorch原生训练大语言模型:从零构建LLM训练循环 大语言模型(LLM)训练本质上是深度神经网络在超大规模参数空间中的优化过程,其核心原理涵盖前向传播、自动微分、梯度下降与分布式协同。技术价值在于突破封装黑箱,实现对显存占用、梯度流动、精度控制和并行策略的全链路掌控。典型应用场景包括学术研究中的机制验证、工业场景下的定制化模型锻造,以及GPU资源受限环境下的轻量级LLM训练。本文聚焦PyTorch原生训练与LLM底层实现,详解从Dataset数据管道、nn.Module模型构建、混合精度训练(AMP)到分布式数据并行(DDP)的完整闭环,覆盖从零构建训练循环 阅读详情

相关推荐

Unlimiformer原理与实战:让Transformer原生支持百万token长文本

Transformer的自注意力机制因O(n²)复杂度天然受限于输入长度,导致长文本建模成为NLP工程落地的核心瓶颈。其本质是序列建模能力与计算效率之间的根本矛盾——模型需全局感知,但硬件与算法难以支撑。Unlimiformer不修改模型结构、不重训、不替换算子,而是将长输入视为外部知识库,利用模型最后一层隐藏状态实现语义对齐的动态检索,并在精选片段上执行原生注意力,从而在保持训练一致性的前提下突破长度限制。该方法兼具理论严谨性与工程鲁棒性,广泛适用于法律合同审查、RAG系统构建、会议纪要生成等真实场景,是

weixin_32112641的博客 288

如何训练2457亿参数量的中文巨量模型“源1.0”

如何训练2457亿参数量的中文巨量模型“源1.0” 浪潮人工智能研究院 从2018年的BERT到2020年的GPT-3,NLP语言模型经历了爆发式的发展过程,其中BERT模型的参数量为3.4亿,而GPT-3的模型参数量达到了1750亿。2021年9月,浪潮人工智能研究院发布了“源1.0”,它是目前规模最大的中文AI单体模型,参数规模高达2457亿,训练采用的中文数据集达5TB。“源1.0”在语言智能方面表现优异,获得中文语言理解评测基准CLUE榜单的零样本学习和小样本学习两类总榜冠军。测试结果显示,人群

AI科技大本营 1487

万字长文:大模型时代客服系统架构演进:从传统NLP到LLM+RAG的技术跃迁之路

无论是规则引擎还是传统NLP,本质都是**“预定义逻辑”**——所有能处理的问题,都必须是工程师提前想到的。用户可能用方言提问(“我买的鞋子挤脚得很,能退不?”);用户可能用隐喻(“你们的快递比蜗牛还慢,什么时候到?”);用户可能问跨领域问题(“我买的手机充电慢,是不是和你们的数据线有关?”)。传统系统根本无法处理这些“未预定义”的场景——这就是它的“死穴”。规则引擎时代:客服是“工具”,只能处理预设的问题;传统NLP时代:客服是“助手”,能理解简单的语义;

AI 领航者的博客 904

万字长文教你从零实现百万参数LLM训练_llm是怎么生成

在这篇文章中,我们将尝试制作一个只有 230 万个参数的 LLM,有趣的是,我们不需要特别多的 GPU。除这些概念外,LLaMA 论文还介绍了其他重要方法,包括使用带有特定参数的 AdamW 优化器、高效实现(如 xformers 库中的因果多头注意力算子),以及手动实现Transformer层的后向传播函数,以优化后向传播过程中的计算。让我们相应地调整模型设置。在当前的架构中,嵌入层的词汇量为 65 个,代表了我们数据集中的字符数目。让我们创建一个函数,模仿论文中 RoPE 的实际实现:​​​​​​​。

2401_85116933的博客 626

机器人示教器方案昆仑通态脚本实现( 三菱FX3U+昆仑通态3轴联动))

项目应用场景:最终客户需要自由的修改程序流程,如检测什么信号,多少时间,再进入下一步,轴定位轨迹可以自由修改,方便最终可以在不修改PLC程序的情况下,自由示教程序。3.指令数量可以自行添加,在内存足够的情况下,无限制,只需要在PLC框架里面写好每个指令执行的内容就可以了,不需要在程序里面重复写相同类容;4.模板有延时指令,输入指令,输出指令,伺服定位指令,焊钳控制指令,自动修磨指令,转矩模式指令,结束指令等(可自行添加);1.有类似示教器编程功能,可以任意位置插入指令,可以任意位置删除指令;

huanyuecuiyu的博客 970

FPGA时钟架构解密:从SRCC/MRCC到全局时钟树的实战指南

本文深入解析Xilinx 7系列FPGA时钟架构,从SRCC/MRCC引脚特性到全局时钟树设计,详细介绍了BUFG、BUFMR等关键组件的应用场景和优化策略。通过对比SRCC与MRCC的驱动范围及适用场景,提供低抖动时钟布线技巧和时钟域交叉(CDC)设计方法,帮助工程师构建高性能FPGA时钟系统。

weixin_29191081的博客 1484

用Glyph实现AI速读,处理百万字小说不再难

本文介绍了如何在星图GPU平台上自动化部署Glyph-视觉推理镜像,实现AI对百万字小说的高效速读与深度理解。该镜像将长文本渲染为高密度图像,由视觉语言模型解析,典型应用于跨章节人物关系梳理、伏笔追踪及风格化续写等小说分析场景。

weixin_42560991的博客 631

AI大模型与碳足迹评估结合模式及示范案例

AI大模型与碳足迹评估相结合,可以提供更精确、更快速的碳排放量计算,优化减排策略,并促进可持续发展目标的实现。

贾贾的博客 3943

3 万字硬核长文:一文吃透大语言模型 LLM 的底层原理与工作机制

3 万字硬核长文:一文吃透大语言模型 LLM 的底层原理与工作机制

2301_76168381的博客 3613

华为OD机考双机位C卷 - 斗地主之顺子 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 斗地主之顺子(OD上机考试双机位C卷)。提供在线OJ刷题。Java、C++、Python、GO语言、C语言、JavaScript题解,并提供完整思路讲解。

算法大师! 9693

【原理图PCB专题】Allegro模块化移动器件报...has the LOCKED property怎么解锁?

正常来说做好一个模块化,如果不需要再动,最好还是lock,防止不明白的工程师异动导致问题。如果复用布局设计时,因为有些器件和拓扑并不完全一致,那需要调整部分器件,被锁之后只能全选,无法修改。所以解开锁定后,就能正常编辑了。

一点硬件 2391

无需训练,100%完美检索!LLM练出「火眼金睛」,InfiniRetri超长文本一针见血

在处理超长文本时,大语言模型(LLM)的上下文窗口限制一直是难以逾越的障碍。近日,新研究提出了一种革命性方法——,通过利用LLM自身的注意力机制,无需额外训练即可实现对百万级token的精准检索,甚至让7B参数模型的性能媲美72B巨型模型。本文将深入解析这一突破性技术的核心原理与实验成果。

东方佑 1358

基于 STM32 的便携式肌电信号采集与疲劳度评估系统设计与实现

本系统以 STM32 单片机为核心控制器,通过肌电电极采集人体骨骼肌表面的 sEMG 信号,经仪表放大、滤波、AD 采样后送入 MCU 进行时域 / 频域特征提取,利用 RMS(均方根)、MPF(中位频率)、MF(平均频率)等指标实时评估肌肉疲劳状态,最终通过 OLED 显示疲劳等级,并支持蓝牙上传至上位机。

weixin_42300449的博客 105

清华团队突破:AI实现图像式百万字长文档记忆

清华团队突破:AI实现图像式百万字长文档记忆

weixin_49122920的博客 1011

YOLOv8与Swin Transformer的完美结合:如何提升目标检测的精度与速度

Swin Transformer(Shifted Window Transformer)是一种新型的视觉Transformer架构,采用了局部窗口(Window)和局部窗口偏移(Shifted Window)的策略,极大减少了计算复杂度,同时保持了全局感知能力。局部窗口注意力:每个窗口内的元素进行自注意力计算,减少计算量。窗口偏移:通过在不同层次引入窗口偏移,增强了全局信息的交互。层级设计:通过堆叠多个层次的模块,逐渐捕捉不同尺度的特征。

shrgegrb的博客 2151

基于混合智能框架的景区边界范围预测与补全系统

摘要 本文提出一种混合智能框架,结合随机森林模型和GIS规则约束,解决景区边界缺失问题。系统基于Python和ArcGIS平台,利用多源地理空间数据训练随机森林分类器预测景区范围,并集成地形、水文、道路等GIS规则进行优化。实验结果表明,该方法能有效预测15000个景区的边界,精度优于单一模型。创新点在于: 1)数据驱动与知识驱动相结合的混合智能范式; 2)面向全国尺度的大规模边界补全; 3)提供完整的Python+ArcGIS实现方案。该系统为景区精细化管理提供了技术支撑,具有实用价值。

huanghm88的专栏 282

别再瞎找了!大语言模型(LLM)核心原理,吃透这篇“万字长文”就够了!

如果零散地看大语言模型的相关描述:有人说大模型是预测下一个词的模型,有人说大模型是将词转化为向量,有人说大模型运用了自注意力机制,还有人指出大模型采用无监督学习和强化学习……让人看得眼花缭乱。

m0_59235945的博客 939

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

无限上下文新突破!无需RAG和长文本模型,也能实现超强检索!一篇带你彻底掌握!

这些被“重点关注”的句子被存储在一个外部缓存中,如同大脑在阅读过程中记住的关键情节。在处理后续的文本片段时,InfiniRetri 会将缓存中保留的相关句子与当前片段进行合并,共同作为 LLM 的输入。这种机制使得 LLM 在处理局部文本时,能够“回忆”起先前被认为重要的上下文信息,从而在整体上理解和处理更长的文本。与直接缓存模型内部状态不同,InfiniRetri 仅缓存关键的句子文本,这更类似于人类记忆语义信息而非底层的神经元激活。

m0_59235945的博客 1761

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

如何将 LLM 的上下文扩展至百万级?

在2023年初,即便是当时最先进的GPT-3.5,其上下文长度也仅限于2k。然而,时至今日,1M的上下文长度已经成为衡量模型技术先进性的重要标志之一。如果把 LLM 比作新时代的操作系统,上下文窗口便是它的「内存」。一个现代的操作系统需要足够大的内存才能完成各种各样的复杂任务。与之类似,一个优秀的 LLM 也需要足够长的上下文长度来完成各种复杂的任务。基于此种观念,GLM 技术团队经过不断的技术迭代,从最初的仅支持2K上下文的ChatGLM-6B,发展到ChatGLM2-6B(32K)、ChatGLM3-6

python12222_的博客 1047

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Glyph vs 传统LLM:谁更适合长文本?

本文介绍了如何在星图GPU平台上自动化部署Glyph-视觉推理镜像,实现长文本的高效理解与问答。该镜像将小说、法律合同、科研论文等数十万字文档渲染为高信息密度图像,交由视觉语言模型处理,显著提升上下文利用率与推理速度,适用于合同审查、学术综述、企业知识管理等典型场景。

weixin_35414260的博客 335

告别Token焦虑!Glyph让LLM处理百万级文本更简单

本文介绍了如何在星图GPU平台上自动化部署Glyph-视觉推理镜像,突破传统LLM的Token限制,实现百万级长文本的高效理解。通过将PDF、代码、网页等文档智能渲染为高信息密度图像,该镜像可直接应用于法务合同审阅、科研论文速读和代码库全局分析等典型场景,显著提升超长文档处理效率。

weixin_35899324的博客 489

LIFT框架:让短上下文LLM也能理解超长文本

论文标题:LIFT: Improving Long Context Understanding through Long Input Fine-Tuning机构:多机构联合研究(待更新)

raintBN的博客 1802

happy_llm学习08—什么是 LLM

大语言模型(LLM)是指具有大规模参数量的语言模型,通常在数十亿甚至数万亿个参数级别以上。这类模型通过在海量文本数据上进行预训练,学习到丰富的语言结构、知识和推理能力。一般来说,LLM 指包含数百亿(或更多)参数的语言模型,它们往往在数 T token 语料上通过多卡分布式集群进行预训练,具备远超出传统预训练模型的文本理解与生成能力。不过,随着 LLM 研究的不断深入,多种参数尺寸的 LLM 逐渐丰富,广义的 LLM 一般覆盖了从十亿参数到万亿参数的所有大型语言模型。只要模型展现出涌现能力。

weixin_65615457的博客 1034

B站开源长文本大模型:我很小但很能“装”

B站开源长文本大模型:我很小但很能“装”

2301_81940605的博客 1437
上一篇: langgraph:基于agent和qwen2.5构造一个多功能机器人,私有化部署
下一篇: Qwen3 低成本手撕Search-R1的强化学习训练框架
Python_金钱豹
博客等级 码龄5年 1万+粉丝 2835原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值