[深度学习] 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_heads
        self.d_model = d_model
        assert d_model % self.num_heads == 0
        self.depth = d_model // self.num_heads
        self.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_model
        self.num_layers = num_layers
        self.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_model
        self.num_layers = num_layers
        self.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'] = block1
            attention_weights[f'decoder_layer{i+1}_block2'] = block2
        return 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_ *= mask
    return 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.mfbz.cn/a/747418.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Orangepi Zero2使用外设驱动库wiringOP配合时间函数驱动HC-SR04超声波测距模块

目录 一、HC-SR04超声波模块原理和硬件接线 1.1 超声波测距原理: 1.2 超声波时序图: 1.3 HC-SR04超声波模块硬件接线: 二、时间函数 2.1 时间函数gettimeofday()原型和头文件: 2.2 使用gettimeofday()函数获取当前时间的秒数…

经验分享,免费商标查询网站

有时候想快速查询商标状况,官方网站比较慢,这里分享一个免费快速的网站。 网址:https://www.sscha.com/ 截图:

platform 设备驱动实验

platform 设备驱动实验 Linux 驱动的分离与分层 代码的重用性非常重要,否则的话就会在 Linux 内核中存在大量无意义的重复代码。尤其是驱动程序,因为驱动程序占用了 Linux内核代码量的大头,如果不对驱动程序加以管理,任由重复的…

电脑没声音是什么原因?一篇文章帮你解决疑惑

在使用电脑时,声音是至关重要的一部分,无论是播放音乐、观看视频还是进行视频会议。然而,有时候电脑可能会出现没声音的情况,这让人感到非常困扰。那么电脑没声音是什么原因呢?本文将详细介绍解决电脑没声音问题的三种…

【Java Web】XML格式文件

目录 一、XML是什么 二、常见配置文件类型 *.properties类型: *.xml类型: 三、DOM4J读取xml配置文件 3.1 DOM4J的使用步骤 3.2 DOM4J的API介绍 一、XML是什么 XML即可扩展的标记语言,由标记语言可知其基本语法和HTML一样都是由标签构成的文件…

仓库管理系统12--物资设置供应商设置

1、添加供应商窗体 2、布局控件UI <UserControl x:Class"West.StoreMgr.View.SupplierView"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc"http://…

VLM系列文章1-LLaVA

作为VLM系列的第一篇文章&#xff0c;打算以LLaVA入手&#xff0c;毕竟是VLM领域较为经典的工作。 1. 核心贡献 多模态指令跟随数据&#xff1a;包括PT、SFT数据的构造流程&#xff1b;大型多模态模型&#xff1a;一种新的框架&#xff0c;结构较为简单高效&#xff1b;评估数…

深入了解 GPT-4 和 ChatGPT 的 API---使用 OpenAI Python 库

文章目录 OpenAI 访问权限和 API 密钥Hello World 示例程序使用 GPT-4 和 ChatGPTChatCompletion 端点的输入选项ChatCompletion 端点的输出格式 OpenAI 将 GPT-4 和 ChatGPT 作为服务提供。这意味着用户无法直接访问模型代码&#xff0c;也无法在自己的服务器上运行这些模型。…

牛客周赛 Round 48 解题报告 | 珂学家

前言 题解 这场感觉有点难&#xff0c;D完全没思路, EF很典&#xff0c;能够学到知识. E我的思路是容斥贡献&#xff0c;F很典&#xff0c;上周考过一次&#xff0c;引入虚拟节点质数(有点像种类并查集类似的技巧). 欢迎关注 珂朵莉 牛客周赛专栏 珂朵莉 牛客小白月赛专栏 …

【第十八课】区域经济分析——探索性空间数据分析软件实操

一、前言 ArcGIS有专门处理探索性空间数据分析方法的工具,即地统计分析模块。 该模块主要由三个功能模块组成:探索性数据分析(Explore)、地统计分析向导(Geostatistical Wizard),以及生成数据子集(Create Subsets)。其中利用 这些基本功能模块,可以方便完成多种地统…

Thinkphp/Laravel高校竞赛管理系统的设计与实现_9pi7u

高校竞赛管理&#xff0c;其工作流程繁杂、多样、管理复杂与设备维护繁琐。而计算机已完全能够胜任高校竞赛管理工作&#xff0c;而且更加准确、方便、快捷、高效、清晰、透明&#xff0c;它完全可以克服以上所述的不足之处。这将给查询信息和管理带来很大的方便&#xff0c;从…

【Qt】Qt多线程编程指南:提升应用性能与用户体验

文章目录 前言1. Qt 多线程概述2. QThread 常用 API3. 使用线程4. 多线的使用场景5. 线程安全问题5.1. 加锁5.2. QReadWriteLocker、QReadLocker、QWriteLocker 6. 条件变量 与 信号量6.1. 条件变量6.2 信号量 总结 前言 在现代软件开发中&#xff0c;多线程编程已成为一个不可…

数字图像分析(第三部分)

文章目录 第11章 基于概率图模型的图像分析概率有向图模型因子分解生成式模型链式图条件独立性有向图模型的马尔科夫毯概率无向图模型模型定义概率无向图模型的因子分解条件随机场条件随机场的定义条件随机场的预测算法第12章 运动分析运动相机建模光流运动表达方法运动估计准则…

AI软件革新文本操作体验:从自动粘贴文本到一键提取保存手机号码

在当今数字化时代&#xff0c;AI技术的快速发展为各行各业带来了革命性的变革。特别是在文本处理领域&#xff0c;AI软件通过其强大的自动粘贴文本功能以及一键提取并保存手机号码的便捷操作&#xff0c;极大地提高了工作效率&#xff0c;为用户带来了全新的体验。本文将深入探…

CSS 文本输入框右下角的尺寸控件(三斜线:-webkit-resizer)消除,以及如何配置其样式,添加 resize 让标签元素可进行拖拽放大。

前言&#xff1a;在日常的前端开发中&#xff0c;不管是原始的和 还在在各类组件库中的文本输入框中&#xff0c;元素内容的右下角总是有一个三斜线的样式&#xff0c;本文简单了解它是什么&#xff1f;如何去控制并修改样式&#xff1f; 一、它是&#xff1f; 这三个斜线其实…

v0.9.6 开源跨平台个人知识管理工具 TidGi-Desktop

在这个信息爆炸的时代&#xff0c;知识管理变得尤为重要。太记(TidGi)&#xff0c;一款基于太微(TiddlyWiki)的知识管理桌面应用&#xff0c;正是为了满足人们对信息整理、知识管理和个人隐私保护的需求而设计的。它不仅能够帮助用户高效地管理和整理信息&#xff0c;还能够自动…

简化部署流程——无线UWB如何实现自标定?

一.什么是UWB信标自标定&#xff1f; UWB&#xff08;超宽带&#xff09;自标定是指在UWB系统中&#xff0c;基站或节点能够自动识别和确定自己的位置&#xff0c;无需外部干预或手动输入其地理位置信息。这种技术主要利用系统内部的信号测量和算法来自动计算节点之间的距离以…

使用PEFT库进行ChatGLM3-6B模型的LORA高效微调

PEFT库进行ChatGLM3-6B模型LORA高效微调 LORA微调ChatGLM3-6B模型安装相关库使用ChatGLM3-6B模型GPU显存占用准备数据集加载模型加载数据集数据处理数据集处理配置LoRA配置训练超参数开始训练保存LoRA模型模型推理从新加载合并模型使用微调后的模型 LORA微调ChatGLM3-6B模型 本…

【vue】vue响应式原理

vue响应式原理 vue2的响应式原理 vue2对对象类型的监听是通过Object.defineProperty实现的&#xff0c;给想要实现响应式的数据对象每个属性加上get,set方法&#xff0c;以实现数据劫持的操作。而对数组类型的监听是通过重写数组的方法实现的。 Object.defineProperty的定义…

组合数学、圆排列、离散数学多重集合笔记

自用 如果能帮到您&#xff0c;那也值得高兴 知识点 离散数学经典题目 多重集合组合 补充容斥原理公式 隔板法题目 全排列题目&#xff1a;