notes for datawhale summer camp NPL task3

了解 Transformer 模型,并基于 Transformer 模型实现在机器翻译任务上的应用

Transformer 介绍

基于循环卷积神经网络的序列到序列建模方法是现存机器翻译任务中的经典方法。然而,它们在建模文本长程依赖方面都存在一定的局限性

为了更好地描述文字序列,谷歌的研究人员在 2017 年提出了一种新的模型 Transformer

Transformer 视频讲解

它摒弃了循环结构,并完全通过注意力机制完成对源语言序列和目标语言序列全局依赖的建模。在抽取每个单词的上下文特征时,Transformer 通过自注意力机制(self-attention)衡量上下文中每一个单词对当前单词的重要程度

Transformer 的主要组件包括编码器 (Encoder)、解码器 (Decoder) 和注意力层。其核心是利用多头自注意力机制(Multi-Head Self-Attention)

// 关于 Transformer的20题

Transformer 模型基本架构

Transformer 模型基本架构

layer

  • sublayer
    • multi-head self-attention
    • positionwise feed-forword network

嵌入表示层

输入文本序列,生成词向量 + 位置编码

为了得到不同位置对应的编码,Transformer 模型使用不同频率的正余弦函数如下所示
P E p o s , 2 i = sin ⁡ ( p i s / 1000 0 2 i / d ) PE_{pos, 2i}=\sin(pis/10000^{2i/d}) PEpos,2i=sin(pis/100002i/d)
P E p o s , 2 i + 1 = cos ⁡ ( p i s / 1000 0 2 i / d ) PE_{pos, 2i+1}=\cos(pis/10000^{2i/d}) PEpos,2i+1=cos(pis/100002i/d)

注意力层

**自注意力(Self-Attention)**操作是基于 Transformer 的机器翻译模型的基本操作,在源语言的编码和目标语言的生成中频繁地被使用以建模源语言、目标语言任意两个单词之间的依赖关系
给定由单词语义嵌入及其位置编码叠加得到的输入表示 { x i ∈ R d } i = 1 t \{x_{i} \in R^{d}\}_{i=1}^{t} {xiRd}i=1t
为了实现对上下文语义依赖的建模,进一步引入在自注意力机制中涉及到的三个元素:查询 q i ( Q u e r y ) q_{i}(Query) qiQuery ,键 k i ( K e y ) k_{i}(Key) kiKey ,值 v i ( V a l u e ) v_{i}(Value) viValue
通过位置 i i i 查询向量与其他位置的键向量做点积得到匹配分数 q i ⋅ k 1 , q i ⋅ k 2 , . . . , q i ⋅ k t q_{i}\cdot k_{1},q_{i}\cdot k_{2},...,q_{i}\cdot k_{t} qik1,qik2,...,qikt
Z = A t t e n t i o n ( Q , K , V ) = S o f t m a x ( Q K T d ) V Z=Attention(Q,K,V)=Softmax(\frac{QK^{T}}{\sqrt{d}})V Z=Attention(Q,K,V)=Softmax(d QKT)V
其中 Q ∈ R L × d q Q \in R^{L\times d_{q}} QRL×dq, K ∈ R L × d k K \in R^{L\times d_{k}} KRL×dk, V ∈ R L × d v V \in R^{L\times d_{v}} VRL×dv 分别表示输入序列中的不同单词的 q , k , v q,k,v q,k,v 向量拼接组成的矩阵,L 表示序列长度, Z ∈ R L × d v Z \in R^{L\times d_{v}} ZRL×dv 表示自注意力操作的输出, d \sqrt{d} d 表示稳定优化的放缩因子

//🤡

前馈层

前馈层接受自注意力子层的输出作为输入,并通过一个带有 Relu 激活函数的两层全连接网络对输入进行更加复杂的非线性变换
F F N ( x ) = R e l u ( x W 1 + b 1 ) W 2 + b 2 FFN(x)=Relu(xW_{1}+b_{1})W_{2}+b_{2} FFN(x)=Relu(xW1+b1)W2+b2

其中 W 1 , b 1 , W 2 , b 2 W_{1},b_{1},W_{2},b_{2} W1,b1,W2,b2 表示前馈子层的参数。另外,以往的训练发现,增大前馈子层隐状态的维度有利于提升最终翻译结果的质量,因此,前馈子层隐状态的维度一般比自注意力子层要大
//🙈

残差连接与层归一化

Transformer 结构组成的网络结构通常都是非常庞大而复杂,这就导致模型的训练比较困难。研究者们在 Transformer 块中进一步引入了残差连接与层归一化技术以进一步提升训练的稳定性。

具体来说,残差连接主要是指使用一条直连通道直接将对应子层的输入连接到输出上去,从而避免由于网络过深在优化过程中潜在的梯度消失问题
x l + 1 = f ( x l ) + x l x^{l+1}=f(x^l)+x^l xl+1=f(xl)+xl
其中 x l x^l xl 表示第 l l l 层的输入, f ( ⋅ ) f(\cdot) f() 表示一个映射函数

此外,为了进一步使得每一层的输入输出范围稳定在一个合理的范围内,层归一化技术被进一步引入每个 Transformer 块的当中:

L N ( x ) = α ⋅ x − μ σ + b LN(x)=\alpha \cdot \frac{x-\mu}{\sigma} + b LN(x)=ασxμ+b

其中 μ \mu μ σ \sigma σ 分别表示均值和方差,用于将数据平移缩放到均值为 0,方差为 1 的标准分布, a a a b b b 是可学习的参数。层归一化技术可以有效地缓解优化过程中潜在的不稳定、收敛速度慢等问题

编码器和解码器结构

not-very-accurate illustration

not-very-accurate illustration

相比于编码器端,解码器端要更复杂一些。具体来说,解码器的每个 Transformer 块的第一个自注意力子层额外增加了注意力掩码,对应图中的掩码多头注意力(Masked Multi-Head Attention)部分

在翻译的过程中,编码器端主要用于编码源语言序列的信息,而这个序列是完全已知的,因而编码器仅需要考虑如何融合上下文语义信息即可。而解码端则负责生成目标语言序列,这一生成过程是自回归的,即对于每一个单词的生成过程,仅有当前单词之前的目标语言序列是可以被观测的,因此这一额外增加的掩码是用来掩盖后续的文本信息,以防模型在训练阶段直接看到后续的文本序列进而无法得到有效地训练

此外,解码器端还额外增加了一个多头注意力(Multi-Head Attention)模块,使用交叉注意力(Cross-attention)方法,同时接收来自编码器端的输出以及当前 Transformer 块的前一个掩码注意力层的输出

//🙃

基于 task2 的 baseline 修改代码

主要修改模型结构部分的代码:

# 位置编码
class PositionalEncoding(nn.Module):def __init__(self, d_model, dropout=0.1, max_len=5000):super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(p=dropout)pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-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).transpose(0, 1)self.register_buffer('pe', pe)def forward(self, x):x = x + self.pe[:x.size(0), :]return self.dropout(x)# Transformer
class TransformerModel(nn.Module):def __init__(self, src_vocab, tgt_vocab, d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward, dropout):super(TransformerModel, self).__init__()self.transformer = nn.Transformer(d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward, dropout)self.src_embedding = nn.Embedding(len(src_vocab), d_model)self.tgt_embedding = nn.Embedding(len(tgt_vocab), d_model)self.positional_encoding = PositionalEncoding(d_model, dropout)self.fc_out = nn.Linear(d_model, len(tgt_vocab))self.src_vocab = src_vocabself.tgt_vocab = tgt_vocabself.d_model = d_modeldef forward(self, src, tgt):# 调整src和tgt的维度src = src.transpose(0, 1)  # (seq_len, batch_size)tgt = tgt.transpose(0, 1)  # (seq_len, batch_size)src_mask = self.transformer.generate_square_subsequent_mask(src.size(0)).to(src.device)tgt_mask = self.transformer.generate_square_subsequent_mask(tgt.size(0)).to(tgt.device)src_padding_mask = (src == self.src_vocab['<pad>']).transpose(0, 1)tgt_padding_mask = (tgt == self.tgt_vocab['<pad>']).transpose(0, 1)src_embedded = self.positional_encoding(self.src_embedding(src) * math.sqrt(self.d_model))tgt_embedded = self.positional_encoding(self.tgt_embedding(tgt) * math.sqrt(self.d_model))output = self.transformer(src_embedded, tgt_embedded,src_mask, tgt_mask, None, src_padding_mask, tgt_padding_mask, src_padding_mask)return self.fc_out(output).transpose(0, 1)

其他上分技巧

  • 最简单的就是调参,将 epochs 调大一点,使用全部训练集,以及调整模型的参数,如head、layers等。如果数据量允许,增加模型的深度(更多的编码器/解码器层)或宽度(更大的隐藏层尺寸),这通常可以提高模型的表达能力和翻译质量,尤其是在处理复杂或专业内容时。

  • 加入术语词典,这是在此竞赛中比较有效的方法,加入术语词典的方法策略也有很多,如:

    • 模型生成的翻译输出中替换术语,这是最简单的方法

    • 整合到数据预处理流程,确保它们在翻译中保持一致

    • 在模型内部动态地调整术语的嵌入,这涉及到在模型中加入一个额外的层,该层负责查找术语词典中的术语,并为其生成专门的嵌入向量,然后将这些向量与常规的词嵌入结合使用

  • 认真做数据清洗,我们在 Task2 已经提到过当前训练集存在脏数据的问题,会影响我们的模型训练

  • 数据扩增

    • 回译(back-translation):将源语言文本先翻译成目标语言,再将目标语言文本翻译回源语言,生成的新文本作为额外的训练数据

    • 同义词替换:随机选择句子中的词,并用其同义词替换

    • 使用句法分析和语义解析技术重新表述句子,保持原意不变

    • 将文本翻译成多种语言后再翻译回原语言,以获得多样化翻译

  • 采用更精细的学习率调度策略(baseline我们使用的是固定学习率):

    • Noam Scheduler:结合了warmup阶段和衰减阶段

    • Step Decay:最简单的一种学习率衰减策略,每隔一定数量的epoch,学习率按固定比例衰减

    • Cosine Annealing:学习率随周期性变化,通常从初始值下降到接近零,然后再逐渐上升

  • 自己训练一个小的预训练模型,尽量选择 1B 以下小模型,对 GPU 资源要求比较高,仅仅使用魔搭平台可能就满足不了

  • 将训练集上训练出来的模型拿到开发集(dev dataset)上 finetune 可以提高测试集(test dataset)的得分,因为开发集与测试集的分布比较相近

  • 在开发集和测试集上训一个语言模型,用这个语言模型给训练集中的句子打分,选出一些高分句子

  • 集成学习:训练多个不同初始化或架构的模型,并使用集成方法(如投票或平均)来产生最终翻译。这可以减少单一模型的过拟合风险,提高翻译的稳定性。

课后思考

相比于组队学习的课程,夏令营/竞赛不会手把手教你怎么做,需要自己动手实践
当然了,两者同样有读不懂的理论学习🥺

说实话,幸好能白嫖,让我在笔记本老伙计上训练模型我都不舍得😋

我有一个坏习惯,就是老是喜欢重复运行,试图发现偶然因素导致的错误。
实际上计算机很少掷骰子,如果结果不理想,要多在自己身上找原因,运行之前先排除基本错误

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

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

相关文章

[PM]产品运营

生命周期 运营阶段 主要工作 拉新 新用户的定义 冷启动 拉新方式 促活 用户活跃的原因 量化活跃度 运营社区化/内容化 留存 用户流失 培养用户习惯 用户挽回 变现 变现方式 付费模式 广告模式 数据变现 变现指标 传播 营销 认识营销 电商营销中心 拼团活动 1.需求整理 2.…

大数据之路 读书笔记 Day7 实时技术 简介及流式技术架构

回顾&#xff1a; Day6 离线数据开发之数据开发平台Day5 数据同步遇到的问题与解决方案 1. 简介 阿里巴巴在流式数据处理方面采用了多种技术和框架&#xff0c;这些技术的特点包括&#xff1a; 高可伸缩性&#xff1a; 阿里巴巴使用Apache Flink进行大规模数据处理&#xff0c…

Springboot项目远程部署gitee仓库(docker+Jenkins+maven+git)

创建仓库 创建一个Springboot项目&#xff0c;勾选web将该项目创建git本地仓库&#xff0c;再创建远程仓库推送上去 创建TestController RestControllerRequestMapping("/test")public class TestController {GetMapping("/hello")public String sayHell…

6.Kafka Acks详解

目录 概述Replication(分区副本)In-sync replicasAcknowledgementsacks0acks1acksallAck实用建议Minimum in-sync replicaCaveat(警告) 概述 本文对 kafka 的一些核心概念进行解释&#xff0c;也是 kafka 需要调优的一些地方。 官方原文速递 Replication(分区副本) 对于每个分…

222.买卖股票的最佳时机(力扣)

代码解决 class Solution { public:int maxProfit(vector<int>& prices) {// 初始化最小买入价为第一个价格int min1 prices[0];// 初始化最大利润为0int max1 0;// 从第二天开始遍历价格数组for (int i 1; i < prices.size(); i) {// 计算当前价卖出的利润&a…

windows edge自带的pdf分割工具(功能)

WPS分割pdf得会员&#xff0c;要充值&#xff01;网上一顿乱找&#xff0c;发现最简单&#xff0c;最好用&#xff0c;免费的还是回到Windows。 Windows上直接在edge浏览器打开PDF&#xff0c;点击 打印 按钮,页面下选择对应页数 打印机 选择 另存为PDF&#xff0c;然后保存就…

硬件开发——UART/I2C/SPI协议

硬件开发——UART/I2C/SPI协议 小狼http://blog.csdn.net/xiaolangyangyang 1、UART 电压&#xff1a; TTL电平&#xff1a;1&#xff1a;&#xff08;3.3V~5V&#xff09;&#xff0c;0&#xff1a;&#xff08;0V&#xff09;RS232电平&#xff1a;1&#xff1a;&#xff0…

【C++题解】1212. 移动数组元素

问题&#xff1a;1212. 移动数组元素 类型&#xff1a;数组找数 题目描述&#xff1a; 在一个不重复的数组中&#xff0c;请将这个数组的最小数和数组第一个数交换&#xff0c;最大数和数组最后一个数交换。 输入&#xff1a; 第一行有一个整数 n ( 5≤n≤100 &#xff09;…

浅谈端到端(自动驾驶)

一、 引言 端到端是近期非常火的话题&#xff0c;尤其在自动驾驶、具身智能等领域。去年UniAD的发布&#xff0c;给大家普及了端到端的网络设计&#xff0c;带动了行业的发展。产业界&#xff0c;特斯拉FSD Beta V12效果惊艳&#xff0c;近期理想也推出了双系统的E2E自动驾驶系…

MySQL 分组函数

目录 1. 单/多行处理 2. 分组函数分类 3. 分组函数组合使用 4. 注意 1. 单/多行处理 分组函数又被叫做多行处理函数&#xff08;多个输入&#xff0c;一个输出&#xff09;&#xff1b; 前面提到的数据处理函数又叫做单行处理函数&#xff08;一个输入&#xff0c;一个输出…

<Qt> 信号和槽

目录 一、信号和槽概述 二、信号和槽的使用​​​​​​ &#xff08;一&#xff09;connect函数 &#xff08;二&#xff09;实现一个点击按钮关闭窗口的功能 &#xff08;三&#xff09;再谈connect 三、自定义槽函数 四、自定义信号 五、带参数的信号和槽 六、信号…

哈喽GPT-4o,程序员如何通过GPT-4o保护自己的合法权益

目录 一、法律研究Prompt&#xff1a;派遣合同和劳务外包合同有什么区别&#xff1f;详细说一下在被裁员时的区别&#xff1f; 二、法律条文检索Prompt&#xff1a;检索《劳动合同法》&#xff0c;以下情况属于第几条&#xff0c;如果公司进行技能考试&#xff0c;并以技能考试…

在Ubuntu上安装redis

Ubuntu上安装redis 一、通过下载redis的压缩包安装二、通过apt包管理器安装Redis三、修改redis的配置文件四、控制redis启动 Redis是一种开源的内存数据存储&#xff0c;可以用作数据库、缓存和消息代理等。本文将会介绍两种不同的安装方式&#xff0c;包括通过压缩包安装以及通…

求职学习day5

安排明天hr面 投一下平安可能。 hr面准备&#xff0c;复习java核心技术&#xff0c;复习java项目。 正视自己&#xff0c;调整心态。 也是很早接触了javaguide但是没有持续学习&#xff0c;项目介绍 | JavaGuide&#xff0c;面试前复习一下感觉还是很有收获的。 还有一些…

studio编译报错java.lang.NullPointerException

安卓studio编译报错&#xff0c;这个是一个新建的项目就报错&#xff0c;原因是 implementation androidx.appcompat:appcompat:1.7.0版本太高&#xff0c;修改后版本 implementation androidx.appcompat:appcompat:1.4.0&#xff0c; 编译又报错 18 issues were found wh…

【MQTT(3)】开发一个客户端,QT-Android安卓手机版本

手机版本更加方便 生成安卓库 参考了这个代码 在编译Mosquitto以支持安卓平台时&#xff0c;主要涉及到使用Android NDK&#xff08;Native Development Kit&#xff09;进行交叉编译。环境的准备参考之前的博客【QT开发&#xff08;17&#xff09;】2023-QT 5.14.2实现Andr…

视频联网共享平台LntonCVS视频监控汇聚平台视频云解决方案

LntonCVS流媒体平台是一款遵循国家GB28181标准协议的先进视频监控与云服务平台。该平台设计独特&#xff0c;能够同时接入并处理多路设备的视频流&#xff0c;支持包括RTSP、RTMP、FLV、HLS、WebRTC在内的多种视频流格式的分发。其功能丰富多样&#xff0c;涵盖了视频直播监控、…

进程与线程(一)进程相关

目录 一. 概念二 . 组成进程控制块程序段数据段 三. 特征四. 进程的状态与转换五. 进程控制进程创建进程终止进程阻塞与进程唤醒进程切换 六. 进程通信共享存储消息传递管道通信 一. 概念 多道程序环境下&#xff0c;允许多个程序并发执行&#xff0c;此时它们将失去封闭性&…

Linux-交换空间(Swap)管理

引入概念 在计算机中&#xff0c;硬盘的容量一般比内存大&#xff0c;内存&#xff08;4GB 8GB 16GB 32GB 64GB…&#xff09;&#xff0c;硬盘&#xff08;512GB 1T 2T…&#xff09;。 冯诺依曼的现代计算机结构体系里面的存储器就是内存 内存是一种易失性存储器&#xff0c…

路由数据获取及封装方法

数据库设计 自联表 定义tree字段 public class LabelValue{public int label { get; set; }public string? value { get; set; }public List<LabelValue> children { get; set; }}获取路由方法 public Response<object> getMenuList() {Response<object>…