当前位置: 首页 > news >正文

知微集:Transformer

欢迎来到"一起学点什么吧"的合集「NLP知微集」。在这里,我们不愿宏大叙事,只聚焦于自然语言处理领域中那些细微却关键的“齿轮”与“螺丝钉”。我相信,真正深刻的理解,源于对细节的洞察。本期,我将为您拆解的是:[Transformer]

Transformer概述

Transformer 是一种深度学习架构,旨在通过捕捉序列中元素之间的上下文关系和依赖来处理序列数据,例如文本或时间序列。它们在自然语言处理(NLP)领域取得了巨大成功,特别是在涉及序列到序列学习任务的领域,如语言翻译、文本生成、文本摘要、情感分析等。

Transformer 架构最早于 2017 年由 Vaswani 等人在论文《Attention is All You Need》中提出。它摒弃了当时用于序列任务的传统神经网络算法,如循环神经网络(RNN)、长短期记忆网络(LSTM)和卷积神经网络(CNN)

在这里插入图片描述

Transformer架构

在这里插入图片描述

注意力机制

注意力机制是现代深度学习架构中的一个关键组成部分,特别是在序列到序列任务和自然语言处理(NLP)模型如 Transformer 中。注意力机制允许模型在处理每个元素时权衡输入序列不同部分的重要性,这对于捕获长距离依赖关系和提高在各种任务上的性能至关重要。

注意力相关

  • Attention(注意力):也称为缩放点积注意力,是指在处理当前token时,为所有其他输入token分配重要性权重的机制
  • Self-attention(自注意力):根据输入序列中的token为输入token分配重要性权重
  • Cross Attention(交叉注意力):当根据来自其他序列的token为输入token分配重要性权重时,则称为交叉注意力。这通常用于机器翻译任务,输入句子的编码用于为输出序列的token分配权重
  • Masked Self-Attention(掩码自注意力):输入序列中的一些token被故意排除(掩码)不参与注意力权重的计算。例如,在训练机器翻译模型的解码器层时,未来的词会被掩码。这通常在处理掩码语言建模任务时进行
  • Multi-headed Attention(多头注意力):在同一个输入序列上并行使用多个自注意力头。这通常是为了让每个头学习数据的不同方面或模式。所有头的输出被连接并进行线性变换以获得最终输出。
  • Masked Multi-Head Attention(掩码多头注意力):在同一个输入上并行使用多个掩码自注意力头

自注意力机制

在这里插入图片描述

逐步解释:

  • 输入token

    • 假设我们每次处理 n 个 token,其中每个 token 表示为维度 embed 的嵌入,那么我们可以将输入表示为一个 X 维的矩阵 dim(n, embed)
    • 对于第一层,token 嵌入来自一个静态的嵌入查找矩阵,而对于后续层,前一层输出被用作下一层的 token 嵌入。
  • Key、Query 和 Value 投影矩阵及相关向量

    • 对于每个自注意力头,初始化以下三个 dim(embed, head_size) 维的投影矩阵:Key ( WKW^KWK )、Query ( WQW^QWQ ) 和 Value ( WVW^VWV )。
    • 输入 token 嵌入与这些投影矩阵相乘,为每个 token 生成 Key( kkk )、Query( qqq )和 Value( vvv )向量
  • 点积注意力

    • 自注意力机制的核心操作是查询向量(Query)和键向量(Key)之间的点积。它衡量了基于查询向量,应该给予每个(键)token多少注意力。

    • 对于给定的token n (我们称之为查询token),通过将token nqnq_nqn )的查询向量与每个其他token( kik_iki )的键向量进行点积,计算来自每个其他token的注意力分数,即
      Attention(Tokenn,Tokeni)=qn∗ki Attention(Token_n,Token_i)=q_n * k_i Attention(Tokenn,Tokeni)=qnki

    • 缩放点积以计算注意力权重:为了稳定训练,点积通常会通过 Key 向量的维度的平方根(通常表示为 dkd_kdk )进行缩放
      Attention(Tokenn,Tokeni)=(qn∗ki)/sqrt(dk) Attention(Token_n,Token_i)=(q_n*k_i)/sqrt(d_k) Attention(Tokenn,Tokeni)=(qnki)/sqrt(dk)

    • 归一化注意力权重:对于每个查询token,注意力分数使用 softmax 进行归一化,使其总和为 1
      Attentionweights[Tokenn,Tokeni]=softmax(Attention(Tokenn,Tokeni)) Attention_{weights}[Token_n,Token_i]=softmax(Attention(Token_n,Token_i)) Attentionweights[Tokenn,Tokeni]=softmax(Attention(Tokenn,Tokeni))

  • 加权值之和:每个 Query 的输出是 Values 的加权组合,其中权重由注意力分数决定
    Output[Tokenn]=sum(Attentionweights[Tokenn,Tokeni]∗V[i]  for  i  in  range(sequence length)) Output[Token_n]=sum(Attention_{weights}[Token_n, Token_i] * V[i]\; for\; i\; in\; range(sequence\,length)) Output[Tokenn]=sum(Attentionweights[Tokenn,Tokeni]V[i]foriinrange(sequencelength))

在许多基于序列的任务中,例如机器翻译或文本摘要,当生成输出序列时,通常需要根据输入序列的不同部分赋予不同的重要性。传统的序列模型,如循环神经网络(RNNs),在有效捕捉长距离依赖关系方面存在局限性。注意力机制通过允许模型动态地“关注”输入序列的特定部分来解决这些局限性。

自注意力机制之所以强大,是因为它允许模型在预测特定位置时,能够同时(并并行地)评估输入序列中的所有位置。这使得模型能够捕捉长距离依赖关系和元素之间的关系,因此对于自然语言理解和生成等任务至关重要。此外,使用多个注意力头允许模型学习输入标记之间的不同类型的依赖关系和模式,使其具有高度的表达能力。

import torch
import torch.nn as nn
import torch.nn.functional as Fclass SelfAttention(nn.Module):"""自注意力机制实现自注意力机制允许模型动态地关注输入序列中不同位置的信息,通过计算输入信息之间的相关性,对输入数据的重要性进行加权处理。"""def __init__(self, d_model):"""初始化自注意力层Arguments:d_model: 输入特征的维度,也是Q、K、V的维度"""super(SelfAttention, self).__init__()self.d_model = d_model  # 特征维度# 定义三个线性变换层,用于生成Query、Key和Value# 设输入特征为I,分别将其乘以三个矩阵Wq、Wk和Wv得到Q(query)、K(key)和V(value)三个矩阵 self.query = nn.Linear(d_model, d_model, bias=False)self.key = nn.Linear(d_model, d_model, bias=False)self.value = nn.Linear(d_model, d_model, bias=False)# 注意:在实际的Transformer实现中,通常会将d_model分成多个头(h),每个头的维度为d_k=d_model/h# 但本实现为简化版的单头自注意力机制def forward(self, x):"""前向传播计算Arguments:x: 输入张量,形状为(batch_size, seq_len, d_model)Returns:输出张量,形状与输入相同(batch_size, seq_len, d_model)"""batch_size, seq_len, _ = x.size()# 1. 通过线性变换生成Query、Key和Value# Self-Attention Layer 一次检查同一句子中的所有单词的注意力,这使得它成为一个简单的矩阵计算,并且能够在计算单元上并行计算。Q = self.query(x)  # (batch_size, seq_len, d_model)K = self.key(x)    # (batch_size, seq_len, d_model)V = self.value(x)  # (batch_size, seq_len, d_model)# 2. 计算注意力分数 (Attention Scores)# 将Query和Key进行矩阵乘法,得到相似度分数# 公式: Q·K^Tscores = torch.matmul(Q, K.transpose(-2, -1))  # (batch_size, seq_len, seq_len)# 3. 缩放注意力分数# 除以根号下d_k,防止点积过大导致softmax梯度变小# 这是实现self-attention的关键步骤,能够提高模型的稳定性和性能 scores = scores / (self.d_model ** 0.5)  # (batch_size, seq_len, seq_len)# 4. 应用softmax函数获取注意力权重# 将分数转换为概率分布,所有位置的权重和为1attn_weights = F.softmax(scores, dim=-1)  # (batch_size, seq_len, seq_len)# 5. 将注意力权重与Value相乘,得到加权和# 公式: Attention(Q, K, V) = softmax(Q·K^T/√d_k)·V# 这使得模型能够根据输入之间的相关性动态地关注重要信息 output = torch.matmul(attn_weights, V)  # (batch_size, seq_len, d_model)return output# 使用示例
if __name__ == "__main__":# 创建一个自注意力层,假设特征维度为512attention = SelfAttention(d_model=512)# 生成一个随机输入 (batch_size=4, seq_len=10, d_model=512)x = torch.randn(4, 10, 512)# 计算自注意力output = attention(x)# 输出形状应该与输入相同print(f"Input shape: {x.shape}")print(f"Output shape: {output.shape}")# 应该输出: torch.Size([4, 10, 512])

掩码自注意力

掩码自注意力机制用于确保在训练或生成过程中,模型不会关注输入序列中的一些token。

例如,在处理机器翻译等序列到序列任务时,防止未来位置的信息泄露非常重要。这意味着在将一个句子从一种语言翻译成另一种语言时,你不希望模型关注当前正在翻译的单词之后的单词,因为那样会引入未来的信息。

这里有一个简化的例子。假设在训练过程中,我们正在学习将句子“I am eating an apple.”翻译成法语(完整的法语翻译:“Je mange une pomme.“),而模型目前将要发出单词“mange”(吃)。在这种情况下,我们希望遮盖单词“une”和“pomme”,以防止模型从这些单词中学习,同时确保“mange”的生成仅受“une”的影响。

在代码实现方面,通过将标记的权重设置为 -inf ,在应用 softmax 归一化之前对其进行掩码处理。这确保了在归一化后,这些词的权重将为零,从而有效地迫使模型只关注序列中当前位置之前的部分。

掩码自注意力机制对于 GPT(生成式预训练 Transformer)等自回归语言模型至关重要,因为它强制执行因果关系,并确保模型逐个toke地生成文本,每个预测仅基于前一个上下文。这防止了模型在训练和生成过程中通过查看未来信息来作弊。此外,掩码自注意力机制也用于 BERT 等编码器模型,在执行掩码语言建模时,会随机掩码输入序列中的某些单词。

交叉注意力和自注意力

交叉注意力和自注意力的主要区别在于它们所操作的输入序列类型及其各自的目的。自注意力捕获单个输入序列内部的关系,而交叉注意力捕获两个不同输入序列元素之间的关系,使模型能够生成连贯且具有上下文相关性的输出。

如上图“transformer架构”中,左侧的编码层使用自注意力来编码输入语言文本,而右侧的解码层使用交叉注意力来关注编码的输入文本

Self-AttentionCross-Attention
输入类型- 自注意力机制作用于单个输入序列
- 通常用于 Transformer 模型的编码器层中,其中输入序列是源输入文本
- 交叉注意力作用于两个不同的输入序列:一个源序列和一个目标序列
- 通常用于 Transformer 模型的解码器层中,其中源序列是上下文,目标序列是正在生成的序列
目的- 自注意力捕获同一输入序列内部的关系
- 通过权衡输入序列中每个元素的重要性,帮助模型学习上下文和长距离依赖关系
- 交叉注意力允许模型在生成目标序列的每个元素时,关注源序列的不同部分
- 它捕捉了源序列中的元素与目标序列中的元素之间的关系。这有助于生成与上下文相关的输出。
使用在 Transformer 的编码器中,每个单词或token都会关注同一句子中的所有其他单词,学习整个句子的上下文信息在机器翻译中,解码器中的交叉注意力机制允许模型在生成目标句子的每个词时查看源句子。这有助于确保生成的翻译具有连贯性和上下文准确性
公式自注意力机制根据从相同输入序列产生的查询(Q)、键(K)和值(V)向量计算注意力分数交叉注意力机制同样基于查询(Q)、键(K)和值(V)向量计算注意力分数。然而,在交叉注意力机制中,这些向量源自不同的序列。查询(Q)和值(V)来自目标序列(解码器输入),而键(K)来自源序列(编码器输出)

多头注意力

多头注意力通过在相同的输入序列上并行运行多个注意力头扩展了单头注意力的概念。这使得模型能够同时学习输入数据中的各种关系和模式。与使用单个注意力头相比,它极大地增强了模型的表达能力。

多头注意力机制的作用是捕获数据中不同类型的关系。这是通过并行使用多个自注意力头来实现的,每个头学习输入的不同方面,使模型能够同时关注各种模式。
在这里插入图片描述

多头注意力的实现

  • 不再使用单一的 K、Q 和 V 矩阵,而是初始化多个集合(每个注意力头一个)
  • 每个注意力头独立计算注意力分数,并生成自己的注意力加权输出。
  • 所有头的输出被连接并进行线性变换,形成最终的多头注意力输出。
  • 每个注意力头针对不同的输入部分,捕捉数据中的多样化模式和关系。

多头注意力机制相较于单头注意力机制的优势与局限性

  • 增强表达性:多头注意力机制能够同时捕捉多样的依赖关系和模式。这是理解数据中复杂关系的关键。
  • 提升泛化能力:通过学习多组注意力参数,模型变得更加鲁棒,能够适应不同的任务和数据集。
  • 计算复杂度增加:多头注意力机制增强了模型的能力。然而,它也增加了计算复杂度,需要更多的计算资源。为了缓解这一问题,在推理过程中,采用一种称为头剪枝的机制(Head Pruning)来丢弃那些不太有用的注意力头。

位置编码

在这里插入图片描述

左侧:图中橙色高亮块显示了位置编码作为输入被用于 Transformer 模型的编码器和解码器块
右侧:展示了一个计算维度为 5 的输入 Token n 的位置编码的示例。然后,将这些位置编码逐元素地加到 Token 嵌入上,以生成模型的输入嵌入。

位置编码的必要性

在许多基于序列的任务中,例如自然语言处理,输入序列中元素的顺序对于理解上下文和意义至关重要。然而,标准嵌入(例如词嵌入)本身不包含元素位置的信息。这就是为什么需要位置编码。

与循环神经网络不同,Transformer 架构并行处理所有输入 Token。如果没有位置信息,输入 Token 被视为一个词袋,从而使得模型难以理解输入的序列性质。因此,将位置编码添加到输入嵌入中,以帮助模型理解数据的序列结构,并区分不同位置上的元素。

与循环神经网络(RNNs)和卷积神经网络(CNNs)不同,Transformer 没有内置的序列顺序概念。

位置编码被添加到输入嵌入中,以提供有关序列中每个单词位置的信息,使模型能够考虑元素的顺序。

在 Transformer 架构中,位置编码被添加到输入嵌入中,然后再将数据输入编码器和解码器堆栈。这使得模型能够理解输入序列中标记之间的顺序关系,并生成连贯的输出序列,例如翻译或文本生成。

工作原理

数学表示

位置编码的公式设计用于为序列中的每个位置提供唯一的编码。位置编码向量随后与原始输入嵌入进行逐元素相加,以生成包含语义和位置信息的嵌入。位置编码的公式如下:
PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel) PE(pos,2i)=sin(pos/10000^{2i/d_{model}})\\ PE(pos,2i+1)=cos(pos/10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)

  • pospospos 表示序列中元素的位序
  • iii 指的是位置编码向量中的维度
  • dmodeld_{model}dmodel 是输入嵌入的维度

基于频率的编码

使用具有不同频率的 sinecosine 函数确保不同位置具有不同的表示。

  • sinsinsin 项在位置上创建一个周期,其频率呈指数衰减。这意味着每个维度的位置编码捕获周期的不同部分。
  • coscoscos 项创建另一个具有相同属性但具有相移周期的周期。

将指数函数以 10,000 为底的选择,以及同时使用 sinecosine 函数,都是经过实践验证而发现有效的经验性选择。

使用上述公式计算位置编码向量后,它们与输入嵌入进行逐元素相加。这种加法将位置信息与嵌入中包含的语义信息结合起来。

堆叠注意力层

带有 Dropout、残差连接和层归一化的堆叠注意力层

Transformer 由多个堆叠在彼此之上的相同层组成。每一层包含一个多头自注意力子层,随后是一个前馈神经网络子层。

每个子层的输出会通过一个 dropout 层、一个层归一化步骤,并采用残差连接来促进训练过程中的梯度流动。

残差连接(跳跃连接)有助于缓解梯度消失问题,并促进深度网络的训练。

层归一化在子层之前和之后应用,以稳定训练。

位置前馈层

经过多个注意力层后,在最后一层,Transformer 独立地对每个位置应用位置感知的前馈层。

该层通常由一个带有 ReLU 激活函数的线性变换层,后接一个 softmax 层组成。

Transformer优点

并行计算

并行计算(Parallelization):自注意力机制支持并行计算,与 RNN、LSTM 等顺序模型相比,能够实现更快的训练和推理。

直到 2017 年,领先的语言模型是循环神经网络(RNNs)和长短期记忆网络(LSTMs)。然而,随着 Google AI 在同年年底发布的论文《Attention is all you need》中引入 Transformer 模型,这一格局发生了剧变。

传统 NLP 模型从“左到右”展开,逐个元素按顺序处理数据。这些模型的正向和反向传播涉及 O(序列长度)O(序列长度)O(序列长度) 操作,这些操作不易并行化。虽然 GPU 能够同时执行多个独立操作,但由于操作的顺序性质,这些模型无法充分利用其潜力,这也阻碍了在大型数据集上的训练。

在这里插入图片描述

Transformer 模型在模型训练过程中带来了范式转变。它引入了一种称为自注意力的机制,该机制同时作用于整个序列(一个 O(1)O(1)O(1)操作)。这一创新使 Transformer 模型高度并行化,从而加速了训练和推理。这些模型有效地利用了 GPU 和 TPU 基础设施的能力。因此,Transformer 代表了神经网络和 NLP 领域内模型构建和训练的关键进步。

在这里插入图片描述

长距离依赖

长距离依赖(Long-Range Dependencies):Transformer 模型在捕捉数据中的长距离依赖方面表现出色。

从 20 世纪 60 年代基于规则的 NLP 模型到 20 世纪 80 年代统计建模技术(N-gram 模型),再到 20 世纪 2000 年代的隐马尔可夫模型到神经语言模型(RNN、LSTM),最终在 2017 年出现了 transformers,自然语言处理领域经历了一系列新的发现。这些进展主要旨在通过更深入地理解语境来提升语言模型的性能。

在 transformers 出现之前,最先进的语言模型是按顺序处理数据的。例如,RNN 需要对遥远的词对交互需要 O(序列长度)O(序列长度)O(序列长度) 步。它们保留了一个隐藏状态,封装了前序元素的信息。这些隐藏状态捕获了序列的语境信息。然而,由于梯度消失或梯度爆炸等问题,它们在捕获长距离依赖方面面临挑战。

Transformer 模型则利用自注意力机制来捕获上下文信息。在这种方法中,最大交互距离为 O(1)O(1)O(1) ,因为输入序列中的所有词都与前一层的所有词进行交互和注意力分配,同时为特定位置进行预测。这种机制使模型能够包含序列中相距较远的元素,有效地建模长距离关系。

可扩展性

可扩展性(Scalability):Transformer 模型可以扩展以处理大型数据集和复杂任务。

Transformer 模型可以扩展以处理大型数据集和复杂任务。这种可扩展性对于在大量数据上进行训练和实现最先进的性能至关重要。

迁移学习

迁移学习(Transfer Learning):预训练的 Transformer 模型可以针对特定任务进行微调,利用从大规模预训练中学习到的知识。

预训练随后进行微调已被证明是构建用于语言驱动任务的机器学习模型的一种非常成功的方法。Transformer 可以在大型通用语言语料库上进行预训练,捕捉丰富的语言模式和语义。然后,这些预训练的模型可以针对特定任务进行微调,减少对大量特定任务标记数据的需要。下图很好地描绘了使用 Transformer 模型进行预训练、微调和迁移学习的过程。

在这里插入图片描述

Transformer 模型在多个领域的广泛应用

Transformer 模型在各种自然语言处理任务中表现出卓越的适应性,包括机器翻译、情感分析、文本分类和问答等。此外,Transformer 模型被广泛应用于各种行业和功能领域,涵盖计算机视觉、语音识别、机器人技术、医疗保健、金融、推荐系统等。

在这里插入图片描述

尽管原始论文的重点是语言翻译任务,但随后出现了几个有影响力的模型以适应不同类型的 NLP 任务。2018 年,OpenAI 推出了 GPT(后来用于 ChatGPT),Google 开发了 BERT(用于 Google 搜索引擎),随后一系列语言模型(RoBERTa、DALL-E、LLaMA、PaLM、T5、GPT-4 等)在文本到文本、文本到图像、文本到视频和文本到语音生成中找到了应用。

它们捕捉复杂关系、处理长距离依赖关系以及促进迁移学习的能力,使它们成为现代人工智能研究和应用的核心。

在这里插入图片描述

Transformer局限

高计算需求、内存需求以及长训练时间

自注意力机制相较于循环机制最广受赞誉的优势之一是其高度并行化。然而,在自注意力机制中,需要计算所有词对之间的交互,这意味着计算量随着序列长度的增加呈平方级增长,需要大量的内存和训练时间。对于循环模型,操作数量则呈线性增长。这一局限性通常将输入序列限制在约 512 个 token,并阻止了 Transformer 直接应用于需要更长上下文的任务,如文档摘要、DNA 序列、高分辨率图像等。

在这里插入图片描述

Transformer 模型,尤其是较大的模型,在训练和推理过程中需要大量的计算资源。根据数据规模、基础设施可用性和模型参数大小,构建预训练模型可能需要几天甚至几周的时间

难以解释

Transformer 模型的架构高度复杂,这限制了其可解释性。Transformer 模型类似于“黑箱”模型,因为难以理解模型的内部工作机制以及解释为何做出某些预测。多层神经网络和自注意力机制使得难以追踪特定输入特征如何影响其输出。这种有限的透明度引发了关于人工智能应用中使用中的问责制、公平性和版权问题的担忧。

高碳排放

随着 Transformer 模型的规模和规模的扩大,它们被发现更加准确和强大。因此,普遍的策略是构建更大的模型来提高性能。由于大型模型计算密集,它们也是能源密集的。

决定机器学习模型总能源需求的因素包括算法设计、使用的处理器数量、处理器的速度和功率、数据中心在输送电力和冷却处理器方面的效率,以及能源供应组合(可再生、天然气、煤炭等)。Patterson 等人提出了以下公式来计算人工智能模型的碳足迹:
在这里插入图片描述

“见微知著,积跬步以至千里”,至此,关于 [Transformer] 的微探索之旅就暂告一段落了。感谢您的耐心阅读。希望这片小小的“知微”碎片,能让你对NLP有更清晰的认识。

点赞关注不迷路,点击合集标签「#NLP知微集」,不错过每一次细微的洞察。

下期再见,继续我们的拆解之旅!

Reference

  • https://aiml.com/what-are-the-main-advantages-of-the-transformer-models/
  • https://aiml.com/what-are-transformers/
  • https://aiml.com/explain-the-transformer-architecture/
  • https://aiml.com/explain-self-attention-and-masked-self-attention-as-used-in-transformers/
  • https://aiml.com/what-is-multi-head-attention-and-how-does-it-improve-model-performance-over-single-attention-head/

文章转载自:

http://kck7afSc.xLpdm.cn
http://jkzx4E6V.xLpdm.cn
http://BWf5i3Ze.xLpdm.cn
http://PkyIBjnf.xLpdm.cn
http://sDTOEZ7q.xLpdm.cn
http://aVZ4CgQc.xLpdm.cn
http://aL1GdKBz.xLpdm.cn
http://DXJsPDSL.xLpdm.cn
http://5KFWeE4Q.xLpdm.cn
http://BPPtpruW.xLpdm.cn
http://invOClo8.xLpdm.cn
http://y3DuX0pN.xLpdm.cn
http://vRV4yxja.xLpdm.cn
http://DFxv3Dls.xLpdm.cn
http://RB3fCsZB.xLpdm.cn
http://I7vqe0er.xLpdm.cn
http://DEeQLEdV.xLpdm.cn
http://lbLLEhqb.xLpdm.cn
http://VXDgZoKD.xLpdm.cn
http://f2oiFGrg.xLpdm.cn
http://vY4hclo7.xLpdm.cn
http://Zp32ec7P.xLpdm.cn
http://0d69UPs4.xLpdm.cn
http://9ajjJqCT.xLpdm.cn
http://TPxCBD8K.xLpdm.cn
http://gtXemOQJ.xLpdm.cn
http://pMoJP7X6.xLpdm.cn
http://zQZs4icE.xLpdm.cn
http://isH7VpWi.xLpdm.cn
http://eH0GXtBG.xLpdm.cn
http://www.dtcms.com/a/384128.html

相关文章:

  • 大数据毕业设计选题推荐-基于大数据的客户购物订单数据分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • C# JPG转PDF实现方案
  • 单变量单步时序预测 | TCN-BiLSTM时间卷积结合长短期记忆神经网络(MATLAB)
  • uniapp scroll-view 设置scrollTop无效
  • Day24_【深度学习(2)—PyTorch框架安装】
  • 未来汽车电气/电子(E/E)架构——迈向全新电气/电子范式之路上的复杂性掌控
  • 【Linux手册】mmap 接口:内存映射实现高效 IO 的
  • 如何使用代理 IP 实现爬虫代理
  • Ubuntu 录制 gif
  • Day24_【深度学习(3)—PyTorch使用—张量的创建和类型转换】
  • IP-Prefix 配置核心要点与典型应用场景
  • 为什么企业需要高防IP
  • 通过 DNS 解析SCAN IP
  • 网络:TCP/IP协议
  • 【后端】数据库四大范式详细解析
  • 银河麒麟部署mysql8.0并连接应用
  • Mysql中有那些锁
  • React 状态管理(手写实现react-redux)
  • C++:类和对象(下)
  • 智能驾驶再加速:L4 级 AI 系统落地难点与城市试点经验总结
  • 第4章:CPU进阶命令
  • brew@homebrew@linux通用包管理工具linuxbrew
  • NumPy 是 Python 科学计算的基石
  • LLMs之RL之GRPO:《Magistral》的翻译与解读
  • FPGA入门-数码管静态显示
  • 【大模型】企业级应用场景概览
  • uTools 轻工具 简洁又方便
  • Can总线原理
  • Matplotlib 全面详解:从入门到高级应用
  • 爬虫获取API接口的实战指南