Transformer--详解

news2024/10/8 15:15:14

Transformer旨在解决自然语言处理任务中的长依赖性问题。与传统的递归神经网络(如LSTM、GRU)不同,Transformer完全摒弃了递归结构,依赖自注意力机制(Self-Attention)来建模输入序列中的所有位置之间的关系。因此,Transformer能够并行处理整个序列,这极大地提高了训练速度和效率。

Transformer在许多自然语言处理任务(如机器翻译、文本生成、文本分类等)中表现优异,尤其是大规模语言模型(如BERT、GPT、T5等)的基础架构。

Transformer的基本结构

Transformer模型由编码器(Encoder)解码器(Decoder)两个部分组成,二者都由堆叠的多层相似结构组成。以下是各部分的基本结构:

  1. 编码器(Encoder)

    • 编码器由多个层堆叠组成,每一层包括两个子层:

      1. 多头自注意力机制(Multi-Head Self-Attention):输入序列的所有位置之间进行相互注意,允许模型关注序列中不同部分的信息。

      2. 前馈神经网络(Feed-Forward Network):独立应用于每个位置。

    • 每个子层后都有一个残差连接和层归一化(Layer Normalization),使得梯度传播更为稳定。

  2. 解码器(Decoder)

    • 解码器也由多个层堆叠组成,但每层有三个子层:

      1. Masked 多头自注意力机制:确保模型在生成序列时,每个位置只能关注之前的位置。

      2. 编码器-解码器注意力:解码器关注编码器的输出。

      3. 前馈神经网络

    • 同样每个子层后都有残差连接和层归一化。

  3. 注意力机制(Attention Mechanism)

    • Transformer依赖于一种称为Scaled Dot-Product Attention的注意力机制。它通过计算查询(Query)、键(Key)和值(Value)之间的点积来生成注意力分数。

  4. 位置编码(Positional Encoding)

    • Transformer没有递归结构,因此模型需要一种方式来捕捉序列中的位置信息。位置编码通过正弦和余弦函数添加到输入嵌入上,帮助模型捕获位置信息。

Transformer的经典代码

以下是使用Keras实现Transformer编码器的简化代码示例:

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dense, LayerNormalization, Dropout, Embedding
from tensorflow.keras.models import Model
​
# Scaled Dot-Product Attention
def scaled_dot_product_attention(query, key, value, mask=None):
    matmul_qk = tf.matmul(query, key, transpose_b=True)  # 计算Q和K的点积
    dk = tf.cast(tf.shape(key)[-1], tf.float32)
    scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)  # 缩放
​
    if mask is not None:
        scaled_attention_logits += (mask * -1e9)  # 如果有mask,填充为负无穷
​
    attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)  # 归一化
    output = tf.matmul(attention_weights, value)  # 计算权重与V的乘积
    return output, attention_weights
​
# Multi-head Attention Layer
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 = Dense(d_model)
        self.wk = Dense(d_model)
        self.wv = Dense(d_model)
        self.dense = 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=None):
        batch_size = tf.shape(q)[0]
​
        # 通过线性层获得Q, K, V
        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([
        Dense(dff, activation='relu'),  # 第一层
        Dense(d_model)  # 第二层
    ])
​
# Transformer Encoder Layer
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 = LayerNormalization(epsilon=1e-6)
        self.layernorm2 = LayerNormalization(epsilon=1e-6)
​
        self.dropout1 = Dropout(rate)
        self.dropout2 = Dropout(rate)
​
    def call(self, x, mask=None):
        attn_output, _ = self.mha(x, x, x, mask)  # 自注意力
        attn_output = self.dropout1(attn_output)
        out1 = self.layernorm1(x + attn_output)  # 残差连接 + LayerNorm
​
        ffn_output = self.ffn(out1)  # 前馈
        ffn_output = self.dropout2(ffn_output)
        out2 = self.layernorm2(out1 + ffn_output)  # 残差连接 + LayerNorm
​
        return out2
​
# Transformer Encoder
class Encoder(tf.keras.layers.Layer):
    def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size, maximum_position_encoding, rate=0.1):
        super(Encoder, self).__init__()
​
        self.d_model = d_model
        self.num_layers = num_layers
​
        self.embedding = Embedding(input_vocab_size, d_model)
        self.pos_encoding = positional_encoding(maximum_position_encoding, self.d_model)
​
        self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate) for _ in range(num_layers)]
​
        self.dropout = Dropout(rate)
​
    def call(self, x, mask=None):
        seq_len = tf.shape(x)[1]
​
        # 添加embedding和位置编码
        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)
​
        for i in range(self.num_layers):
            x = self.enc_layers[i](x, mask)
​
        return x
​
# 位置编码
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])  # apply sin to even indices in the array
    angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])  # apply cos to odd indices in the array
    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

文本生成任务的示例代码

接下来是如何使用Transformer架构进行文本生成。这种生成任务可以视为基于语言模型的任务,即给定一部分文本,预测接下来的文本。

使用一个已经训练好的Transformer语言模型来生成文本,以下是简化的文本生成代码:

import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing.sequence import pad_sequences
​
# 假设已经有了一个训练好的Transformer模型
# 为了生成文本,需要以下步骤:
​
def generate_text(model, tokenizer, seed_text, max_sequence_len, num_words):
    for _ in range(num_words):
        token_list = tokenizer.texts_to_sequences([seed_text])[0]  # 将种子文本转换为token序列
        token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre')  # 填充序列
        predicted = model.predict(token_list, verbose=0)  # 预测下一个单词
        predicted_word_index = np.argmax(predicted, axis=-1)  # 获取最大概率的单词索引
        output_word = ""
        for word, index in tokenizer.word_index.items():
            if index == predicted_word_index:
                output_word = word
                break
        seed_text += " " + output_word  # 更新种子文本
    return seed_text
​
# 使用示例:
seed_text = "The future of AI"
generated_text = generate_text(model, tokenizer, seed_text, max_sequence_len=10, num_words=50)
print(generated_text)

代码解释:

  1. 多头注意力机制:实现了Transformer中的核心模块——多头注意力机制,它可以让模型同时关注输入序列中的不同部分。

  2. 前馈神经网络:每一层中除了注意力机制外,还包含一个前馈网络以增强模型的表达能力。

  3. 位置编码:用于给Transformer提供序列位置信息。

  4. 文本生成函数:利用训练好的模型进行文本预测,逐步生成句子。

总结

Transformer凭借其并行化的结构、自注意力机制以及位置编码技术,能够非常有效地处理长距离依赖问题。它被广泛应用于各类自然语言处理任务,尤其是在大规模预训练语言模型中(如BERT、GPT等)。

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

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

相关文章

ELK中L的filebeat配置及使用(超详细)

上一次讲解了如何在linux服务器上使用docker配置ELK中的E和K,这期着重讲解一下L怎么配置。 首先L在elk中指的是一个数据处理管道,可以从多种来源收集数据,进行处理和转换,然后将数据发送到 Elasticsearch。L的全称就是&#xff1…

国外电商系统开发-运维系统文件下载

文件下载,作者设计的比较先进,如果下载顺利,真的还需要点两次鼠标,所有的远程文件就自动的下载到了您的PC电脑上了。 现在,请您首选选择要在哪些服务器上下载文件: 选择好了服务器以后,现在选择…

【智能算法应用】人工水母搜索算法求解二维路径规划问题

摘要 本文应用人工水母搜索算法(Jellyfish Search, JFS)求解二维空间中的路径规划问题。水母搜索算法是一种新型的智能优化算法,灵感来源于水母的群体运动行为,通过模仿水母的觅食、漂浮等行为,实现全局最优路径的搜索…

51单片机基本知识

51单片机的基本知识 一、单片机介绍 单片机是单片微型计算机的简称,把各种功能部件包括中央处理器(CPU)、只读存储器(ROM)、随机读写存储器(RAM)、输入输出(I/O)单元、…

算法闭关修炼百题计划(四)

仅供个人复习 1.两数相加2.寻找峰值3.寻找旋转排序数组中的最小值4.寻找旋转排序数组中的最小值II5.搜索旋转排序数组6.岛屿的最大面积7.最大数8.会议室9.最长连续序列 1.两数相加 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储…

【微服务】网关 - Gateway(上)(day7)

概述 引入 在前几个系列中,使用Eureka、Consul、Nacos解决了服务注册、服务发现的问题;使用SpringCloudLoadBalancer解决了负载均衡的问题;使用OpenFeign解决了远程调用的问题。 但是现在所有的微服务接口都是直接对外暴露的,可…

【优选算法】(第二十八篇)

目录 K个⼀组翻转链表(hard) 题目解析 讲解算法原理 编写代码 两数之和(easy) 题目解析 讲解算法原理 编写代码 K个⼀组翻转链表(hard) 题目解析 1.题目链接:. - 力扣(Leet…

win11 24H2怎么安装_u盘安装win11 24H2详细步骤【支持新旧机型安装】

10月1日,微软正式发布了Windows 11 24H2正式版。对于win11 24h2新机器安装肯定是可以的,对于旧电脑在硬件配置上可能无法满足Windows 11 24h2的最低系统要求,如果按官方要求是无法安装win11的。但是如果采用第三方pe方式安装的话,…

Android Studio实现安卓图书管理系统

获取源码请点击文章末尾QQ名片联系,源码不免费,尊重创作,尊重劳动 171安卓小说 1.开发环境 android stuido3.6 jak1.8 2.功能介绍 安卓端: 1.注册登录 2.图书列表 3.图书借阅 4.借阅列表 3.系统截图

VSCode使用Code Runner插件运行时,路径错误问题

1. 问题介绍 由于Code Runner插件的工作目录与文件执行目录不同,而导致路径错误! 示例演示: 创建根目录test-dir,然后在里面分别创建两个目录code和data,分别存放Python程序read_file.py和输入数据input.txt read_fi…

PCIe配置篇(2)——如何进行配置操作(二)

一、配置机制 我们之前提到过,配置空间存在于PCIe设备上,而处理器通常无法直接执行配置读写请求,因为它只能生成内存和I/O请求。这意味着RC(Root Complex)需要将某些访问请求转换为配置请求,以支持配置空间…

人像抠图换背景怎么做?5款出色抠图工具让照片更加聚焦精彩

拍了一张很赞的照片,结果背景一团糟,完全抢了人像的风头?又或者在社交媒体上看到别人分享的图片,人像突出、背景清晰,而自己的总是差那么点意思? 别担心,现在有了人像抠图app,这些烦…

YOLOv10改进策略【注意力机制篇】| EMA 即插即用模块,提高远距离建模依赖(含二次创新)

一、本文介绍 本文记录的是基于EMA模块的YOLOv10目标检测改进方法研究。EMA认为跨维度交互有助于通道或空间注意力预测,并且解决了现有注意力机制在提取深度视觉表示时可能带来的维度缩减问题。在改进YOLOv10的过程中能够为高级特征图产生更好的像素级注意力&#…

浅谈 WMS 的应用行业_SunWMS智慧仓储物流系统

【大家好,我是唐Sun,唐Sun的唐,唐Sun的Sun。一站式数智工厂解决方案服务商】 仓库管理系统(WMS)已经成为众多行业优化运营、提高效率和竞争力的重要工具。WMS 的应用范围广泛,涵盖了制造业、零售业、电商、…

数据结构--堆的深度解析

目录 引言 一、基本概念 1.1堆的概念 1.2堆的存储结构 1.3堆的特点 二、 堆的基本操作 2.1初始化 2.2创建堆 2.3插入元素 2.4删除元素 2.5堆化操作 2.6堆的判空 2.7获取堆顶元素 三、堆的常见应用 1. 优先队列 2. 堆排序 3. Top-k 问题 4. 图论中的应用 四…

超享云服务器是什么意思?是免费的吗

超享云服务器是什么意思?超享云服务器是一种基于云计算技术,提供高性能、高可靠性和可扩展性的虚拟化服务器服务。它是通过虚拟化技术在物理服务器上运行,能够根据用户需求进行灵活的扩展和配置。虽然一些云服务提供商可能会提供免费试用期或…

Chromium 如何查找前端Browser 等对象定义在c++中的实现呢

以前端Navigator 对象为例: 1、直接在vscode里面搜索"Navigator" 过滤条件*.idl,这样可以搜到Navigator.idl对象文件。 2、打开Navigator.idl 可以看到平级目录对应的Navigator.h 和Navigator.cc定义 3、Navigator.idl会在out\Debug\gen\thir…

【bug】finalshell向远程主机拖动windows快捷方式导致卡死

finalshell向远程主机拖动windows快捷方式导致卡死 问题描述 如题,作死把桌面的快捷方式拖到了finalshell连接的服务器面板中,导致finalshell没有响应(小概率事件,有时会触发) 解决 打开任务管理器查看finalshell进…

基于SpringBoot博物馆游客预约系统【附源码】

基于SpringBoot博物馆游客预约系统 效果如下: 主页面 注册界面 展品信息界面 论坛交流界面 后台登陆界面 后台主界面 参观预约界面 留言板界面 研究背景 随着现代社会的快速发展和人们生活水平的提高,文化生活需求也在日益增加。博物馆作为传承文化、…

2024年10款好用的图纸加密软件推荐!企业CAD图纸加密推荐

随着企业信息安全意识的不断提高,尤其是在工业设计和制造领域,保护CAD图纸等核心技术资料的安全成为企业管理的重点。图纸一旦泄露,可能会给企业带来巨大的经济损失。因此,选择一款好用的图纸加密软件,对企业而言尤为重…