transformer实现词性标注

1、self-attention

1.1、self-attention结构图

上图是 Self-Attention 的结构,在计算的时候需要用到矩阵 Q(查询), K(键值), V(值)。在实际中,Self-Attention 接收的是输入(单词的表示向量 x组成的矩阵 X) 或者上一个 Encoder block 的输出。而 QK正是通过 Self-Attention 的输入进行线性变换得到的。

1.2 Q,K,V的计算

Self-Attention 的输入用矩阵 X进行表示,则可以使用线性变阵矩阵 WQWKWV 计算得到 QKV。计算如下图所示,注意 X, Q, K, V每一行都表示一个单词

 3.3 Self-Attention 的输出

得到矩阵 QKV之后就可以计算出 Self-Attention 的输出了,计算的公式如下: 

公式中计算矩阵 Q和 K 每一行向量的内积,为了防止内积过大,因此除以 dk 的平方根。乘以 K 的转置后,得到的矩阵行列数都为 n,n 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。下图为 乘以 的转置,1234 表示的是句子中的单词。

得到 QK^{T} 之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数,公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1。

对矩阵每一行进行softmax
​​​​​

 

得到 Softmax 矩阵之后可以和 V相乘,得到最终的输出 Z

self-attention输出

 上图中 Softmax 矩阵的第 1 行表示单词 1 与其他所有单词的 attention 系数,最终单词 1 的输出 Z1 等于所有单词 i 的值 Vi 根据 attention 系数的比例加在一起得到,如下图所示:

Zi的计算方法

class Attention(nn.Module):def __init__(self, input_n:int,hidden_n:int):super().__init__()self.hidden_n = hidden_nself.input_n=input_nself.W_q = torch.nn.Linear(input_n, hidden_n)self.W_k = torch.nn.Linear(input_n, hidden_n)self.W_v = torch.nn.Linear(input_n, hidden_n)def forward(self, Q, K, V, mask=None):Q = self.W_q(Q)K = self.W_k(K)V = self.W_v(V)attention_scores = torch.matmul(Q, K.transpose(-2, -1))attention_weights = softmax(attention_scores)output = torch.matmul(attention_weights, V)return output

2、multi-head attention

       

从上图可以看到 Multi-Head Attention 包含多个 Self-Attention 层,首先将输入 X分别传递到 h 个不同的 Self-Attention 中,计算得到 h 个输出矩阵 Z。下图是 h=8 时候的情况,此时会得到 8 个输出矩阵 Z

多个self-attention

 得到 8 个输出矩阵 Z1 到 Z8 之后,Multi-Head Attention 将它们拼接在一起 (Concat),然后传入一个 Linear层,得到 Multi-Head Attention 最终的输出 Z

Multi-Head Attention的输出

 可以看到 Multi-Head Attention 输出的矩阵 Z与其输入的矩阵 X 的维度是一样的。

class MultiHeadAttention(nn.Module):def __init__(self,hidden_n:int, h:int = 2):"""hidden_n: hidden dimensionh: number of heads"""super().__init__()embed_size=hidden_nheads=hself.embed_size = embed_sizeself.heads = heads# 每个head的处理的特征个数self.head_dim = embed_size // heads# 如果不能整除就报错assert (self.head_dim * self.heads == self.embed_size), 'embed_size should be divided by heads'# 三个全连接分别计算qkvself.values = nn.Linear(self.head_dim, self.head_dim, bias=False)self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)# 输出层self.fc_out = nn.Linear(self.head_dim * self.heads, embed_size)def forward(self, Q, K, V, mask=None):query,values,keys=Q,K,VN = query.shape[0]  # batch# 获取每个句子有多少个单词value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]# 维度调整 [b,seq_len,embed_size] ==> [b,seq_len,heads,head_dim]values = values.reshape(N, value_len, self.heads, self.head_dim)keys = keys.reshape(N, key_len, self.heads, self.head_dim)queries = query.reshape(N, query_len, self.heads, self.head_dim)# 对原始输入数据计算q、k、vvalues = self.values(values)keys = self.keys(keys)queries = self.queries(queries)# 爱因斯坦简记法,用于张量矩阵运算,q和k的转置矩阵相乘# queries.shape = [N, query_len, self.heads, self.head_dim]# keys.shape = [N, keys_len, self.heads, self.head_dim]# energy.shape = [N, heads, query_len, keys_len]energy = torch.einsum('nqhd, nkhd -> nhqk', [queries, keys])# 是否使用mask遮挡t时刻以后的所有q、kif mask is not None:# 将mask中所有为0的位置的元素,在energy中对应位置都置为 -1*10^10energy = energy.masked_fill(mask==0, torch.tensor(-1e10))# 根据公式计算attention, 在最后一个维度上计算softmaxattention = torch.softmax(energy/(self.embed_size**(1/2)), dim=3)# 爱因斯坦简记法矩阵元素,其中query_len == keys_len == value_len# attention.shape = [N, heads, query_len, keys_len]# values.shape = [N, value_len, heads, head_dim]# out.shape = [N, query_len, heads, head_dim]out = torch.einsum('nhql, nlhd -> nqhd', [attention, values])# 维度调整 [N, query_len, heads, head_dim] ==> [N, query_len, heads*head_dim]out = out.reshape(N, query_len, self.heads*self.head_dim)# 全连接,shape不变output = self.fc_out(out)return output

3、transformer block

3.1 encoder blockg构架图

 上图红色部分是 Transformer 的 Encoder block 结构,可以看到是由 Multi-Head Attention, Add & Norm, Feed Forward, Add & Norm 组成的。刚刚已经了解了 Multi-Head Attention 的计算过程,现在了解一下 Add & Norm 和 Feed Forward 部分。

3.2 Add & Norm

Add & Norm 层由 Add 和 Norm 两部分组成,其计算公式如下:

 其中 X表示 Multi-Head Attention 或者 Feed Forward 的输入,MultiHeadAttention(X) 和 FeedForward(X) 表示输出 (输出与输入 X 维度是一样的,所以可以相加)。

Add指 X+MultiHeadAttention(X),是一种残差连接,通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到。

残差连接

 Norm指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛。

3.3 Feed Forward

Feed Forward 层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激活函数,对应的公式如下。

Feed Forward

 X是输入,Feed Forward 最终得到的输出矩阵的维度与 X 一致。

class TransformerBlock(nn.Module):def __init__(self, hidden_n:int, h:int = 2):"""hidden_n: hidden dimensionh: number of heads"""super().__init__()embed_size=hidden_nheads=h# 实例化自注意力模块self.attention =MultiHeadAttention (embed_size, heads)# muti_head之后的layernormself.norm1 = nn.LayerNorm(embed_size)# FFN之后的layernormself.norm2 = nn.LayerNorm(embed_size)forward_expansion=1dropout=0.2# 构建FFN前馈型神经网络self.feed_forward = nn.Sequential(# 第一个全连接层上升特征个数nn.Linear(embed_size, embed_size * forward_expansion),# relu激活nn.ReLU(),# 第二个全连接下降特征个数nn.Linear(embed_size * forward_expansion, embed_size))# dropout层随机杀死神经元self.dropout = nn.Dropout(dropout)def forward(self, value, key, query, mask=None):attention = self.attention(value, key, query, mask)# 输入和输出做残差连接x = query + attention# layernorm标准化x = self.norm1(x)# dropoutx = self.dropout(x)# FFNffn = self.feed_forward(x)# 残差连接输入和输出forward = ffn + x# layernorm + dropoutout = self.dropout(self.norm2(forward))return out

transformer

import torch.nn as nn
class Transformer(nn.Module):def __init__(self,vocab_size, emb_n: int, hidden_n: int, n:int =3, h:int =2):"""emb_n: number of token embeddingshidden_n: hidden dimensionn: number of layersh: number of heads per layer"""embedding_dim=emb_nsuper().__init__()self.embedding_dim = embedding_dimself.embeddings = nn.Embedding(vocab_size,embedding_dim)self.layers=nn.ModuleList([TransformerBlock(hidden_n,h) for _ in range(n)    ])def forward(self,x):N,seq_len=x.shapeout=self.embeddings(x)for layer in self.layers:out=layer(out,out,out)return out

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

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

相关文章

新手将最简单的springboot部署上tomcat出现的意外问题

现阶段springboot部署到tomcat的文章一抓一大把且都相同,便贴一个地址以展示流程: SpringBoot打war包部署Tomcat(最全)_spring boot war 部署tomcat_聊Java的博客-CSDN博客 那么就说一下我出现的问题: 在完整复现流程且确认代码无误的情况下,部署到tomcat,此时问题出现了:启动…

(线特征)opencv+opencv contribute 配置

写一篇博客,记录开始线特征slam的历程。 在配置环境的时候,可以发现大多数都是用到了opencv3.4.16和其contribute版本,这里进行一个相关操作的教学。配置环境是在Ubuntu下面进行的,建议使用Ubuntu18来进行线特征的配置以及代码的…

【Axure高保真原型】中继器网格图片拖动摆放

今天和大家分享中继器网格图片拖动摆放的原型模板,我们可以通过鼠标拖动来移动图片,拖动过程其他图标会根据图片拖动自动排列,松开鼠标是图片停放在指定位置,其他图标自动排列。那这个模板是用中继器制作的,所以使用也…

培训机构到底靠不靠谱?

前言 英雄算法联盟八月集训 已经接近尾声,九月算法集训将于 09月01日(明天) 正式开始,目前已经提前开启报名,截至目前总人数为 2093 人,距离报名结束还有最后一天,报名方式见 这里,想…

经典文献阅读之--SLAMesh(网格化激光SLAM)

0. 简介 最近激光SLAM的新工作真的是越来越多了,而大多数当前的激光SLAM系统都是在点云中构建地图,即使在人眼看来是稠密的,但当放大时,点云是稀疏的。稠密地图对于机器人应用至关重要,例如基于地图的导航。由于内存成…

SQL语言-01

SQL Structured Query Language 的简单介绍 SQL 中的书写规则 SQL 中的数据类型

基于SpringBoot+Vue的旅游系统

摘 要 随着旅游业的发展,越来越多的人选择旅游作为自己的出行方式。在旅游规划过程中,旅游景点选择是至关重要的环节。本文提出了一种基于协同过滤推荐算法的旅游平台系统。该系统采用前后端分离的设计,主要使用了SpringBoot、Vue等技术&…

经纬恒润荣获吉利汽车“最佳价值贡献”奖

8月18日,以“全面向新 共创共赢”为主题,吉利汽车在宁波成功举行2023年电子电器核心供应商恳谈会。经纬恒润凭借在项目合作上持续创新、高效协同等优异表现,获得“最佳价值贡献”奖项。 作为国产汽车代表性品牌之一,吉利汽车积极推…

使用errors.Wrapf()代替log.Error()

介绍不同语言的错误处理机制: Error handling patterns[1] Musings about error handling mechanisms in programming languages[2] 项目中 main调func1,func1调取func2... 这样就会出现很多的 if err ! nil { log.Printf()} , 在Kibana上查看时会搜到多条日志, 需要…

汽车制造行业,配电柜如何实施监控?

工业领域的生产过程依赖于高效、稳定的电力供应,而配电柜作为电力分配和控制的关键组件,其监控显得尤为重要。 配电柜监控通过实时监测、数据收集和远程控制,为工业企业提供了一种有效管理电能的手段,从而确保生产的连续性、安全性…

Web 开发 Django 模板

上次为大家介绍了 Django 的模型和自带的管理工具,有了这个工具就可以全自动地根据模型创建后台管理界面,以供网站管理者更方便的管理网站数据。有了网站数据,那怎么样更方便又好看的展示给用户看呢?目前流行的 Web 框架基本都采用…

ChatGPT AIGC 一个指令总结Python所有知识点

在ChatGPT中,直接输入一个指令就可以生成Python的所有知识点大纲。 非常实用的ChatGPT功能。 AIGC ChatGPT ,BI商业智能, 可视化Tableau, PowerBI, FineReport, 数据库Mysql Oracle, Office, Python ,ETL Excel 2021 实操,函数,图表,大屏可视化 案例实战 http://t.…

小研究 - JVM 逃逸技术与 JRE 漏洞挖掘研究(一)

Java语言是最为流行的面向对象编程语言之一, Java运行时环境(JRE)拥有着非常大的用户群,其安全问题十分重要。近年来,由JRE漏洞引发的JVM逃逸攻击事件不断增多,对个人计算机安全造成了极大的威胁。研究JRE安…

【C++】线程安全问题

原子类型非线程安全 #include <iostream> #include <thread>int main() {int num 0;int count 100000;std::thread thread1([&](){for(int i 0; i < count; i){num;}});std::thread thread2([&](){for(int i 0; i < count; i){num;}});std::thr…

双亲委派机制

双亲委派机制流程 当Application ClassLoader 收到一个类加载请求时&#xff0c;他首先不会自己去尝试加载这个类&#xff0c;而是将这个请求委派给父类加载器Extension ClassLoader去完成。 当Extension ClassLoader收到一个类加载请求时&#xff0c;他首先也不会自己去尝试…

目标检测笔记(十一):如何结合特定区域进行目标检测(基于OpenCV的人脸检测实例)

文章目录 背景代码结果 背景 由于我们在做项目的时候可能会涉及到某个指定区域进行目标检测或者人脸识别等任务&#xff0c;所以这篇博客是为了探究如何在传统目标检测的基础上来结合特定区域进行检测&#xff0c;以OpenCV自带的包为例。 一般来说有两种方式实现区域指定&…

基于Java+SpringBoot+Mybaties-plus+Vue+ElementUI 高校汉服租赁网站的 设计与实现

一.项目介绍 高校汉服租赁网站分为普通用户以及管理员两类 普通用户&#xff1a; 注册、登录系统、查看汉服首页发帖公告信息、 交流论坛&#xff08;发帖、查看帖子、评论&#xff09;、 公告咨询&#xff08;查看公告以及评论&#xff09;、 汉服信息&#xff08;查…

在Windows操作系统上安装Neo4j数据库

在Windows操作系统上安装Neo4j数据库 一、在Windows操作系统上安装Neo4j数据库 一、在Windows操作系统上安装Neo4j数据库 点击 MySQL可跳转至MySQL的官方下载地址。 在VUE3项目的工程目录中&#xff0c;通过以下命令可生成node_modules文件夹。 npm install&#xff08;1&am…

docker 安装 Nginx

1、下载 docker pull nginx:latest 2、本地创建管理目录 mkdir -p /var/docker/nginx/conf mkdir -p /var/docker/nginx/log mkdir -p /var/docker/nginx/html 3、将容器中的相应文件复制到管理目录中 /usr/docker/nginx docker run --name nginx -p 80:80 -d nginxdocke…

基于Pytorch的神经网络部分自定义设计

一、基础概念&#xff08;学习笔记&#xff09; &#xff08;1&#xff09;训练误差和泛化误差[1] 本质上&#xff0c;优化和深度学习的目标是根本不同的。前者主要关注的是最小化目标&#xff0c;后者则关注在给定有限数据量的情况下寻找合适的模型。训练误差和泛化误差通常不…