【python、nlp、transformer】transformer与nlp感受器

Transformer的优势

相比之前占领市场的LSTM和GRU模型,Transformer有两个显著的优势:

1. Transformer能够利用分布式GPU进行并行训练,提升模型训练效率。

2. 在分析预测更长的文本时,捕捉间隔较长的语义关联效果更好.

认识Transformer架构

Transformer模型的作用:

基于seq2seq架构的transformer模型可以完成NLP领域研究的典型任务,如机器翻译,文本生成等.同时又可以构建预训练语言模型,用于不同任务的迁移学习.

声明:

在接下来的架构分析中,我们将假设使用Transformer模型架构处理从一种语言文本到另一种语言文本的翻译工作,因此很多命名方式遵循NLP中的规则.比如:Embeddding层将称作文本嵌入层,Embedding层产生的张量称为词嵌入张量,它的最后一维将称作词向量等

Transformer总体架构可分为四个部分:

输入部分

源文本嵌入层及其位置编码器

文本嵌入层的作用:无论是源文本嵌入还是目标文本嵌入,都是为了将文本中词汇的数字表示转变为向量表示,希望在这样的高维空间捕捉词汇间的关系.

位置编码器的作用:因为在Transformer的编码器结构中,并没有针对词汇位置信息的处理,因此需要在Embedding层后加入位置编码器,将词汇位置不同可能会产生不同语义的信息加入到词嵌入张量中,以弥补位置信息的缺失.

# 构建Embedding类实现文本嵌入层代码
import torch
import torch.nn as nn
import math
from torch.autograd import Variableclass Embeddings(nn.Module):def __init__(self, d_model, vocab):"""类的初始化Args:d_model (_type_): 词嵌入的维度vocab (_type_): 词表的大小"""super(Embeddings, self).__init__()self.lut = nn.Embedding(vocab, d_model)self.d_model = d_modeldef forward(self, x):"""前向传播函数Args:x (_type_): 输入的索引张量,形状为 (L, N)Returns:_type_: 词嵌入张量,形状为 (L, N, d_model)"""return self.lut(x) * math.sqrt(self.d_model)

文本嵌入层使用

d_model=512
vocab=1000
x=Variable(torch.LongTensor([[1,2,3,4,5],[6,7,8,9,10]]))
embedding_layer=Embeddings(d_model,vocab)
output=embedding_layer(x)
print(output)

位置编码器

# 位置编码器
class PositionalEncoding(nn.Module):def __init__(self, d_model, dropout, max_len=5000):"""位置编码器Args:d_model (_type_): 词嵌入的维度dropout (_type_): 置零的比例,让一定的神经元失效max_len (int, optional): 每个句子的最大长度. Defaults to 5000."""super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(p=dropout)# 初始化位置编码矩阵pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len).unsqueeze(1)div_term=torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) /d_model))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0)self.register_buffer('pe', pe)def forward(self, x):"""_summary_Args:x (_type_): 文本序列的的词嵌入表示"""x=x+Variable(self.pe[:, :x.size(1)], requires_grad=False)return self.dropout(x)

使用 

# 绘制词汇向量中特征的分布曲线
import matplotlib.pyplot as plt
import numpy as npplt.figure(figsize=(15, 5))
pe=PositionalEncoding(20,0)
y=pe(Variable(torch.zeros(1, 100,20)))
plt.plot(np.arange(100), y[0, :, 4:8].data.numpy())
plt.legend(['dim %d'%p for p in [4, 5,  6, 7]])
# 输出效果分析:
# 每条颜色的曲线代表某一个词汇中的特征在不同位置的含义.
# 保证同一词汇随着所在位置不同它对应位置嵌入向量会发生变化.
# 正弦波和余弦波的值域范围都是1到﹣1这又很好的控制了嵌入数值的大小,有助于梯度的快速计算.
目标文本嵌入层及其位置编码器

输出部分

线性层的作用:通过对上一步的线性变化得到指定维度的输出,也就是转换维度的作用.

softInax层的作用:使最后一维的向量中的数字缩放到0-1的概率值域内,并满足他们的和为1.

import torch.nn.functional as F
class Generator(nn.Module):def __init__(self, d_model, vocab):super(Generator, self).__init__()self.proj = nn.Linear(d_model, vocab)def forward(self, x):return F.log_softmax(self.proj(x), dim=-1)

编码器部分

由N个编码器层堆叠而成

每个编码器层由两个子层连接结构组成

第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接

第二个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接

class Encoder(nn.Module):def __init__(self, layer, N):"""_summary_Args:layer (_type_): 编码器层N (_type_): 编码器层个数"""super(Encoder, self).__init__()self.layers=clones(layer, N)self.norm=LayerNorm(layer.size)def forward(self, x, mask):for layer in self.layers:x=layer(x, mask)return self.norm(x)

解码器部分

由N个解码器层堆叠而成

每个解码器层由三个子层连接结构组成

第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接

第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接

第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接

class Decoder(nn.Module):def __init__(self, layer, N):super(Decoder, self).__init__()self.layers=clones(layer, N)self.norm=LayerNorm(layer.size)def forward(self, x, memory, src_mask, tgt_mask):for layer in self.layers:x=layer(x, memory, src_mask, tgt_mask)return self.norm(x)

专用名词

掩码张量

什么是掩码张量?

掩代表遮掩,码就是我们张量中的数值,它的尺寸不定,里面一般只有1和0的元素,代表位置被遮掩或者不被遮掩,至于是0位置被遮掩还是1位置被遮掩可以自定义,因此它的作用就是让另外一个张量中的一些数值被遮掩,也可以说被替换,它的表现形式是一个张量。

掩码张量的作用:

在transformer中,掩码张量的主要作用在应用attention(将在下一小节讲解)时,有一些生成的attention张量中的值计算有可能已知了未来信息而得到的,未来信息被看到是因为训练时会把整个输出结果都一次性进行Embedding,但是理论上解码器的的输出却不是一次就能产生最终结果的,而是一次次通过上一次结果综合得出的,因此,未来的信息可能被提前利用.所以,我们会进行遮掩。

def subsquest_mask(size):"""生成掩码张量代码Args:size (_type_): 掩码张量最后两个维度的大小,它的最后两维形成一个方阵"""attn_shape=(1, size, size)subsquest_mask=np.triu(np.ones(attn_shape), k=1).astype('uint8')return torch.from_numpy(1-subsquest_mask)

注意力机制

什么是注意力?

我们观察事物时,之所以能够快速判断一种事物(当然允许判断是错误的), 是因为我们大脑能够很快把注意力放在事物最具有辨识度的部分从而作出判断,而并非是从头到尾的观察一遍事物后,才能有判断结果.正是基于这样的理论,就产生了注意力机制.

注意力计算规则:

它需要三个指定的输入Q(query), K(key), V(value), 然后通过公式得到注意力的计算结果,这个结果代表query在key和value作用下的表示.而这个具体的计算规则有很多种,我这里只介绍我们用到的这一种.

什么是注意力机制:

注意力机制是注意力计算规则能够应用的深度学习网络的载体,除了注意力计算规则外,还包括一些必要的全连接层以及相关张量处理,使其与应用网络融为一体.使用自注意力计算规则的注意力机制称为自注意力机制.

注意力机制的计算规则 

import torch.nn.functional as Fdef attention(query, key, value, mask=None, dropout=None):"""注意力机制的实现代码Args:query (_type_): 查询向量,是一段准备被概括的文本key (_type_): 键向量,是给出的提示value (_type_): 值向量,是大脑中的对提示K的延伸mask (_type_, optional): 掩码张量. Defaults to None.dropout (_type_, optional): 丢弃率. Defaults to None.Returns:_type_: 注意力机制的输出"""d_k=query.size(-1)scores=torch.matmul(query, key.transpose(-2, -1))/math.sqrt(d_k)if mask is not None:scores=scores.masked_fill(mask==0, -1e9)p_attn=F.softmax(scores, dim=-1)if dropout is not None:p_attn=dropout(p_attn)return torch.matmul(p_attn, value), p_attn

多头注意力机制

只有使用了一组线性变化层,即三个变换张量对Q,K,V分别进行线性变换,这些变换不会改变原有张量的尺寸,因此每个变换矩阵都是方阵。

得到输出结果后,多头的作用才开始显现,每个头开始从词义层面分割输出的张量,也就是每个头都想获得一组Q,K,V 进行注意力机制的计算,但是句子中的每个词的表示只获得一部分,也就是只分割了最后一维的词嵌入向量,这就是所谓的多头。

将每个头的获得的输入送到注意力机制中,就形成多头注意力机制.

多头注意力机制的作用:这种结构设计能让每个注意力机制去优化每个词汇的不同特征部分,从而均衡同一种注意力机制可能产生的偏差,让词义拥有来自更多元的表达,实验表明可以从而提升模型效果。

import copydef clones(module, N):"""用于生成相同的网络层Args:module (_type_): 要克隆的目标网络层N (_type_): 需要克隆的数量"""return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])class MultiHeadedAttention(nn.Module):def __init__(self, head, embedding_dim, dropout=0.1):"""多头注意力机制的实现代码Args:head (_type_): 头数embedding_dim (_type_): 词嵌入维度dropout (_type_, optional): 丢弃率. Defaults to 0.1."""super(MultiHeadedAttention, self).__init__()# 保证d_model是头数的整数倍assert embedding_dim%head==0self.d_k=embedding_dim // headself.head=headself.embedding_dim=embedding_dimself.linears=clones(nn.Linear(embedding_dim, embedding_dim), 4)self.attn=Noneself.dropout=nn.Dropout(p=dropout)def forward(self, query, key, value, mask=None):"""前向逻辑结构Args:query (_type_): _description_key (_type_): _description_value (_type_): _description_mask (_type_, optional): _description_. Defaults to None."""if mask is not None:mask=maskbatch_size=query.size(0)query, key, value = [model(x).view(batch_size, -1, self.head, self.d_k).transpose(1, 2) for model, x in zip(self.linears, (query, key, value))]x, self.attn = attention(query, key, value, mask, self.dropout)x = x.transpose(1, 2).contiguous().view(batch_size, -1, self.head * self.d_k)return self.linears[-1](x)

前馈全连接层

在Transformer中前馈全连接层就是具有两层线性层的全连接网络.

前馈全连接层的作用:

考虑注意力机制可能对复杂过程的拟合程度不够,通过增加两层网络来增强模型的能力.

class PositionwiseFeedForward(nn.Module):def __init__(self, d_model, d_ff, dropout=0.1):"""_summary_Args:d_model (_type_): _description_d_ff (_type_): 词嵌入的维度dropout (float, optional): _description_. Defaults to 0.1."""super(PositionwiseFeedForward, self).__init__()self.w1=nn.Linear(d_model, d_ff)self.w2=nn.Linear(d_ff, d_model)self.dropout=nn.Dropout(dropout)def forward(self, x):return self.w2(self.dropout(torch.relu(self.w1(x))))

规范化层

规范化层的作用:

它是所有深层网络模型都需要的标准网络层,因为随着网络层数的增加,通过多层的计算后参数可能开始出现过大或过小的情况,这样可能会导致学习过程出现异常,模型可能收敛非常的慢.因此都会在一定层数后接规范化层进行数值的规范化,使其特征数值在合理范围内.

class LayerNorm(nn.Module):def __init__(self, features, eps=1e-6):"""_summary_Args:features (_type_): 词嵌入维度eps (_type_, optional): 防止分母为0. Defaults to 1e-6."""super(LayerNorm, self).__init__()self.a2=nn.Parameter(torch.ones(features))self.b2=nn.Parameter(torch.zeros(features))self.eps=epsdef forward(self, x):"""_summary_Args:x (_type_): 上一层的输出"""mean=x.mean(-1, keepdim=True)std=x.std(-1, keepdim=True)return self.a2*(x-mean)/(std+self.eps)+self.b2

子层连接结构

输入到每个子层以及规范化层的过程中,还使用了残差链接(跳跃连接),因此我们把这一部结构整体叫做子层连接(代表子层及其链接结构),在每个编码器层中,都有两个子层,这两个子层加上周围的链接结构就形成了两个子层连接结构.

class SublayerConnection(nn.Module):def __init__(self, size, dropout):"""_summary_Args:size (_type_): 词嵌入维度dropout (_type_): 随机抑制比率"""super(SublayerConnection, self).__init__()self.norm=LayerNorm(size)self.dropout=nn.Dropout(dropout)def forward(self, x, sublayer):return x+self.dropout(sublayer(self.norm(x)))

编码器层

编码器层的作用:作为编码器的组成单元,每个编码器层完成一次对输入的特征提取过程,即编码过程

class EncoderLayer(nn.Module):def __init__(self, size, self_attn, feed_forward, dropout):"""_summary_Args:size (_type_): 词维度大小self_attn (_type_): 多头注意力层feed_forward (_type_): 实例化的前馈全连接层dropout (_type_): _description_"""super(EncoderLayer, self).__init__()self.self_attn=self_attnself.feed_forward=feed_forwardself.sublayer=clones(SublayerConnection(size, dropout),2)self.size=sizedef forward(self, x, mask):x=self.sublayer[0](x, lambda x:self.self_attn(x, x, x, mask))return self.sublayer[1](x, self.feed_forward)

解码器层

class DecoderLayer(nn.Module):def __init__(self, size, self_attn, src_attn, feed_forward, dropout):"""_summary_Args:size (_type_): 词维度大小self_attn (_type_): 注意力机制,自注意力src_attn (_type_): 非自注意力机制feed_forward (_type_): 前馈全连接层dropout (_type_): _description_"""super(DecoderLayer, self).__init__()self.size=sizeself.self_attn=self_attnself.src_attn=src_attnself.feed_forward=feed_forwardself.sublayer=clones(SublayerConnection(size, dropout), 3)def forward(self, x, memory, src_mask, tgt_mask):"""_summary_Args:x (_type_): 上一层输入memory (_type_): 来自编码器层语义储存变量src_mask (_type_): 源数据掩码张量tgt_mask (_type_): 目标数据掩码张量"""m=memoryx=self.sublayer[0](x, lambda x: self.self_attn(x, x, x, tgt_mask))x=self.sublayer[1](x, lambda x: self.src_attn(x, m, m, src_mask))return self.sublayer[2](x, self.feed_forward)

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

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

相关文章

ARM系列 -- 虚拟化(一)

今天来研究一个有意思的话题,虚拟化(virtualization)。 开始前,先闲扯一下,最近一个词比较火,“元宇宙(Metaverse)”。在维基百科里面是这么定义元宇宙的,“The Metaver…

2024-02-27(Kafka)

1.Kafka中所有的消息都是保存在主题中的,要生产消息到Kafka,首先必须要创建一个主题。 2.Kafka的生产者/消费者 安装kafka集群,可以测试如下: 创建一个topic主题(消息都是存放在topic中,类似mysql建表的过…

iMazing 3.0.0.3 for mac 中文破解版2024最新图文安装教程

我们刚刚发布了iMazing 3.0.0.3 for mac 中文版本。Windows和macOS用户现在都可以试驾并体验iPhone管理的未来。 备受期待的第一个Windows版本得益于过去几个月macOS测试版的所有改进,使其成为一个稳定的初始版本。 我们的开发团队创造了一种无缝的外观和体验&#…

Android日历提醒增删改查事件、添加天数不对问题

Android日历提醒是非常好的提醒功能&#xff0c;笔者在做的过程中&#xff0c;遇到的一些问题&#xff0c;现整理出来&#xff0c;以供参考。 一、申请日历的读写权限 <uses-permission android:name"android.permission.WRITE_CALENDAR" /> <uses-permiss…

Lua速成(5)table

一、table table 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型&#xff0c;如&#xff1a;数组、字典等。 Lua table 使用关联型数组&#xff0c;你可以用任意类型的值来作数组的索引&#xff0c;但这个值不能是 nil。 Lua table 是不固定大小的&#xff0c;你可以…

springboot-基础-eclipse集成mybatis+使用方法+排错

备份笔记。所有代码都是2019年测试通过的&#xff0c;如有问题请自行搜索解决&#xff01; 目录 集成mybatis安装mybatis的jar包安装插件&#xff1a;mybatis-generator安装方法生成方法报错&#xff1a;java.lang.RuntimeException: Exception getting JDBC Driver mybatis注解…

数据之美:用山海鲸展现数据魅力

在数据分析领域&#xff0c;数据可视化是一个至关重要的环节。作为一名资深的数据分析师&#xff0c;我深知一个直观、易于理解的数据可视化看板对于传达信息、辅助决策的重要性。今天&#xff0c;我将以自己在用的山海鲸可视化软件为例&#xff0c;与大家分享如何制作一个高效…

LeetCode 热题 100 | 图论(上)

目录 1 200. 岛屿数量 2 994. 腐烂的橘子 2.1 智障遍历法 2.2 仿层序遍历法 菜鸟做题&#xff0c;语言是 C 1 200. 岛屿数量 解题思路&#xff1a; 遍历二维数组&#xff0c;寻找 “1”&#xff08;若找到则岛屿数量 1&#xff09;寻找与当前 “1” 直接或间接连接在…

项目登录方案选型

一.Cookie + Session 登录 大家都知道,HTTP 是一种无状态的协议。无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即我们给服务器发送 HTTP 请求之后,服务器根据请求返回数据,但不会记录任何信息。为了解决 HTTP 无状态的问题,出现了 Cookie。Co…

离线数仓(四)【数仓数据同步策略】

前言 今天来把数仓数据同步解决掉&#xff0c;前面我们已经把日志数据到 Kafka 的通道打通了。 1、实时数仓数据同步 关于实时数仓&#xff0c;我们的 Flink 直接去 Kafka 读取即可&#xff0c;我们在学习 Flink 的时候也知道 Flink 提供了 Kafka Source&#xff0c;所以这里不…

协议-http协议-基础概念02-请求应答过程-请求响应报文结构-头部字段-请求方法-响应方式

参考来源&#xff1a; 极客时间-透视HTTP协议(作者&#xff1a;罗剑锋)&#xff1b; web抓包实战课-陶辉&#xff1b; 01-HTTP协议请求-应答过程 最简单的浏览器 HTTP 请求过程 浏览器从地址栏的输入中获得服务器的 IP 地址和端口号&#xff1b;浏览器用 TCP 的三次握手与服…

CSS复合选择器(一)

CSS复合选择器&#xff08;一&#xff09; 1.交集选择器2. 并集选择器3. 后代选择器4. 子代选择器5.兄弟选择器5.1相邻兄弟选择器&#xff1a;5.2通用兄弟选择器&#xff1a; 6.属性选择器 1.交集选择器 作用&#xff1a;选中同时符合多个条件的元素。 交集有并且的含义&#…

基于springboot的4S店车辆管理系统源码和论文

随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&#xf…

python中写monogo的uri参数里,为什么有多个IP,是连接多个服务器吗

问题来源&#xff1a; 代码如下&#xff1a; from pymongo import MongoClientmongo_uri "mongodb://admin:password192.168.93.23:32725,192.132.9.35:32740,192.22.16.42:30538/?" # 创建MongoClient实例 client MongoClient(mongo_uri)为什么uri中会存在多个…

win10开机黑屏,只有鼠标,解决方案

问题描述 win10进不去桌面&#xff0c;可以进去锁屏&#xff0c;只有鼠标&#xff0c;也能进去任务管理器&#xff08;ctrlwindelete&#xff09;, 问题分析 进入任务管理器->文件->运行新任务 然后输入 explorer.exe 发现找不到了 原因&#xff1a;误删explorer.exe …

Linux系统---nginx(1)服务

目录 一.Nginx概述 1.定义 2.Nginx模块作用 &#xff08;1&#xff09;main模块 &#xff08;2&#xff09;stream服务模块 &#xff08;3&#xff09;邮件服务模块 &#xff08;4&#xff09;第三方模块 &#xff08;5&#xff09;events模块 &#xff08;6&#xff0…

300分钟吃透分布式缓存-16讲:常用的缓存组件Redis是如何运行的?

Redis 基本原理 Redis 简介 Redis 是一款基于 ANSI C 语言编写的&#xff0c;BSD 许可的&#xff0c;日志型 key-value 存储组件&#xff0c;它的所有数据结构都存在内存中&#xff0c;可以用作缓存、数据库和消息中间件。 Redis 是 Remote dictionary server 即远程字典服务…

SpringCloud有哪些组件

什么是SpringCloud&#xff1f; Spring Cloud是基于Spring Boot的分布式系统开发工具&#xff0c;它提供了一系列开箱即用的、针对分布式系统开发的特性和组件&#xff0c;用于帮助开发人员快速构建和管理云原生应用程序。 Spring Cloud的主要目标是解决分布式系统中的常见问题…

linux使用 busybox microcom AT指令测试4G/5G模块

1、busybox microcom命令使用方法如下&#xff1a; 参数&#xff1a; -d&#xff1a;表示延时时间&#xff0c;一般不设置。 -t&#xff1a;表示超时时间&#xff0c;超多长时间后该命令自动退出。单位为ms。 -s&#xff1a;表示传输速度&#xff0c;即串口波特率。 -X&#…

阿里云oss工具ossutil使用手册(windows)

一、下载安装 下载地址和教程 安装ossutil。 单击下载链接下载Windows安装包。 将工具解压&#xff0c;并双击运行ossutil.bat文件。 配置ossutil。 输入配置命令。 ossutil config 根据提示设置配置文件路径。 请输入配置文件名&#xff0c;文件名可以带路径&#xff08;…