news 2026/4/14 8:22:36

循环神经网络与文本处理:深度循环神经网络的实现与应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
循环神经网络与文本处理:深度循环神经网络的实现与应用

深度循环神经网络

学习目标

通过学习本课程,学员将了解深度循环神经网络的函数依赖关系,简洁实现,训练与预测。

相关知识点

  • 深度循环神经网络

学习内容

讨论一个具有单向隐藏层的循环神经网络。其中,隐变量和观测值与具体的函数形式的交互方式是相当随意的。只要交互类型建模具有足够的灵活性,这就不是一个大问题。然而,对一个单层来说,这可能具有相当的挑战性。而在循环神经网络中,我们首先需要确定如何添加更多的层,以及在哪里添加额外的非线性。

事实上,我们可以将多层循环神经网络堆叠在一起,通过对几个简单层的组合,产生了一个灵活的机制。特别是,数据可能与不同层的堆叠有关。

下图描述了一个具有LLL个隐藏层的深度循环神经网络,每个隐状态都连续地传递到当前层的下一个时间步和下一层的当前时间步。

图1 深度循环神经网络结构

1 深度循环神经网络

1.1 函数依赖关系

我们可以将深度架构中的函数依赖关系形式化,这个架构是由 图1 中描述了LLL个隐藏层构成。

假设在时间步ttt有一个小批量的输入数据Xt∈Rn×d\mathbf{X}_t \in \mathbb{R}^{n \times d}XtRn×d
(样本数:nnn,每个样本中的输入数:ddd)。同时,将lthl^\mathrm{th}lth隐藏层(l=1,…,Ll=1,\ldots,Ll=1,,L)的隐状态设为Ht(l)∈Rn×h\mathbf{H}_t^{(l)} \in \mathbb{R}^{n \times h}Ht(l)Rn×h
(隐藏单元数:hhh),输出层变量设为Ot∈Rn×q\mathbf{O}_t \in \mathbb{R}^{n \times q}OtRn×q
(输出数:qqq)。设置Ht(0)=Xt\mathbf{H}_t^{(0)} = \mathbf{X}_tHt(0)=Xt,第lll个隐藏层的隐状态使用激活函数ϕl\phi_lϕl,则为公式(1):

Ht(l)=ϕl(Ht(l−1)Wxh(l)+Ht−1(l)Whh(l)+bh(l)),(1)\mathbf{H}_t^{(l)} = \phi_l(\mathbf{H}_t^{(l-1)} \mathbf{W}_{xh}^{(l)} + \mathbf{H}_{t-1}^{(l)} \mathbf{W}_{hh}^{(l)} + \mathbf{b}_h^{(l)})\tag{1},Ht(l)=ϕl(Ht(l1)Wxh(l)+Ht1(l)Whh(l)+bh(l)),(1)
eq_deep_rnn_H

其中,权重Wxh(l)∈Rh×h\mathbf{W}_{xh}^{(l)} \in \mathbb{R}^{h \times h}Wxh(l)Rh×hWhh(l)∈Rh×h\mathbf{W}_{hh}^{(l)} \in \mathbb{R}^{h \times h}Whh(l)Rh×h和偏置bh(l)∈R1×h\mathbf{b}_h^{(l)} \in \mathbb{R}^{1 \times h}bh(l)R1×h
都是第lll个隐藏层的模型参数。
最后,输出层的计算仅基于第lll个隐藏层最终的隐状态,如公式(2)所示:

Ot=Ht(L)Whq+bq,(2)\mathbf{O}_t = \mathbf{H}_t^{(L)} \mathbf{W}_{hq} + \mathbf{b}_q\tag{2},Ot=Ht(L)Whq+bq,(2)

其中,权重Whq∈Rh×q\mathbf{W}_{hq} \in \mathbb{R}^{h \times q}WhqRh×q和偏置bq∈R1×q\mathbf{b}_q \in \mathbb{R}^{1 \times q}bqR1×q都是输出层的模型参数。

与多层感知机一样,隐藏层数目LLL和隐藏单元数目hhh都是超参数。它们可以进行调整。另外,用门控循环单元或长短期记忆网络的隐状态来代替eq_deep_rnn_H中的隐状态进行计算,可以很容易地得到深度门控循环神经网络或深度长短期记忆神经网络。

1.2 深度循环神经网络的简洁实现

实现多层循环神经网络所需的许多逻辑细节在高级API中都是现成的。简单起见,我们仅示范使用此类内置函数的实现方式。以长短期记忆网络模型为例,我们指定了层的数量,而不是使用单一层这个默认值。我们从加载时间机器数据集开始。

1.2.1 安装环境依赖与加载数据集
%pip install d2l==0.17.6--no-deps%pip install matplotlib-inline
%matplotlib inlineimportmathimporttorchimportrandomimportrefromtorchimportnnfromtorch.nnimportfunctionalasFfromd2limporttorchasd2limportcollections
#获取数据集!wget https://model-community-picture.obs.cn-north-4.myhuaweicloud.com/ascend-zone/notebook_datasets/0f19d2300e0711f09b46fa163edcddae/timemachine.txt

本课程采用本地加载数据集的方式加载数据集,需要定义以下函数:

defread_time_machine_local(file_path):"""从本地文件加载时间机器数据集"""withopen(file_path,'r',encoding='utf-8')asf:lines=f.readlines()return[re.sub('[^A-Za-z]+',' ',line).strip().lower()forlineinlines]deftokenize(lines,token='word'):"""分词器:将文本行拆分为单词或字符标记"""iftoken=='word':return[line.split()forlineinlines]eliftoken=='char':return[list(line)forlineinlines]else:print('ERROR: unknown token type: '+token)

定义Vocab类:

classVocab:def__init__(self,tokens=None,min_freq=0,reserved_tokens=None):iftokensisNone:tokens=[]ifreserved_tokensisNone:reserved_tokens=[]counter=count_corpus(tokens)self._token_freqs=sorted(counter.items(),key=lambdax:x[1],reverse=True)self.idx_to_token=['<unk>']+reserved_tokens self.token_to_idx={token:idxforidx,tokeninenumerate(self.idx_to_token)}fortoken,freqinself._token_freqs:iffreq<min_freq:breakiftokennotinself.token_to_idx:self.idx_to_token.append(token)self.token_to_idx[token]=len(self.idx_to_token)-1def__len__(self):returnlen(self.idx_to_token)def__getitem__(self,tokens):ifnotisinstance(tokens,(list,tuple)):returnself.token_to_idx.get(tokens,self.unk)return[self.__getitem__(token)fortokenintokens]defto_tokens(self,indices):ifnotisinstance(indices,(list,tuple)):returnself.idx_to_token[indices]return[self.idx_to_token[index]forindexinindices]@propertydefunk(self):return0@propertydeftoken_freqs(self):returnself._token_freqs

定义计算token频率、本地文件加载语料库和词汇表、随机采样生成小批量数据等用于本地数据加载的函数:

defcount_corpus(tokens):"""计算token频率"""iflen(tokens)==0orisinstance(tokens[0],list):tokens=[tokenforlineintokensfortokeninline]returncollections.Counter(tokens)defload_corpus_time_machine_local(file_path,max_tokens=-1):"""从本地文件加载语料库和词汇表"""lines=read_time_machine_local(file_path)tokens=tokenize(lines,'char')vocab=Vocab(tokens)corpus=[vocab[token]forlineintokensfortokeninline]ifmax_tokens>0:corpus=corpus[:max_tokens]returncorpus,vocabdefseq_data_iter_random(corpus,batch_size,num_steps):"""随机采样生成小批量数据"""corpus=corpus[random.randint(0,num_steps-1):]num_subseqs=(len(corpus)-1)//num_steps initial_indices=list(range(0,num_subseqs*num_steps,num_steps))random.shuffle(initial_indices)defdata(pos):returncorpus[pos:pos+num_steps]num_batches=num_subseqs//batch_sizeforiinrange(0,batch_size*num_batches,batch_size):initial_indices_per_batch=initial_indices[i:i+batch_size]X=[data(j)forjininitial_indices_per_batch]Y=[data(j+1)forjininitial_indices_per_batch]yieldtorch.tensor(X),torch.tensor(Y)defseq_data_iter_sequential(corpus,batch_size,num_steps):"""顺序分区生成小批量数据"""offset=random.randint(0,num_steps)num_tokens=((len(corpus)-offset-1)//batch_size)*batch_size Xs=torch.tensor(corpus[offset:offset+num_tokens])Ys=torch.tensor(corpus[offset+1:offset+1+num_tokens])Xs,Ys=Xs.reshape(batch_size,-1),Ys.reshape(batch_size,-1)num_batches=Xs.shape[1]//num_stepsforiinrange(0,num_steps*num_batches,num_steps):X=Xs[:,i:i+num_steps]Y=Ys[:,i:i+num_steps]yieldX,YclassSeqDataLoader:"""序列数据加载器"""def__init__(self,file_path,batch_size,num_steps,use_random_iter,max_tokens):self.data_iter_fn=seq_data_iter_randomifuse_random_iterelseseq_data_iter_sequential self.corpus,self.vocab=load_corpus_time_machine_local(file_path,max_tokens)self.batch_size,self.num_steps=batch_size,num_stepsdef__iter__(self):returnself.data_iter_fn(self.corpus,self.batch_size,self.num_steps)defload_data_time_machine_local(file_path,batch_size,num_steps,use_random_iter=False,max_tokens=10000):"""从本地加载时间机器数据集的主函数"""data_iter=SeqDataLoader(file_path,batch_size,num_steps,use_random_iter,max_tokens)returndata_iter,data_iter.vocab
# 从本地加载数据集file_path="./timemachine.txt"batch_size,num_steps=32,35train_iter,vocab=load_data_time_machine_local(file_path,batch_size,num_steps)

我们有不同的词元,所以输入和输出都选择相同数量,即vocab_size。隐藏单元的数量仍然是256256256。唯一的区别是,我们现在通过num_layers的值来设定隐藏层数

importtorch_npu vocab_size,num_hiddens,num_layers=len(vocab),256,2num_inputs=vocab_size device=torch.device('npu:0')lstm_layer=nn.LSTM(num_inputs,num_hiddens,num_layers)model=d2l.RNNModel(lstm_layer,len(vocab))model=model.to(device)
1.2.2 深度循环神经的训练预测

由于使用了长短期记忆网络模型来实例化两个层,因此训练速度被大大降低了。

num_epochs,lr=100,2d2l.train_ch8(model,train_iter,vocab,lr*1.0,num_epochs,device)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/30 20:32:35

循环神经网络与文本处理:编码器-解码器架构及其应用

编码器-解码器架构 学习目标 通过本课程&#xff0c;学员将了解到编码器-解码器架构的基本原理、组成组件以及其在机器翻译等序列转换问题中的应用。 相关知识点 编码器-解码器架构 学习内容 1 编码器-解码器架构 1.1 编码器 机器翻译是序列转换模型的一个核心问题&#xff0c;…

作者头像 李华
网站建设 2026/4/13 23:41:25

测试容器韧性:Kubernetes杀Pod的专业测试指南

在云原生架构中&#xff0c;容器韧性&#xff08;Container Resilience&#xff09;是确保应用高可用的核心指标&#xff0c;它衡量系统在故障&#xff08;如Pod意外终止&#xff09;下的恢复能力。Kubernetes&#xff08;K8s&#xff09;作为主流容器编排平台&#xff0c;其“…

作者头像 李华
网站建设 2026/4/12 15:59:46

长尾关键词如何助力SEO策略优化与网站流量提升

长尾关键词是SEO策略中不可或缺的组成部分&#xff0c;因其能够为网站带来更精准的流量。通常&#xff0c;这些关键词由多个词组成&#xff0c;比传统关键词更具针对性&#xff0c;帮助满足用户特定的搜索需求。在实施长尾关键词策略时&#xff0c;网站需要关注内容的相关性&am…

作者头像 李华
网站建设 2026/4/13 2:41:41

城市管廊设备运维管理平台解决方案

当城市地下综合管廊如血脉般纵横延伸&#xff0c;如何保障这条“生命线”的安全稳定运行&#xff0c;成为现代城市治理的关键命题。面对成千上万的电力、通信、给排水、燃气等设备&#xff0c;传统人工巡检与管理模式已难以为继。当前城市管廊设备运维面临三大挑战&#xff1a;…

作者头像 李华
网站建设 2026/4/11 2:11:40

CES消费电子热浪衔接Formnext制造浪潮:深圳3D打印展的全民创造进行时

在拉斯维加斯CES 2026的璀璨灯光下,一项深刻的变革正在发生:消费级3D打印机正褪去极客专属的神秘面纱,凭借革命性的易用体验,步入全球千万家庭与创业工坊。而这场始于消费电子展台的创新浪潮,其真正的产业化动能与生态全景,将在亚洲的核心舞台——Formnext Asia Shenzhen深圳国…

作者头像 李华
网站建设 2026/4/13 15:19:16

西门子PLC博图与优傲UR机器人的Profinet通讯实战

西门子plc博图与优傲UR机器人进行Profinet通讯&#xff0c;s7-1200/1500 与UR机器人通讯&#xff0c;实际应用案例使用中&#xff0c;可提供GSD配置文件&#xff0c;设置说明书&#xff0c;和博图plc程序&#xff0c;目前版本为v15或以上&#xff0c;程序只提供配置好的内容配置…

作者头像 李华