【机器学习】一文搞懂算法模型之:Transformer

news/2024/7/19 11:55:39 标签: 机器学习, 算法, transformer

Transformer

  • 1、引言
  • 2、Transformer
    • 2.1 定义
    • 2.2 原理
    • 2.3 算法公式
      • 2.3.1 自注意力机制
      • 2.3.1 多头自注意力机制
      • 2.3.1 位置编码
    • 2.4 代码示例
  • 3、总结

1、引言

小屌丝:鱼哥, 你说transformer是个啥?
小鱼:嗯… 啊… 嗯…就是…
小屌丝:你倒是说啊,是个啥?
小鱼:你不知道?
小屌丝:我知道啊,
小鱼:你知道,你还问我?
小屌丝:考考你
小鱼:kao…kao… wo??
小屌丝:对
小鱼:看你你很懂 transformer
小屌丝: 必须的
小鱼:那你来跟我说一说?
小屌丝:可以。
小鱼:秃头顶上点灯
小屌丝:啥意思? 你说的是啥意思?你说清楚,啥意思???

在这里插入图片描述
小鱼:唉~ ~没文化,真可怕。

2、Transformer

2.1 定义

Transformer是一种基于自注意力机制的深度学习模型,它完全摒弃了传统的循环神经网络(RNN)和卷积神经网络(CNN)结构,转而通过自注意力机制来计算输入序列中不同位置之间的依赖关系。

Transformer模型由谷歌在2017年提出,并在自然语言处理领域取得了显著的成绩,如机器翻译、文本生成、问答系统等。

2.2 原理

Transformer的核心思想是利用自注意力机制来捕捉输入序列中的上下文信息。
它采用Encoder-Decoder架构,其中Encoder负责将输入序列编码为一系列的隐藏状态,而Decoder则根据这些隐藏状态生成输出序列。

在Transformer中,自注意力机制是通过计算输入序列中每个位置与其他位置之间的相似度来实现的。

具体来说,对于输入序列中的每个位置,Transformer会生成一个查询向量、一个键向量和一个值向量。然后,它会计算查询向量与所有键向量之间的相似度,得到一个相似度分数矩阵。

最后,根据这个相似度分数矩阵对值向量进行加权求和,得到每个位置的输出表示。

2.3 算法公式

2.3.1 自注意力机制

自注意力机制

  • 输入:查询矩阵Q、键矩阵K、值矩阵V
  • 输出:自注意力输出Z
  • 公式 Z = s o f t m a x ( Q K T / √ d k ) V Z = softmax(QK^T/√d_k)V Z=softmax(QKT/√dk)V

其中,d_k是键向量的维度,用于缩放点积结果以防止梯度消失。

2.3.1 多头自注意力机制

多头自注意力机制

  • 输入:查询矩阵Q、键矩阵K、值矩阵V、头数h
  • 输出:多头自注意力输出MultiHead(Q, K, V)
  • 公式 M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , . . . , h e a d h ) W O MultiHead(Q, K, V) = Concat(head_1, ..., head_h)W^O MultiHead(Q,K,V)=Concat(head1,...,headh)WO

其中,每个头head_i都执行一次自注意力机制,W^O是输出线性变换的权重矩阵。

2.3.1 位置编码

位置编码
为了捕捉序列中的位置信息,Transformer使用位置编码将位置信息嵌入到输入向量中。

公式 P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 ( 2 i / D ) ) P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 ( 2 i / D ) ) PE(pos, 2i) = sin(pos / 10000^(2i / D)) PE(pos, 2i+1) = cos(pos / 10000^(2i / D)) PE(pos,2i)=sin(pos/10000(2i/D))PE(pos,2i+1)=cos(pos/10000(2i/D))

其中, p o s pos pos是位置索引, i i i是维度索引, D D D是输入向量的维度。

2.4 代码示例

# -*- coding:utf-8 -*-
# @Time   : 2024-03-17
# @Author : Carl_DJ

'''
import torch  
import torch.nn as nn  
import torch.nn.functional as F  
  
# 定义位置编码类  
class PositionalEncoding(nn.Module):  
    def __init__(self, d_model, max_len=5000):  
        super(PositionalEncoding, self).__init__()  
          
        # 计算位置编码  
        pe = torch.zeros(max_len, d_model)  
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)  
        div_term = torch.exp(torch.arange(0, d_model, 2).float() *  
                                 -(np.log(torch.tensor(10000.0)) / d_model))  
        pe[:, 0::2] = torch.sin(position * div_term)  
        pe[:, 1::2] = torch.cos(position * div_term)  
        pe = pe.unsqueeze(0).transpose(0, 1)  
        self.register_buffer('pe', pe)  
          
    def forward(self, x):  
        x = x + self.pe[:, :x.size(1)]  
        return x  
  
# 定义Transformer编码器层  
class TransformerEncoderLayer(nn.Module):  
    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):  
        super(TransformerEncoderLayer, self).__init__()  
        self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)  
        self.linear1 = nn.Linear(d_model, dim_feedforward)  
        self.dropout = nn.Dropout(dropout)  
        self.linear2 = nn.Linear(dim_feedforward, d_model)  
          
        self.norm1 = nn.LayerNorm(d_model)  
        self.norm2 = nn.LayerNorm(d_model)  
        self.dropout1 = nn.Dropout(dropout)  
        self.dropout2 = nn.Dropout(dropout)  
          
    def forward(self, src, src_mask=None, src_key_padding_mask=None):  
        # 自注意力机制  
        src2, attn = self.self_attn(src, src, src, attn_mask=src_mask,  
                                      key_padding_mask=src_key_padding_mask)  
        src = src + self.dropout1(src2)  
        src = self.norm1(src)  
          
        # 前馈神经网络  
        src2 = self.linear2(self.dropout(F.relu(self.linear1(src))))  
        src = src + self.dropout2(src2)  
        src = self.norm2(src)  
          
        return src, attn  
  
# 定义Transformer编码器  
class TransformerEncoder(nn.Module):  
    def __init__(self, encoder_layer, num_layers, norm=None):  
        super(TransformerEncoder, self).__init__()  
        self.layers = nn.ModuleList([encoder_layer for _ in range(num_layers)])  
        self.num_layers = num_layers  
        self.norm = norm  
          
    def forward(self, src, mask=None, src_key_padding_mask=None):  
        output = src  
          
        # 堆叠多个编码器层  
        for mod in self.layers:  
            output, attn = mod(output, mask, src_key_padding_mask)  
          
        if self.norm:  
            output = self.norm(output)  
          
        return output  
  
# 定义完整的Transformer模型  
class TransformerModel(nn.Module):  
    def __init__(self, src_vocab_size, d_model, nhead, num_encoder_layers, dim_feedforward, max_position_embeddings):  
        super(TransformerModel, self).__init__()  
        self.src_mask = None  
        self.position_enc = PositionalEncoding(d_model, max_position_embeddings)  
        encoder_layer = TransformerEncoderLayer(d_model, nhead, dim_feedforward, dropout=0.1)  
        encoder_norm = nn.LayerNorm(d_model)  
        self.encoder = TransformerEncoder(encoder_layer, num_encoder_layers, norm=encoder_norm)  
		self.src_embedding = nn.Embedding(src_vocab_size, d_model)  
    	self.d_model = d_model  
      
def generate_square_subsequent_mask(self, sz):  
    mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)  
    mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))  
    return mask  
  
def forward(self, src, src_mask=None):  
    if src_mask is None:  
        device = src.device  
        bsz, seq_len = src.size()  
        src_mask = self.generate_square_subsequent_mask(seq_len).to(device)  
      
    src = self.src_embedding(src) * math.sqrt(self.d_model)  
    src = self.position_enc(src)  
    output = self.encoder(src, src_mask)  
    output = self.decoder(output)  
      
    return output


代码解析

  • PositionalEncoding:定义位置编码类,用于给输入序列添加位置信息。Transformer模型是位置无关的,因此需要通过位置编码来提供序列中每个位置的信息。

  • TransformerEncoderLayer:定义Transformer编码器层,包含自注意力机制和前馈神经网络。每个编码器层都会接收输入序列,经过自注意力机制和前馈神经网络处理,输出新的序列表示。

  • TransformerEncoder:定义Transformer编码器,通过堆叠多个编码器层来构建更深的模型。

  • TransformerModel:定义完整的Transformer模型,包括嵌入层、位置编码、编码器和解码器。模型将源语言序列作为输入,经过一系列变换后,输出每个位置的目标语言词汇的预测概率。

  • generate_square_subsequent_mask:生成一个上三角矩阵的掩码,用于在自注意力机制中防止模型看到未来的信息。

  • forward:模型的前向传播函数。首先,将源语言序列通过嵌入层转换为向量表示,并乘以模型维度的平方根进行缩放。然后,将位置编码加到嵌入向量上。接下来,将结果输入到编码器中。最后,将编码器的输出传递给解码器,得到每个位置的预测概率。

在这里插入图片描述

3、总结

Transformer模型通过自注意力机制打破了传统RNN和CNN的局限性,能够更好地捕捉序列中的长期依赖关系,因此在自然语言处理任务中取得了显著的效果。

Transformer的Encoder-Decoder架构和多头自注意力机制使得模型能够同时处理输入序列中的多个位置,提高了模型的并行性和效率。通过位置编码,Transformer还能够处理序列中的位置信息,使得模型在处理自然语言等序列数据时更加灵活和准确。

虽然Transformer模型具有强大的能力,但它也需要大量的数据和计算资源来进行训练。

因此,在实际应用中,我们通常使用预训练的Transformer模型(如BERT、GPT等)作为基础,通过微调来适应特定的任务需求。

我是小鱼

  • CSDN 博客专家
  • 阿里云 专家博主
  • 51CTO博客专家
  • 企业认证金牌面试官
  • 多个名企认证&特邀讲师等
  • 名企签约职场面试培训、职场规划师
  • 多个国内主流技术社区的认证专家博主
  • 多款主流产品(阿里云等)测评一、二等奖获得者

关注小鱼,一起学习机器学习&深度学习领域的知识。


http://www.niftyadmin.cn/n/5444352.html

相关文章

​Edge-TTS:微软推出的,免费、开源、支持多种中文语音语色的AI工具

Edge-TTS是由微软推出的文本转语音Python库,通过微软Azure Cognitive Services转化文本为自然语音。适合需要语音功能的开发者,GitHub上超3000星。作为国内付费TTS服务的替代品,Edge-TTS支持40多种语言和300种声音,提供优质的语音…

自动捆绑Vue组件CSS样式-CSS-IN-JS

vite-plugin-vue-style-bundler 开发Vue组件时,编译产物由js和css组成,导入该组件时需要同时导入js和css。 vite-plugin-vue-style-bundler可以实现 自动提取Vue组件中的css样式一起打包到js源代码中,然后在运行时将style自动插入到head的vi…

GPT-4 VS Claude3、Gemini、Sora:五大模型的技术特点与用户体验

【最新增加Claude3、Gemini、Sora、GPTs讲解及AI领域中的集中大模型的最新技术】 2023年随着OpenAI开发者大会的召开,最重磅更新当属GPTs,多模态API,未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义,不亚…

Promise和事件轮询

Promise和事件轮询 今日目标: 1.Promise 要求:能够清楚的说出Promise的特性和静态方法 2.事件轮询 要求:能够理解清楚同步和异步在底层的实现机制 00-回顾 # ajax概述 async javascript and xml: 异步的js和xml作用: 实现客…

基于小波神经网络的回归分析,基于ANN的回归分析

目标 背影 BP神经网络的原理 BP神经网络的定义 BP神经网络的基本结构 BP神经网络的神经元 BP神经网络的激活函数, BP神经网络的传递函数 小波神经网络(以小波基为传递函数的BP神经网络) 代码链接:小波神经网络回归分析,小波分解+BP神经网络-机器学习文档类资源-CSDN文库 …

子矩阵(十四届蓝桥杯python组A)

这题思路就是用两次单调队列。 下面是TIE的代码。9/10&#xff1b;用了priority_queue做单调队列&#xff0c;而不是手动写的。 &#xff08;手写单调队列好麻烦~~~&#xff0c;脑子晕死&#xff0c;考试的时候过了9个点也ok&#xff0c;&#xff09; #include<iostream&…

如何与施耐德Schneider建立EDI连接?

EDI基础知识 何为EDI&#xff1f;是一个软件、系统还是一种流程呢&#xff1f;准确来说&#xff0c;EDI全称Electronic Data Interchange&#xff0c;中文名称是电子数据交换&#xff0c;也被称为“无纸化贸易”。EDI是&#xff1a; 标准化的数据格式连接业务系统间的数据桥梁…

阿里云通过脚本直接修改SSH配置来允许root登录并启用密码认证

看起来你想要通过脚本直接修改SSH配置来允许root登录并启用密码认证。然而&#xff0c;PermitRootLogin和PasswordAuthentication这两个指令是/etc/ssh/sshd_config文件中的配置选项&#xff0c;不能直接通过set命令在bash脚本中设置。set命令在shell脚本中用于设置或取消设置s…