【AI-NLP】Transformer理论及源码理解

普通人也能看懂的Transformer源代码解释(PyTorch) Transformer源代码解释之PyTorch篇 章节 词嵌入 位置编码 多头注意力 搭建Transformer 在这里插入图片描述 词嵌入 Transformer本质上是一种Encoder,以翻译任务为例,原始数据集是以两种语言组成一行的,在应用时,应是Encoder输入源语言序列,Decoder里面输入需要被转换的语言序列(训练时)。一个文本常有许多序列组成,常见操作为将序列进行一些预处理(如词切分等)变成列表,一个序列的列表的元素通常为词表中不可切分的最小词,整个文本就是一个大列表,元素为一个一 阅读详情

提出背景

改进了RNN的训练慢的缺点,利用self-attention机制实现并行计算。并且Transformer可以增加到非常深的深度,充分发掘DNN模型的特性,提升模型准确率。同时使用注意力机制更容易关注序列的全局特征,解决了RNN不善处理长距离依赖的问题
本质上是一个seq2seq的模型,因此可用于机器翻译,语音辨识,语音合成等问题

总体结构

整体结构由编码器与解码器组成,一个编码器中可有若干个编码层

注意,Encoder中的参数各不相同

Encoder

编码器的作用在于,输入一个向量,输出一个等长的向量

要点:

  1. 使用多头注意力机制,关注全局输入向量的资讯
  2. 使用了残差及layer normalization,避免出现梯度消失问题
  3. 使用前向神经网络,每个位置的单词对应的前馈神经网络都完全一样

Self Attention

query,key,value全由输入向量自身计算得到的一种注意力机制。每一个输入向量分别对应了查询、键、值权重矩阵,用于生成查询、键、值向量,权重矩阵为训练参数

Decoder

输入有两部分

  • 编码器最后一层的输出作为key和value
  • 同时解码器自己的输入经过多头自注意力的计算作为query

输出为对应的结果序列

结构与编码器类似,唯一的不同在于Masked Multi-Head Attention使用了掩码机制,不再关注全局的资讯,而是只考虑了当前位置以及当前位置之前的信息,存在时序性

细节再探

  1. Teacher forcing:将真实标签作为decoder的输入,依次预测结果,相当于把正确答案给解码器

  2. 掩码作用:考虑到Teacher forcing已经将正确答案输入到模型,因此在每次预测一个token时,需要将其及其之后的token先掩盖,保证训练任务和预测任务在执行自回归时,是同样的形式

  1. d k d_k dk​是query和key向量的维度
    在计算注意力权重时除以 d k d_k dk​,避免了随着 d k d_k dk​的增大,即维度增大时,计算出的权重出现过大(softmax后的值非0即1)的情况,从而保留了数据原始的分布,可以使得梯度回传时更加平稳
  1. 使用layer normalize而非batch normalize:ln是针对一个样本内部做归一化;bn针对的是各个样本的特征做归一化,在文本长度变化较大时,这种归一化方式会造成均值方差抖动明显
  1. 多头self attention意在让根据词向量得出的query, key, value向量,进入不同的线性层(子空间),分别进行自注意力计算,捕捉全局丰富的语义信息,再将所有结果concat,拼接回原有的形状,最后再进入一个线性层得到结果
  1. 在decoder中计算自注意力时,query来自带有掩码的自注意力计算得出,而key和value来自encoder最后的输出,目的是让Decoder端的单词(token)给予Encoder端对应的单词(token)“更多的关注(attention weight)”
  1. 自注意力是基于全局信息进行计算,而忽略了时序信息(导致任意打乱句子中token的顺序,结果不变),位置编码PE解决了这一问题。PE的长度与embedding相同,使二者可以直接相加。
    计算方式是根据token的文本中的位置,PE向量中偶数位使用sin计算,奇数位使用cos计算。由于三角函数公式不受序列长度的限制,也就是可以对比所遇到序列的更长的序列进行表示

源码阅读

主函数部分

确定了模型的输入部分,由两部分组成encoder的输入,decoder的输入
将token转换成id后以tensor形式传入模型

P代表填充码,S代表起始,E代表结束。对文本进行了id映射
模型参数初始化,选用交叉熵损失函数,Adam自适应学习率优化器

主模型定义

class Transformer(nn.Module):
    def __init__(self):
        super(Transformer, self).__init__()
        self.encoder = Encoder()
        self.decoder = Decoder()
        self.projection = nn.Linear(d_model, tgt_vocab_size, bias=False)

    def forward(self, enc_inputs, dec_inputs):
        enc_outputs, enc_self_attns = self.encoder(enc_inputs)
        dec_outputs, dec_self_attns, dec_enc_attns = self.decoder(dec_inputs, enc_inputs, enc_outputs)
        dec_logits = self.projection(dec_outputs) # dec_logits : [batch_size x src_vocab_size x tgt_vocab_size]
        return dec_logits.view(-1, dec_logits.size(-1)), enc_self_attns, dec_self_attns, dec_enc_attns

由编码器,解码器及全连接层组成
编码器输入 为1*5的张量,输出为1*5*512的张量(批量大小为1,文本长度为5,embedding向量维度为512),及注意力权重参数6*8*5*5
(6代表编码器中编码层的数量;8代表8头注意力,计算了8次,有8个子空间;5*5代表文本内部的相关性计算的结果)
解码器输入为编码器的输出及解码层输入文本
输出为注意力计算得出的结果(1*5*512),及解码器掩码自注意力权重参数及交互注意力权重参数
将解码器的输出作为全连接层的输入,通过全连接层将512维向量压缩成7维,对应翻译文本的长度(5*7)

编码器

class Encoder(nn.Module):
    def __init__(self):
        super(Encoder, self).__init__()
        # 词向量5*512
        self.src_emb = nn.Embedding(src_vocab_size, d_model)
        # 位置编码6*512
        self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(src_len+1, d_model), freeze=True)
        self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])

    def forward(self, enc_inputs):  # enc_inputs : [batch_size x source_len] [1*5]
        enc_outputs = self.src_emb(enc_inputs) + self.pos_emb(torch.LongTensor([[1, 2, 3, 4, 0]]))
        enc_self_attn_mask = get_attn_pad_mask(enc_inputs, enc_inputs)
        enc_self_attns = []
        for layer in self.layers:
            enc_outputs, enc_self_attn = layer(enc_outputs, enc_self_attn_mask)
            enc_self_attns.append(enc_self_attn)
        return enc_outputs, enc_self_attns

定义词向量,位置向量,并将二者相加,传入编码层中迭代
位置向量由当前token所在文本中的位置计算得出

# n_position为文本长度,d_model为总向量维度
def get_sinusoid_encoding_table(n_position, d_model):
    def cal_angle(position, hid_idx):
        return position / np.power(10000, 2 * (hid_idx // 2) / d_model)
    def get_posi_angle_vec(position):
        return [cal_angle(position, hid_j) for hid_j in range(d_model)]

    # 6*512
    sinusoid_table = np.array([get_posi_angle_vec(pos_i) for pos_i in range(n_position)])
    sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2])  # dim 2i
    sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2])  # dim 2i+1
    return torch.FloatTensor(sinusoid_table)

编码层

由多头自注意力层,以及前向神经网络组成
QKV均来自编码层输入的embedding
此时输入输出均为1*5*512

class EncoderLayer(nn.Module):
    def __init__(self):
        super(EncoderLayer, self).__init__()
        self.enc_self_attn = MultiHeadAttention()
        self.pos_ffn = PoswiseFeedForwardNet()

    def forward(self, enc_inputs, enc_self_attn_mask):
        # enc_input: torch.Size([1, 5, 512])
        # enc_inputs to same Q,K,V
        enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask)
        enc_outputs = self.pos_ffn(enc_outputs)  # enc_outputs: [batch_size x len_q x d_model]
        # torch.Size([1, 5, 512])
        return enc_outputs, attn

多头自注意力层

class MultiHeadAttention(nn.Module):
    def __init__(self):
        super(MultiHeadAttention, self).__init__()
        self.W_Q = nn.Linear(d_model, d_k * n_heads)
        self.W_K = nn.Linear(d_model, d_k * n_heads)
        self.W_V = nn.Linear(d_model, d_v * n_heads)
        self.linear = nn.Linear(n_heads * d_v, d_model)
        self.layer_norm = nn.LayerNorm(d_model)

    def forward(self, Q, K, V, attn_mask):
        # q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]
        # attn_mask: [1 x 5 x 5]
        residual, batch_size = Q, Q.size(0)
        # (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)
        # torch.Size([1, 8, 5, 64])
        q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1, 2)  # q_s: [batch_size x n_heads x len_q x d_k]
        k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1, 2)  # k_s: [batch_size x n_heads x len_k x d_k]
        v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1, 2)  # v_s: [batch_size x n_heads x len_k x d_v]
		# 将mask从1*5*5复制为1*8*5*5
        attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]

        # context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]
        context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)
        context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]
        output = self.linear(context)
        return self.layer_norm(output + residual), attn # output: [batch_size x len_q x d_model]

使用 W Q W_Q WQ​矩阵与Embedding相乘时,本质是将 W Q W_Q WQ​视为一个线性层,KV同理
多头计算的步骤是:先映射分头,再计算注意力权重


以上公式实现如下 值得注意是,我们会找出文本序列中是padding的位置,并将其在`attn_mask`对应的位置上设置为True。接着在计算注意力,padding位置将被设置为负无穷,在经过softmax计算后结果基本为0,对当前单词的注意力计算就不会产生影响
class ScaledDotProductAttention(nn.Module):
    def __init__(self):
        super(ScaledDotProductAttention, self).__init__()

    def forward(self, Q, K, V, attn_mask):
        scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k)
        # padding负无穷
        scores.masked_fill_(attn_mask, -1e9) 
        attn = nn.Softmax(dim=-1)(scores)
        context = torch.matmul(attn, V)
        return context, attn

前馈神经网络层

在前向神经网络层中,使用一维卷积进行计算
原因在于当kernel_size=1,stride=1,padding=0时,与MLP的节点计算方式一样,变相实现了一个MLP
nn.Conv1d的输入数据格式只能以三维tensor[batch, channel, length]输入,与nn.Linear输入数据格式不同;
并且 nn.Conv1d的数据作用位置也不同,nn.Conv1d作用在第二个维度channel上,而nn.Linear作用于第三个维度

class PoswiseFeedForwardNet(nn.Module):
    def __init__(self):
        super(PoswiseFeedForwardNet, self).__init__()
        self.conv1 = nn.Conv1d(in_channels=d_model, out_channels=d_ff, kernel_size=1)
        self.conv2 = nn.Conv1d(in_channels=d_ff, out_channels=d_model, kernel_size=1)
        self.layer_norm = nn.LayerNorm(d_model)

    def forward(self, inputs):
        residual = inputs  # inputs : [batch_size, len_q, d_model]
        # nn.Conv1d作用于第2个维度,因此要交换位置
        output = nn.ReLU()(self.conv1(inputs.transpose(1, 2)))
        output = self.conv2(output).transpose(1, 2)
        return self.layer_norm(output + residual)

Masked

为解码层的自注意力加入掩码机制,使其无法查看当前及当前以后的序列

def get_attn_subsequent_mask(seq):
    attn_shape = [seq.size(0), seq.size(1), seq.size(1)]
    subsequent_mask = np.triu(np.ones(attn_shape), k=1)
    subsequent_mask = torch.from_numpy(subsequent_mask).byte()
    return subsequent_mask

解码器

class Decoder(nn.Module):
    def __init__(self):
        super(Decoder, self).__init__()
        # 7*512
        self.tgt_emb = nn.Embedding(tgt_vocab_size, d_model)
        self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(tgt_len+1, d_model), freeze=True)
        self.layers = nn.ModuleList([DecoderLayer() for _ in range(n_layers)])

    def forward(self, dec_inputs, enc_inputs, enc_outputs):  # dec_inputs : [batch_size x target_len]
        dec_outputs = self.tgt_emb(dec_inputs) + self.pos_emb(torch.LongTensor([[5, 1, 2, 3, 4]]))
        dec_self_attn_pad_mask = get_attn_pad_mask(dec_inputs, dec_inputs)
        dec_self_attn_subsequent_mask = get_attn_subsequent_mask(dec_inputs)
        # 将掩码转换为bool类型
        dec_self_attn_mask = torch.gt((dec_self_attn_pad_mask + dec_self_attn_subsequent_mask), 0)

        dec_enc_attn_mask = get_attn_pad_mask(dec_inputs, enc_inputs)

        dec_self_attns, dec_enc_attns = [], []
        for layer in self.layers:
            dec_outputs, dec_self_attn, dec_enc_attn = layer(dec_outputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask)
            dec_self_attns.append(dec_self_attn)
            dec_enc_attns.append(dec_enc_attn)
        return dec_outputs, dec_self_attns, dec_enc_attns

解码层

定义了两层注意力,分别为自注意力和交互注意力
其中自注意力为masked
交互注意力中,Q来自decoder,KV来自encoder

class DecoderLayer(nn.Module):
    def __init__(self):
        super(DecoderLayer, self).__init__()
        self.dec_self_attn = MultiHeadAttention()
        self.dec_enc_attn = MultiHeadAttention()
        self.pos_ffn = PoswiseFeedForwardNet()

    def forward(self, dec_inputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask):
        dec_outputs, dec_self_attn = self.dec_self_attn(dec_inputs, dec_inputs, dec_inputs, dec_self_attn_mask)
        dec_outputs, dec_enc_attn = self.dec_enc_attn(dec_outputs, enc_outputs, enc_outputs, dec_enc_attn_mask)
        dec_outputs = self.pos_ffn(dec_outputs)
        return dec_outputs, dec_self_attn, dec_enc_attn

参考资料

  1. 李沐Transformer论文逐段精读【论文精读】
  2. 李宏毅Transformer
  3. Transformer从零详细解读(可能是你见过最通俗易懂的讲解)
  4. 源码请见:graykode/nlp-tutorial
机器翻译模型Transformer代码详细解析 谷歌一个月前发了一篇论文Attention is all you need,文中提出了一种新的架构叫做Transformer,用以来实现机器翻译。论文发出不久,就有人用tensorflow实现了Transformer模型,本文对其代码进行细致的分析。 阅读详情

相关推荐

【AI理论学习】对Transformer中Positional Encoding的理解

在任何一门语言中,词语的位置和顺序对句子意思表达都是至关重要的。传统的RNN模型在处理句子时,以序列的模式逐个处理句子中的词语,这使得词语的顺序信息在处理过程中被天然的保存下来了,并不需要额外的处理。而对于Transformer来说,由于句子中的词语都是同时进入网络进行处理,顺序信息在输入网络时就已丢失。因此,Transformer是需要额外的处理来告知每个词语的相对位置的。其中的一个解决方案,就是论文中提到的。

小哲的博客 5209

Transformer源码详解(Pytorch版本)逐行讲解

下面的PAD表示填充,填充就是当句子长度不满足max_len时候,会填充pad。## 这里有两个数据进行输入,一个是enc_inputs 形状为[batch_size, src_len],主要是作为编码段的输入,一个dec_inputs,形状为[batch_size, tgt_len],主要是作为解码端的输入。一定需要注意的是这里得到的矩阵形状是batch_size x len_q x len_k,我们是对k中的pad符号进行标识,并没有对q中的做标识,因为没必要(尚未理解,有理解的小伙伴评论私信奥)

Queen_sy的博客 2万+

源码剖析transformer、self-attention

首先给大家引入一个github博客,这份代码是我在看了4份transformer的源码后选出来的,这位作者的写法非常易懂,代码质量比较高。https://github.com/Separius/BERT-keras 这篇文章主要跟大家分享四个点:多头机制(multi-head)、LN和GELU、位置编码。 在这再给大家安利几篇博客,便于大家更具体的理解自注意力的内在原理。 https://z...

weixin_42078618的博客 1万+

Transformer代码从零解读【Pytorch官方版本】

输入经过词向量层和位置编码层,得到最终的输入,通过掩码注意力机制,然后交互注意力机制与Encoder的输出做交互,Encoder的输出做K矩阵、V矩阵,Decoder的值做Q矩阵,再经过前馈神经网络层,得到Decoder的输出,解码端是没法并行的,因为输入【S】,输出【I】,然后输出的【I】作为下一阶段的输入,这一次的输入取决于上一次的输出,所以解码端无法并行,如果当前输入为【S】,则后面的【卷起来】被遮挡,当输入为【S卷】时,后面的【起来】被遮挡,形成上三角矩阵为1的矩阵,如何去掉PAD信息?

qq_23022733的博客 3337

Transformer源码理解(Tensorflow)

前言 源码来自:https://github.com/Kyubyong/transformer

星垂平野阔 3217

我的机器学习入门之路(中)——深度学习(自然语言处理)

继上一篇《我的机器学习入门之路(上)——传统机器学习》,这一篇博客主要记录深度学习(主要是自然语言处理)这一块内容的学习过程。以下均将自然语言处理简称NLP。 这一块内容的学习路线分为三部分:明确NLP的研究问题及传统的方法有哪些、深度学习(NLP)基础及深度学习框架的使用、NLP的深入学习。 一、明确NLP的研究问题及传统的方法有哪些 不像机器学习中研究的问题一般都是直接的分类或...

PaniniGu的博客 2163

深入理解 Transformer:为什么我们需要 Transformer?

这几年,Transformer 几乎已经成为人工智能领域绕不开的一个名字。无论是我们熟悉的大语言模型,还是文本生成、机器翻译、图像理解、多模态模型,背后都能看到 Transformer 的影子。AttentionQ、K、VEncoderDecoderTransformer 好像就是由一堆复杂的矩阵运算拼起来的。如果只是停留在这个层面,我们确实可以把 Transformer 的公式背下来,甚至把代码实现出来。但是,这样并不能真正理解 Transformer。

htw250056的博客 2472

AI自然语言处理NLP原理与Python实战:对话系统的优化

1.背景介绍 自然语言处理(Natural Language Processing,NLP)是人工智能(AI)领域的一个重要分支,旨在让计算机理解、生成和处理人类语言。在过去的几年里,NLP技术取得了显著的进展,这主要归功于深度学习和大规模数据的应用。在这篇文章中,我们将探讨NLP的核心概念、算法原理、实际应用以及未来趋势。 NLP的主要

AI天才研究院 384

Nlp资源合集

# NLP执行师国际文凭证照班。

宝宝单机的博客 784

自然语言处理NLP星空智能对话机器人系列:贝叶斯Bayesian Transformer论文源码复现课程片段1至片段9

Coherence is everything you need! – Gavin Wang(星空智能对话机器人作者,AI通用双线思考法创始人) 星空智能对话机器人的Gavin认为Transformer是拥抱数据不确定性的艺术。 Transformer的架构、训练及推理等都是在Bayesian神经网络不确定性数学思维下来完成的。Encoder-Decoder架构、Multi-head注意力机制、Dropout和残差网络等都是Bayesian神经网络的具体实现;基于Transformer各种模型变种及实践也都

大模型与Agent智能体 1259

自然语言处理NLP星空智能对话机器人系列:GavinNLP星空对话机器人Transformer课程片段1到片段4

自然语言处理NLP星空智能对话机器人系列:GavinNLP星空对话机器人Transformer课程片段1到片段4 Coherence is everything you need! – Gavin Wang(星空智能对话机器人作者,AI通用双线思考法创始人) 星空智能对话机器人的Gavin认为Transformer是拥抱数据不确定性的艺术。 Transformer的架构、训练及推理等都是在Bayesian神经网络不确定性数学思维下来完成的。Encoder-Decoder架构、Multi-head注意力机制、

大模型与Agent智能体 1054

Nlp教程资源合集

weixin_53721706的博客 872

自然语言处理NLP星空智能对话机器人系列:NLP on Transformers 101第二章

自然语言处理NLP星空智能对话机器人系列:NLP on Transformers 101 第二章 NLP on Transformers 101 (基于Transformer的NLP智能对话机器人实战课程) One Architecture, One Course,One Universe 本课程以Transformer架构为基石、萃取NLP中最具有使用价值的内容、围绕手动实现工业级智能业务对话机器人所需要的全生命周期知识点展开,学习完成后不仅能够从算法、源码、实战等方面融汇贯通NLP领域NLU、NLI、N

大模型与Agent智能体 663

AI人工智能进阶-BERT/Transformer/LSTM/RNN原理与代码

所有的分享都来自于我个人笔记,经过我自己的思考总结实践积累下来的东西,希望能帮助到入门的朋友们。

u012456282的专栏 2031

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co.

2018年可谓是自然语言处理(NLP)的元年,本文详细介绍了BERT 的前世今生以及BERT源码分析。

艾文 1317

【实验】Linux下完全卸载oracle单实例(亲身体验完整版)

停止oracle数据库服务 停止监听 卸载数据库实例 因为自己懒得再弄dbca图形化界面啥的,直接采用dbca静默删除数据库实例,命令如下 dbca -silent -deleteDatabase -sourcedb orclhq -sid orcl -sysDBAUserName orcl -sysDBAPassword zte [oracle@slave ~]$ dbca -silent ...

萝卜吃鱼914的博客 1945

NLP和数据分析的神书:大模型小黑书来啦!附PDF《基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理》

《基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理》由清华大学出版社出版,全面介绍了Transformer架构及其在自然语言处理(NLP)中的应用,特别是GPT系列模型的实践与实现。书中详细讲解了Transformer的原理,并提供了使用HuggingFace预训练RoBERTa模型的实用指南,涵盖数据集构建、数据整理器定义及模型训练等步骤。此外,书中还探讨了机器翻译、语音转文本、文本转语音、问答系统等NLP任务,并介绍了应对假新闻的技术方法。本书实用性强,内容全面,案例

OpenCVtuxiang的博客 537

ANSYS 2026 R1 Windows系统安装避坑指南:环境配置、模块部署与许可证实战

ANSYS作为主流CAE仿真平台,其安装部署已远超传统软件范畴,演变为涉及操作系统底层、GPU驱动兼容性、许可证微服务架构和统一缓存机制的系统工程。理解ANSYS安装原理,需从Windows 11 UEFI安全启动要求、DirectX 12 Ultimate图形栈依赖、gRPC架构的License Manager端口动态分配等核心机制切入;技术价值在于保障HFSS GPU加速、Fluent MPI并行稳定性及Workbench多模块协同可靠性;典型应用场景涵盖高校仿真实验室升级、工业设计院所平台重建及高性能

weixin_29251337的博客 1420

【NLP】完全解析!Bert & Transformer 阅读理解源码详解

接上一篇:你所不知道的 Transformer!超详细的 Bert 文本分类源码解读 | 附源码中文情感分类单标签参考论文:https://arxiv.org/abs/1706.03762...

fengdu78的博客 571

信息安全与技术——(十一)恶意代码检测与防范技术

恶意代码(Malicious Code )或恶意软件(Malware )主要是指以危害信息的安全等不良意图为目的的程序,它们一般潜伏在受害计算机系统中实施破坏或窃取信息。

m0_63853448的博客 5991

基于互相关(NCC)模板匹配——find_ncc_model_defocused.hdev

相关性原理:仅在NCC(r,c) = ±1时,模板与图像完全匹配; NCC绝对值越大,表示模板与正在检测部分图像越接近; NCC绝对值越接近于零,表示模板与图像越不一致。 线性光照变化不会影响NCC计算结果。 重要函数一: 创建模板:create_ncc_model( Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Metric : ModelID) 参数列表: Template(in):单通道灰度图像,它的区域可被创建为模板。 Num

m0_51271525的博客 3413

【综述】CV和NLP领域的Transformer原理和实践

本教程包含BERT、ERNIE等20多个的Transformer类模型的原理讲解,同时配套10+基于Transformer类模型的案例实践,我们一起开始学习吧,相信一定会有很多收获。

m0_63642362的博客 527

小目标检测难题终结:YOLOv11 + 注意力机制,精度直接拉满

如果你在实操中遇到精度提升不明显或速度下降过多的问题,不妨尝试调整注意力模块的类型(如替换为CA)或插入层级,或针对性优化小目标的数据集增强策略。记住,小目标检测的核心是“特征强化与空间定位”,只要结合业务场景灵活调整注意力模块的组合,你也能让YOLOv11在小目标识别任务中脱颖而出。接下来,我们从模块选型到代码落地,一步步带你打造“小目标检测专精版”YOLOv11,真正帮你解决工业场景中(如安防、质检)的小目标识别痛点。在城市安防场景中,改进后的YOLOv11对远处行人、车辆(小目标)的识别准确率提升。

m0_64661770的博客 199
上一篇: 233搞懂HMM(隐马尔可夫)
下一篇: 【AI/NLP】InstructGPT数据标注问题
CodeSlogan
博客等级 码龄6年 4227粉丝 130原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeSlogan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值