[深度学习] Transformer

Transformer是一种深度学习模型,最早由Vaswani等人在2017年的论文《Attention is All You Need》中提出。它最初用于自然语言处理(NLP)任务,但其架构的灵活性使其在许多其他领域也表现出色,如计算机视觉、时间序列分析等。以下是对Transformer模型的详细介绍。

一、基本结构

Transformer模型主要由两个部分组成:编码器(Encoder)和解码器(Decoder)。

编码器(Encoder)
  • 输入嵌入(Input Embedding):将输入的词汇转换为高维向量表示。
  • 位置编码(Positional Encoding):由于Transformer没有循环结构或卷积结构,因此需要显式地加入位置信息。位置编码可以帮助模型了解序列中各个词汇的位置。
  • 多头自注意力机制(Multi-Head Self-Attention):自注意力机制可以捕捉序列中不同位置之间的依赖关系。多头机制允许模型关注不同的子空间。
  • 前馈神经网络(Feed-Forward Neural Network):两个线性变换和一个ReLU激活函数,独立地应用于每个位置。
  • 层归一化(Layer Normalization)残差连接(Residual Connection):每个子层的输出都进行层归一化,并通过残差连接加入子层输入。

编码器包含多个(通常是6个)这样的子层堆叠。

解码器(Decoder)

解码器的结构与编码器类似,但增加了一个用于接收编码器输出的注意力层。

  • 输入嵌入、位置编码、多头自注意力机制、前馈神经网络、层归一化和残差连接:与编码器相同。
  • 掩码多头自注意力机制(Masked Multi-Head Self-Attention):防止解码器当前位置注意到未来位置的信息。
  • 编码器-解码器注意力机制(Encoder-Decoder Attention):使解码器能关注编码器的输出,从而将编码器捕捉到的上下文信息用于生成目标序列。

解码器也包含多个(通常是6个)这样的子层堆叠。

在这里插入图片描述

二、详细机制

注意力机制(Attention Mechanism)

自注意力机制是Transformer的核心。它的计算过程如下:

  1. 计算查询(Query)、键(Key)、值(Value)矩阵
    在这里插入图片描述
    其中,X 是输入序列,WQ、WK、WV是可训练的权重矩阵。

  2. 计算注意力分数
    在这里插入图片描述
    其中:

    • dk是键向量的维度。
    • KT 是键矩阵的转置
  3. 多头机制
    多头注意力机制将输入映射到多个子空间,通过多个注意力头来捕捉不同的特征。然后将这些头的输出连接起来:
    在这里插入图片描述
    其中,每个头是独立的注意力机制,WO 是可训练的线性变换矩阵。

三、Transformer的优点

  1. 并行计算:不同于RNN的序列处理方式,Transformer允许并行计算,提高了训练速度。
  2. 长程依赖:通过自注意力机制,Transformer能够直接捕捉序列中任意位置之间的依赖关系。
  3. 灵活性:Transformer架构可以轻松扩展到不同任务,如语言翻译、文本生成、图像处理等。

四、变种和改进

自从Transformer被提出以来,已经出现了许多改进和变种,例如:

  • BERT(Bidirectional Encoder Representations from Transformers):双向编码器,适用于多种NLP任务。
  • GPT(Generative Pre-trained Transformer):生成模型,专注于文本生成任务。
  • T5(Text-to-Text Transfer Transformer):将所有NLP任务统一为文本到文本的形式。
  • Vision Transformer(ViT):将Transformer应用于图像分类任务。

五、应用领域

Transformer模型在以下领域表现出色:

  1. 自然语言处理(NLP):如机器翻译、文本生成、问答系统等。
  2. 计算机视觉:如图像分类、目标检测等。
  3. 时间序列分析:如股票预测、天气预报等。
  4. 推荐系统:通过捕捉用户与物品之间的复杂关系来提供个性化推荐。

六、代码示例

以下是一个使用TensorFlow实现简单Transformer的代码示例:

import tensorflow as tf
import numpy as np# 注意力机制
def scaled_dot_product_attention(q, k, v, mask):matmul_qk = tf.matmul(q, k, transpose_b=True)dk = tf.cast(tf.shape(k)[-1], tf.float32)scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)if mask is not None:scaled_attention_logits += (mask * -1e9)attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)output = tf.matmul(attention_weights, v)return output, attention_weights# 多头注意力
class MultiHeadAttention(tf.keras.layers.Layer):def __init__(self, d_model, num_heads):super(MultiHeadAttention, self).__init__()self.num_heads = num_headsself.d_model = d_modelassert d_model % self.num_heads == 0self.depth = d_model // self.num_headsself.wq = tf.keras.layers.Dense(d_model)self.wk = tf.keras.layers.Dense(d_model)self.wv = tf.keras.layers.Dense(d_model)self.dense = tf.keras.layers.Dense(d_model)def split_heads(self, x, batch_size):x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))return tf.transpose(x, perm=[0, 2, 1, 3])def call(self, v, k, q, mask):batch_size = tf.shape(q)[0]q = self.wq(q)k = self.wk(k)v = self.wv(v)q = self.split_heads(q, batch_size)k = self.split_heads(k, batch_size)v = self.split_heads(v, batch_size)scaled_attention, attention_weights = scaled_dot_product_attention(q, k, v, mask)scaled_attention = tf.transpose(scaled_attention, perm=[0, 2, 1, 3])concat_attention = tf.reshape(scaled_attention, (batch_size, -1, self.d_model))output = self.dense(concat_attention)return output, attention_weights# 前馈神经网络
def point_wise_feed_forward_network(d_model, dff):return tf.keras.Sequential([tf.keras.layers.Dense(dff, activation='relu'),tf.keras.layers.Dense(d_model)])# 编码器层
class EncoderLayer(tf.keras.layers.Layer):def __init__(self, d_model, num_heads, dff, rate=0.1):super(EncoderLayer, self).__init__()self.mha = MultiHeadAttention(d_model, num_heads)self.ffn = point_wise_feed_forward_network(d_model, dff)self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)self.dropout1 = tf.keras.layers.Dropout(rate)self.dropout2 = tf.keras.layers.Dropout(rate)def call(self, x, training, mask):attn_output, _ = self.mha(x, x, x, mask)attn_output = self.dropout1(attn_output, training=training)out1 = self.layernorm1(x + attn_output)ffn_output = self.ffn(out1)ffn_output = self.dropout2(ffn_output, training=training)out2 = self.layernorm2(out1 + ffn_output)return out2# 解码器层
class DecoderLayer(tf.keras.layers.Layer):def __init__(self, d_model, num_heads, dff, rate=0.1):super(DecoderLayer, self).__init__()self.mha1 = MultiHeadAttention(d_model, num_heads)self.mha2 = MultiHeadAttention(d_model, num_heads)self.ffn = point_wise_feed_forward_network(d_model, dff)self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)self.layernorm3 = tf.keras.layers.LayerNormalization(epsilon=1e-6)self.dropout1 = tf.keras.layers.Dropout(rate)self.dropout2 = tf.keras.layers.Dropout(rate)self.dropout3 = tf.keras.layers.Dropout(rate)def call(self, x, enc_output, training, look_ahead_mask, padding_mask):attn1, attn_weights_block1 = self.mha1(x, x, x, look_ahead_mask)attn1 = self.dropout1(attn1, training=training)out1 = self.layernorm1(x + attn1)attn2, attn_weights_block2 = self.mha2(enc_output, enc_output, out1, padding_mask)attn2 = self.dropout2(attn2, training=training)out2 = self.layernorm2(out1 + attn2)ffn_output = self.ffn(out2)ffn_output = self.dropout3(ffn_output, training=training)out3 = self.layernorm3(out2 + ffn_output)return out3, attn_weights_block1, attn_weights_block2# 编码器
class Encoder(tf.keras.layers.Layer):def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size, rate=0.1):super(Encoder, self).__init__()self.d_model = d_modelself.num_layers = num_layersself.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)self.pos_encoding = positional_encoding(1000, self.d_model)self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate) for _ in range(num_layers)]self.dropout = tf.keras.layers.Dropout(rate)def call(self, x, training, mask):seq_len = tf.shape(x)[1]x = self.embedding(x)x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))x += self.pos_encoding[:, :seq_len, :]x = self.dropout(x, training=training)for i in range(self.num_layers):x = self.enc_layers[i](x, training, mask)return x# 解码器
class Decoder(tf.keras.layers.Layer):def __init__(self, num_layers, d_model, num_heads, dff, target_vocab_size, rate=0.1):super(Decoder, self).__init__()self.d_model = d_modelself.num_layers = num_layersself.embedding = tf.keras.layers.Embedding(target_vocab_size, d_model)self.pos_encoding = positional_encoding(1000, self.d_model)self.dec_layers = [DecoderLayer(d_model, num_heads, dff, rate) for _ in range(num_layers)]self.dropout = tf.keras.layers.Dropout(rate)def call(self, x, enc_output, training, look_ahead_mask, padding_mask):seq_len = tf.shape(x)[1]attention_weights = {}x = self.embedding(x)x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))x += self.pos_encoding[:, :seq_len, :]x = self.dropout(x, training=training)for i in range(self.num_layers):x, block1, block2 = self.dec_layers[i](x, enc_output, training, look_ahead_mask, padding_mask)attention_weights[f'decoder_layer{i+1}_block1'] = block1attention_weights[f'decoder_layer{i+1}_block2'] = block2return x, attention_weights# Transformer模型
class Transformer(tf.keras.Model):def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size, target_vocab_size, rate=0.1):super(Transformer, self).__init__()self.encoder = Encoder(num_layers, d_model, num_heads, dff, input_vocab_size, rate)self.decoder = Decoder(num_layers, d_model, num_heads, dff, target_vocab_size, rate)self.final_layer = tf.keras.layers.Dense(target_vocab_size)def call(self, inp, tar, training, enc_padding_mask, look_ahead_mask, dec_padding_mask):enc_output = self.encoder(inp, training, enc_padding_mask)dec_output, attention_weights = self.decoder(tar, enc_output, training, look_ahead_mask, dec_padding_mask)final_output = self.final_layer(dec_output)return final_output, attention_weights# 位置编码
def positional_encoding(position, d_model):angle_rads = get_angles(np.arange(position)[:, np.newaxis], np.arange(d_model)[np.newaxis, :], d_model)angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])pos_encoding = angle_rads[np.newaxis, ...]return tf.cast(pos_encoding, dtype=tf.float32)def get_angles(pos, i, d_model):angle_rates = 1 / np.power(10000, (2 * (i // 2)) / np.float32(d_model))return pos * angle_rates# 掩码
def create_padding_mask(seq):seq = tf.cast(tf.math.equal(seq, 0), tf.float32)return seq[:, tf.newaxis, tf.newaxis, :]def create_look_ahead_mask(size):mask = 1 - tf.linalg.band_part(tf.ones((size, size)), -1, 0)return mask# 超参数
num_layers = 4
d_model = 128
dff = 512
num_heads = 8
input_vocab_size = 8500
target_vocab_size = 8000
dropout_rate = 0.1# 创建Transformer模型
transformer = Transformer(num_layers, d_model, num_heads, dff, input_vocab_size, target_vocab_size, dropout_rate)# 损失函数和优化器
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction='none')
def loss_function(real, pred):mask = tf.math.logical_not(tf.math.equal(real, 0))loss_ = loss_object(real, pred)mask = tf.cast(mask, dtype=loss_.dtype)loss_ *= maskreturn tf.reduce_sum(loss_) / tf.reduce_sum(mask)learning_rate = tf.keras.optimizers.schedules.ExponentialDecay(1e-4, decay_steps=100000, decay_rate=0.9, staircase=True)
optimizer = tf.keras.optimizers.Adam(learning_rate)# 编译模型
transformer.compile(optimizer=optimizer, loss=loss_function)# 示例输入
sample_input = tf.constant([[1, 2, 3, 4, 0, 0]])
sample_target = tf.constant([[1, 2, 3, 4, 0, 0]])# 训练模型
transformer.fit([sample_input, sample_target], epochs=10)
解释
  1. 注意力机制:定义了计算注意力权重的函数和多头注意力机制。
  2. 前馈神经网络:实现了前馈神经网络的部分。
  3. 编码器和解码器层:定义了编码器和解码器的基本层。
  4. 编码器和解码器:实现了编码器和解码器的堆叠。
  5. Transformer模型:集成了编码器和解码器,定义了完整的Transformer模型。
  6. 位置编码:为输入序列添加位置信息。
  7. 掩码:定义了填充掩码和前瞻掩码,用于处理输入和目标序列中的填充和防止信息泄露。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/37870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL高级-SQL优化- limit优化(覆盖索引加子查询)

文章目录 0、limit 优化0.1、从表 tb_sku 中按照 id 列进行排序,然后跳过前 9000000 条记录0.2、通过子查询获取按照 id 排序后的第 9000000 条开始的 10 条记录的 id 值,然后在原表中根据这些 id 值获取对应的完整记录 1、上传5个sql文件到 /root2、查看…

libctk shared library的设计及编码实践记录

一、引言 1.1 <libctk>的由来 1.2 <libctk>的设计理论依据 1.3 <libctk>的设计理念 二、<libctk>的依赖库 三、<libctk>的目录说明 四、<libctk>的功能模块及使用实例说明 4.1 日志模块 4.2 mysql client模块 4.3 ftp client模块 4…

鸿蒙开发设备管理:【@ohos.geolocation (位置服务)】

位置服务 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import geolocation from ohos.geolocation;geolocation.on(‘locationChange’) on(type: ‘locationChange’, request: L…

安卓开发自定义时间日期显示组件

安卓开发自定义时间日期显示组件 问题背景 实现时间和日期显示&#xff0c;左对齐和对齐两种效果&#xff0c;如下图所示&#xff1a; 问题分析 自定义view实现一般思路&#xff1a; &#xff08;1&#xff09;自定义一个View &#xff08;2&#xff09;编写values/attrs.…

poi-tl 生成 word 文件(插入文字、图片、表格、图表)

文章说明 本篇文章主要通过代码案例的方式&#xff0c;展示 poi-tl 生成 docx 文件的一些常用操作&#xff0c;主要涵盖以下内容 &#xff1a; 插入文本字符&#xff08;含样式、超链接&#xff09;插入图片插入表格引入标签&#xff08;通过可选文字的方式&#xff0c;这种方…

大模型和数据库最新结合进展

写在前面 本文主要内容是上次接受 infoQ 访谈&#xff0c;百度智能云朱洁老师介绍了大模型和 AI 结合相关话题&#xff0c;这次整体再刷新下&#xff0c;给到对这个领域感兴趣的同学。 当前&#xff0c;百度智能云云数据库特惠专场开始&#xff01;热销规格新用户免费使用&am…

最逼真的简易交通灯设计

最逼真的简易交通灯设计 需要资料的请在文章末尾获取&#xff08;有问题可以私信我哦~~&#xff09; 01 资料内容 Proteus仿真文件程序源码实物制作&#xff0c;代码修改&#xff0c;功能定制&#xff08;需额外收费&#xff0c;价格实惠&#xff0c;欢迎咨询&#xff09; …

实验场:在几分钟内使用 Elasticsearch 进行 RAG 应用程序实验

作者&#xff1a;来自 Elastic Joe McElroy, Serena Chou 什么是 Playground&#xff08;实验场&#xff09;&#xff1f; 我们很高兴发布我们的 Playground 体验 —- 一个低代码界面&#xff0c;开发人员可以在几分钟内使用自己的私人数据探索他们选择的 LLM。 在对对话式搜…

41割队伍

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/387 题目描述 给定 𝑛n 个数字 𝑎1,�…

Hi3861 OpenHarmony嵌入式应用入门--LiteOS Semaphore做同步使用

信号量作为同步使用 创建一个Semaphore对象&#xff0c;并指定一个初始的计数值&#xff08;通常称为“许可”或“令牌”的数量&#xff09;。这个计数值表示当前可用的资源数量或可以同时访问共享资源的线程数。当一个线程需要访问共享资源时&#xff0c;它会尝试从Semaphore…

加油站可视化:打造智能化运营与管理新模式

智慧加油站可视化通过图扑 HT 构建仿真的三维模型&#xff0c;将加油站的布局、设备状态、人员活动等信息动态呈现。管理者可以通过直观的可视化界面实时监控和分析运营状况&#xff0c;快速做出决策&#xff0c;提高管理效率和安全水平&#xff0c;推动加油站向智能化管理转型…

后端之路第三站(Mybatis)——结合案例讲Mybatis怎么操作sql

先讲一下准备工作整体流程要做什么 我们要基于一个员工管理系统作为案例&#xff0c;进行员工信息的【增、删、改、查】 原理就是用Mybatis通过java语言来执行sql语句&#xff0c;来达到【增、删、改、查】 一、准备工作 1、引入数据库数据 首先我们把一个员工、部门表的数…

【51单片机入门】速通定时器

文章目录 前言定时器是什么初始化定时器初始化的大概步骤TMOD寄存器C/T寄存器 触发定时器中断是什么中断函数定时器点亮led 总结 前言 在嵌入式系统的开发中&#xff0c;定时器是一个非常重要的组成部分。它们可以用于产生精确的时间延迟&#xff0c;或者在特定的时间间隔内触…

Java--常用类APl(复习总结)

前言: Java是一种强大而灵活的编程语言&#xff0c;具有广泛的应用范围&#xff0c;从桌面应用程序到企业级应用程序都能够使用Java进行开发。在Java的编程过程中&#xff0c;使用标准类库是非常重要的&#xff0c;因为标准类库提供了丰富的类和API&#xff0c;可以简化开发过…

【接口自动化测试】第三节.实现项目核心业务接口自动化

文章目录 前言一、实现登录接口对象封装和调用 1.0 登录接口的接口测试文档 1.1 接口对象层&#xff08;封装&#xff09; 1.2 测试脚本层&#xff08;调用&#xff09;二、课程新增接口对象封装和调用 2.0 课程新增接口的接口测试文档 2.1 接口对象层…

AVL树模拟

1.概念 虽然二叉搜索树可以缩短查找的效率&#xff0c;但如果数据有序或者接近有序时二叉搜索树树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。AVL 树是具有一下性质的二叉搜索树&#xff1a; 1.它的左右子树都是AVL树 2.左右子…

Mac 如何安装 wget

1.安装 Homebrew2.安装 wget3.检测 wget 是否安装成功 1.安装 Homebrew 在安装 wget 之前需要安装一个适用于 mac 的包管理器 Homebrew&#xff0c;打开 mac 终端执行如下命令进行安装&#xff1a; /usr/bin/ruby -e "$(curl -fsSL https://cdn.jsdelivr.net/gh/ineo6/h…

新手第一个漏洞复现:MS17-010(永恒之蓝)

文章目录 漏洞原理漏洞影响范围复现环境复现步骤 漏洞原理 漏洞出现在Windows SMB v1中的内核态函数srv!SrvOs2FeaListToNt在处理FEA&#xff08;File Extended Attributes&#xff09;转换时。该函数在将FEA list转换成NTFEA&#xff08;Windows NT FEA&#xff09;list前&am…

【Golang - 90天从新手到大师】Day14 - 方法和接口

一&#xff0e; go方法 go方法&#xff1a;在函数的func和函数名间增加一个特殊的接收器类型&#xff0c;接收器可以是结构体类型或非结构体类型。接收器可以在方法内部访问。创建一个接收器类型为Type的methodName方法。 func (t Type) methodName(parameter list) {}go引入…

解决“Duplicate keys detected: ‘ ‘.This may cause an update error.”问题

问题原因 出现“Duplicate keys detected”的错误&#xff0c;通常表示在v-for指令中使的:key绑定值有重复。 如果前端是静态数据&#xff0c;一般能自我避免:key绑定值有重复。如果前端是绑定的动态数据&#xff0c;那么需要另外提供一个唯一的键。 在这个例子中&#xff0c…