简介
文章首先介绍了Attention机制如何解决RNN处理长序列的瓶颈问题,详细解释了其实现原理、不同类型(Soft/Hard,Global/Local)及代码实现。同时提供了AI大模型的完整学习路径,从系统设计到微调开发七个阶段,以及思维导图、视频教程等丰富资源,帮助程序员快速掌握大模型技术与应用。
一、Attention的介绍
在普通的RNN结构中,Encoder需要把一个句子转化为一个向量,然后在Decoder中使用,这就要求Encoder把源句子中所有的信息都包含进去,但是当句子长度过长的时候,这个要求就很难达到,或者说会产生瓶颈(比如,输入一篇文章等场长内容),当然我们可以使用更深的RNN和大多的单元来解决这个问题,但是这样的代价也很大。那么有没有什么方法能够优化现有的RNN结构呢?
为此,Bahdanau等人在2015年提出了Attenion机制,Attention翻译成为中文叫做注意力,把这种模型称为Attention based model。就像我们自己看到一副画,我们能够很快的说出画的主要内容,而忽略画中的背景,因为我们注意的,更关注的往往是其中的主要内容。
通过这种方式,在我们的RNN中,我们有通过LSTM或者是GRU得到的所有信息,那么这些信息中只去关注重点,而不需要在Decoder的每个time step使用全部的encoder的信息,这样就可以解决第一段所说的问题了
二、Attention的实现机制
假设我们现在有一个文本翻译的需求,即机器学习翻译为machine learning。那么这个过程通过前面所学习的Seq2Seq就可以实现
上图的左边是Encoder,能够得到hidden_state在右边使用
Deocder中蓝色方框中的内容,是为了提高模型的训练速度而使用teacher forcing手段,否则的话会把前一次的输出作为下一次的输入(但是在Attention模型中不再是这样了)
那么整个过程中如果使用Attention应该怎么做呢?
在之前我们把encoder的最后一个输出,作为decoder的初始的隐藏状态,现在我们不再这样做
1、Attention的实现过程
初始化一个Decoder的隐藏z_0z\_0z_0
这个z_oz\_oz_o会和encoder第一个time step的output进行match操作(或者是socre操作),得到α_01\alpha\_0^1α_01 ,这里的match可以使很多中操作,比如:
- z和h的余弦值
- 是一个神经网络,输入为z和h
- 或者α=hTWz\alpha = h^T W zα=hTWz等
- encoder中的每个output都和z_0z\_0z_0进行计算之后,得到的结果进行softmax,让他们的和为1(可以理解为权重)
之后把所有的softmax之后的结果和原来encoder的输出h_ih\_ih_i进行相加求和得到c0c^0c0 即:c0=∑α^i0hi
- 得到c0c0c0之后,把它作为decoder的input,同和传入初始化的z0z0z0,得到第一个time step的输出和hidden_state(Z1Z^1Z1)
- 把Z_1Z\_1Z_1再和所有的encoder的output进行match操作,得到的结果进行softmax之后作为权重和encoder的每个timestep的结果相乘求和得到c1c^1c1
- 再把c1c1c1作为decoder的input,和Z1Z1Z1作为输入得到下一个输出,如此循环,只到最终decoder的output为终止符
- 整个过程写成数学公式如下:
- 先计算attention权重
- 在计算上下文向量,图中的cic^ici
- 最后计算结果,往往会把当前的output([batch_size,1,hidden_size])和上下文向量进行拼接然后使用
2、不同Attention的介绍
在上述过程中,使用decoder的状态和encoder的状态的计算后的结果作为权重,乘上encoder每个时间步的输出,这需要我们去训练一个合适的match函数,得到的结果就能够在不同的时间步上使用不同的encoder的相关信息,从而达到只关注某一个局部的效果,也就是注意力的效果
Soft-Attention 和 Hard-Attention
最开始Bahdanau等人提出的Attention机制通常被称为soft-attention,所谓的soft-attention指的是encoder中输入的每个词语都会计算得到一个注意力的概率。
在进行图像捕捉的时候,提出了一种hard-attenion的方法,希望直接从input中找到一个和输出的某个词对应的那一个词。但是由于NLP中词语和词语之间往往存在联系,不会只关注某一个词语,所以都会使用soft-attention,所以这里的就不多介绍hard-attention
Global-Attention 和Local AttentionBahdanau等人提出的Bahdanau Attention被称为local attention,后来Luong等人提出的Luong Attention是一种全局的attenion。所谓全局的attenion指的是:使用的全部的encoder端的输入的attenion的权重
local-attenion就是使用了部分的encoder端的输入的权重(当前时间步上的encoder的hidden state),这样可以减少计算量,特别是当句子的长度比较长的时候。
三、Attention的代码实现
通过attention的代码,需要实现计算的是attention weight
通过前面的学习,我们知道attention_weight = f(hidden,encoder_outputs),主要就是实现Luong attention中的三种操作
class Attention(nn.Module): def __init__(self,method,batch_size,hidden_size): super(Attention,self).__init__() self.method = method self.hidden_size = hidden_size assert self.method in ["dot","general","concat"],"method 只能是 dot,general,concat,当前是{}".format(self.method) if self.method == "dot": pass elif self.method == "general": self.Wa = nn.Linear(hidden_size,hidden_size,bias=False) elif self.method == "concat": self.Wa = nn.Linear(hidden_size*2,hidden_size,bias=False) self.Va = nn.Parameter(torch.FloatTensor(batch_size,hidden_size)) def forward(self, hidden,encoder_outputs): """ :param hidden:[1,batch_size,hidden_size] :param encoder_outputs: [batch_size,seq_len,hidden_size] :return: """ batch_size,seq_len,hidden_size = encoder_outputs.size() hidden = hidden.squeeze(0) #[batch_size,hidden_size] if self.method == "dot": return self.dot_score(hidden,encoder_outputs) elif self.method == "general": return self.general_score(hidden,encoder_outputs) elif self.method == "concat": return self.concat_score(hidden,encoder_outputs) def _score(self,batch_size,seq_len,hidden,encoder_outputs): # 速度太慢 # [batch_size,seql_len] attn_energies = torch.zeros(batch_size,seq_len).to(config.device) for b in range(batch_size): for i in range(seq_len): #encoder_output : [batch_size,seq_len,hidden_size] #deocder_hidden :[batch_size,hidden_size] #torch.Size([256, 128]) torch.Size([128]) torch.Size([256, 24, 128]) torch.Size([128]) # print("attn size:",hidden.size(),hidden[b,:].size(),encoder_output.size(),encoder_output[b,i].size()) attn_energies[b,i] = hidden[b,:].dot(encoder_outputs[b,i]) #dot score return F.softmax(attn_energies).unsqueeze(1) # [batch_size,1,seq_len] def dot_score(self,hidden,encoder_outputs): """ dot attention :param hidden:[batch_size,hidden_size] --->[batch_size,hidden_size,1] :param encoder_outputs: [batch_size,seq_len,hidden_size] :return: """ #hiiden :[hidden_size] -->[hidden_size,1] ,encoder_output:[seq_len,hidden_size] hidden = hidden.unsqueeze(-1) attn_energies = torch.bmm(encoder_outputs, hidden) attn_energies = attn_energies.squeeze(-1) #[batch_size,seq_len,1] ==>[batch_size,seq_len] return F.softmax(attn_energies).unsqueeze(1) # [batch_size,1,seq_len] def general_score(self,hidden,encoder_outputs): """ general attenion :param batch_size:int :param hidden: [batch_size,hidden_size] :param encoder_outputs: [batch_size,seq_len,hidden_size] :return: """ x = self.Wa(hidden) #[batch_size,hidden_size] x = x.unsqueeze(-1) #[batch_size,hidden_size,1] attn_energies = torch.bmm(encoder_outputs,x).squeeze(-1) #[batch_size,seq_len,1] return F.softmax(attn_energies,dim=-1).unsqueeze(1) # [batch_size,1,seq_len] def concat_score(self,hidden,encoder_outputs): """ concat attention :param batch_size:int :param hidden: [batch_size,hidden_size] :param encoder_outputs: [batch_size,seq_len,hidden_size] :return: """ #需要先进行repeat操作,变成和encoder_outputs相同的形状,让每个batch有seq_len个hidden_size x = hidden.repeat(1,encoder_outputs.size(1),1) ##[batch_size,seq_len,hidden_size] x = torch.tanh(self.Wa(torch.cat([x,encoder_outputs],dim=-1))) #[batch_size,seq_len,hidden_size*2] --> [batch_size,seq_len,hidden_size] #va [batch_size,hidden_size] ---> [batch_size,hidden_size,1] attn_energis = torch.bmm(x,self.Va.unsqueeze(2)) #[batch_size,seq_len,1] attn_energis = attn_energis.squeeze(-1) # print("concat attention:",attn_energis.size(),encoder_outputs.size()) return F.softmax(attn_energis,dim=-1).unsqueeze(1) #[batch_size,1,seq_len]完成了attention weight的计算之后,需要再对代码中forward_step的内容进行修改
def forward_step(self,decoder_input,decoder_hidden,encoder_outputs): """ :param decoder_input:[batch_size,1] :param decoder_hidden: [1,batch_size,hidden_size] :param encoder_outputs: encoder中所有的输出,[batch_size,seq_len,hidden_size] :return: out:[batch_size,vocab_size],decoder_hidden:[1,batch_size,didden_size] """ embeded = self.embedding(decoder_input) #embeded: [batch_size,1 , embedding_dim] #TODO 可以把embeded的结果和前一次的context(初始值为全0tensor) concate之后作为结果 #rnn_input = torch.cat((embeded, last_context.unsqueeze(0)), 2) # gru_out:[256,1, 128] decoder_hidden: [1, batch_size, hidden_size] gru_out,decoder_hidden = self.gru(embeded,decoder_hidden) gru_out = gru_out.squeeze(1) #TODO 注意:如果是单层,这里使用decoder_hidden没问题(output和hidden相同) # 如果是多层,可以使用GRU的output作为attention的输入 #开始使用attention attn_weights = self.attn(decoder_hidden,encoder_outputs) # attn_weights [batch_size,1,seq_len] * [batch_size,seq_len,hidden_size] context = attn_weights.bmm(encoder_outputs) #[batch_size,1,hidden_size] gru_out = gru_out.squeeze(0) # [batch_size,hidden_size] context = context.squeeze(1) # [batch_size,hidden_size] #把output和attention的结果合并到一起 concat_input = torch.cat((gru_out, context), 1) #[batch_size,hidden_size*2] concat_output = torch.tanh(self.concat(concat_input)) #[batch_size,hidden_size] output = F.log_softmax(self.fc(concat_output),dim=-1) #[batch_Size, vocab_size] # out = out.squeeze(1) return output,decoder_hidden,attn_weights最后
我在一线科技企业深耕十二载,见证过太多因技术卡位而跃迁的案例。那些率先拥抱 AI 的同事,早已在效率与薪资上形成代际优势,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在大模型的学习中的很多困惑。
我整理出这套 AI 大模型突围资料包:
- ✅AI大模型学习路线图
- ✅Agent行业报告
- ✅100集大模型视频教程
- ✅大模型书籍PDF
- ✅DeepSeek教程
- ✅AI产品经理入门资料
完整的大模型学习和面试资料已经上传带到CSDN的官方了,有需要的朋友可以扫描下方二维码免费领取【保证100%免费】👇👇
为什么说现在普通人就业/升职加薪的首选是AI大模型?
人工智能技术的爆发式增长,正以不可逆转之势重塑就业市场版图。从DeepSeek等国产大模型引发的科技圈热议,到全国两会关于AI产业发展的政策聚焦,再到招聘会上排起的长队,AI的热度已从技术领域渗透到就业市场的每一个角落。
智联招聘的最新数据给出了最直观的印证:2025年2月,AI领域求职人数同比增幅突破200%,远超其他行业平均水平;整个人工智能行业的求职增速达到33.4%,位居各行业榜首,其中人工智能工程师岗位的求职热度更是飙升69.6%。
AI产业的快速扩张,也让人才供需矛盾愈发突出。麦肯锡报告明确预测,到2030年中国AI专业人才需求将达600万人,人才缺口可能高达400万人,这一缺口不仅存在于核心技术领域,更蔓延至产业应用的各个环节。
资料包有什么?
①从入门到精通的全套视频教程⑤⑥
包含提示词工程、RAG、Agent等技术点
② AI大模型学习路线图(还有视频解说)
全过程AI大模型学习路线
③学习电子书籍和技术文档
市面上的大模型书籍确实太多了,这些是我精选出来的
④各大厂大模型面试题目详解
⑤ 这些资料真的有用吗?
这份资料由我和鲁为民博士共同整理,鲁为民博士先后获得了北京清华大学学士和美国加州理工学院博士学位,在包括IEEE Transactions等学术期刊和诸多国际会议上发表了超过50篇学术论文、取得了多项美国和中国发明专利,同时还斩获了吴文俊人工智能科学技术奖。目前我正在和鲁博士共同进行人工智能的研究。
所有的视频教程由智泊AI老师录制,且资料与智泊AI共享,相互补充。这份学习大礼包应该算是现在最全面的大模型学习资料了。
资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。
智泊AI始终秉持着“让每个人平等享受到优质教育资源”的育人理念,通过动态追踪大模型开发、数据标注伦理等前沿技术趋势,构建起"前沿课程+智能实训+精准就业"的高效培养体系。
课堂上不光教理论,还带着学员做了十多个真实项目。学员要亲自上手搞数据清洗、模型调优这些硬核操作,把课本知识变成真本事!
如果说你是以下人群中的其中一类,都可以来智泊AI学习人工智能,找到高薪工作,一次小小的“投资”换来的是终身受益!
应届毕业生:无工作经验但想要系统学习AI大模型技术,期待通过实战项目掌握核心技术。
零基础转型:非技术背景但关注AI应用场景,计划通过低代码工具实现“AI+行业”跨界。
业务赋能 突破瓶颈:传统开发者(Java/前端等)学习Transformer架构与LangChain框架,向AI全栈工程师转型。
👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓**