LSTM变种模型

news2024/12/23 18:20:52

一、GRU

1.概念

GRU(门控循环单元,Gated Recurrent Unit)是一种循环神经网络(RNN)的变体,旨在解决标准 RNN 在处理长期依赖关系时遇到的梯度消失问题。GRU 通过引入门控机制简化了 LSTM(长短期记忆网络)的设计,使得模型更轻便,同时保留了 LSTM 的优点。

2.原理

2.1.两个重大改进

1.将输入门、遗忘门、输出门三个门变为更新门(Updata Gate)和重置门(Reset Gate)两个门。

2.将 (候选) 单元状态 与 隐藏状态 (输出) 合并,即只有 当前时刻候选隐藏状态 \tilde{h_t}当前时刻隐藏状态 h_t

2.2模型结构

简化图:

内部结构:

GRU通过其门控机制能够有效地捕捉到序列数据中的时间动态,同时相较于LSTM来说,由于其结构更加简洁,通常参数更少,计算效率更高。

2.2.1 重置门

重置门决定在计算当前候选隐藏状态时,忽略多少过去的信息。

2.2.2 更新门

更新门决定了多少过去的信息将被保留。它使用前一时间步的隐藏状态 ( h_{t-1} ) 和当前输入 ( x_t ) 来计算得出。

2.2.3 候选隐藏状态

候选隐藏状态是当前时间步的建议更新,它包含了当前输入和过去的隐藏状态的信息。重置门的作用体现在它可以允许模型抛弃或保留之前的隐藏状态。

2.2.4 最终隐藏状态

最终隐藏状态是通过融合过去的隐藏状态和当前候选隐藏状态来计算得出的。更新门 ​控制了融合过去信息和当前信息的比例。

h_{t}忘记传递下来的 h_{t-1}中的某些信息,并加入当前节点输入的某些信息。这就是最终的记忆。

3. 代码实现

3.1 原生代码
import numpy as np
​
class GRU:
    def __init__(self, input_size, hidden_size):
        self.input_size = input_size
        self.hidden_size = hidden_size
        
        # 初始化w和b 更新门
        self.W_z = np.random.rand(hidden_size, input_size + hidden_size)
        self.b_z = np.zeros(hidden_size)
        #重置门
        self.W_r = np.random.rand(hidden_size, input_size + hidden_size)
        self.b_r = np.zeros(hidden_size)
        #候选隐藏状态
        self.W_h = np.random.rand(hidden_size, input_size + hidden_size)
        self.b_h = np.zeros(hidden_size)
        
    def tanh(self, x):
        return np.tanh(x)
    
    def sigmoid(self, x):
        return 1 / (1 + np.exp(-x))
    def forward(self, x):
        #初始化隐藏状态
        h_prev=np.zeros((self.hidden_size,))
        concat_input=np.concatenate([x, h_prev],axis=0)
​
        z_t=self.sigmoid(np.dot(self.W_z,concat_input)+self.b_z)
        r_t=self.sigmoid(np.dot(self.W_r,concat_input)+self.b_r)
​
        concat_reset_input=np.concatenate([x,r_t*h_prev],axis=0)
        h_hat_t=self.tanh(np.dot(self.W_h,concat_reset_input)+self.b_h)
​
        h_t=(1-z_t)*h_prev+z_t*h_hat_t
​
        return h_t
​
# 测试数据
input_size=3
hidden_size=2
seq_len=4
​
x=np.random.randn(seq_len,input_size)
​
gru=GRU(input_size,hidden_size)
​
all_h=[]
for t in range(seq_len):
    h_t=gru.forward(x[t,:])
    all_h.append(h_t)
    
print(h_t.shape)
print(np.array(all_h).shape)
        
        
        
3.2 PyTorch
nn.GRUCell
import torch
import torch.nn as nn
​
class GRUCell(nn.Module): 
    def __init__(self,input_size,hidden_size):
        super(GRUCell,self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        
        self.gru_cell=nn.GRUCell(input_size,hidden_size)
        
    def forward(self,x):
        h_t=self.gru_cell(x)
        return h_t
    
# 测试数据
input_size=3
hidden_size=2
seq_len=4
​
gru_model=GRUCell(input_size,hidden_size)
​
x=torch.randn(seq_len,input_size)
​
for t in range(seq_len):
    h_t=gru_model(x[t])
    
print(h_t)
    
​
​
nn.GRU
import torch
import torch.nn as nn
​
class GRU(nn.Module):
    def __init__(self,input_size,hidden_size):
        super(GRU,self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.gru=nn.GRU(input_size,hidden_size)
        
    def forward(self,x):
        out,_=self.gru(x)
        return out
    
# 测试数据
input_size=3
hidden_size=2
seq_len=4
batch_size=5
x=torch.randn(seq_len,batch_size,input_size)
gru_mosel=GRU(input_size,hidden_size)
​
out=gru_mosel(x)
print(out)
print(out.shape)
​

二、BiLSTM

1.概述

双向长短期记忆网络(BiLSTM)是长短期记忆网络(LSTM)的扩展,旨在同时考虑序列数据中的过去和未来信息。BiLSTM 通过引入两个独立的 LSTM 层,一个正向处理输入序列,另一个逆向处理,使得每个时间步的输出包含了该时间步前后的信息。这种双向结构能够更有效地捕捉序列中的上下文关系,从而提高模型对语义的理解能力。

  • 正向传递: 输入序列按照时间顺序被输入到第一个LSTM层。每个时间步的输出都会被计算并保留下来。

  • 反向传递: 输入序列按照时间的逆序(即先输入最后一个元素)被输入到第二个LSTM层。与正向传递类似,每个时间步的输出都会被计算并保留下来。

  • 合并输出: 在每个时间步,将两个LSTM层的输出通过某种方式合并(如拼接或加和)以得到最终的输出。

2. BILSTM模型应用背景

命名体识别

标注集

BMES标注集

分词的标注集并非只有一种,举例中文分词的情况,汉子作为词语开始Begin,结束End,中间Middle,单字Single,这四种情况就可以囊括所有的分词情况。于是就有了BMES标注集,这样的标注集在命名实体识别任务中也非常常见。

词性标注

在序列标注问题中单词序列就是x,词性序列就是y,当前词词性的判定需要综合考虑前后单词的词性。而标注集最著名的就是863标注集和北大标注集。

3. 代码实现

原生代码

import numpy as np
import torch
​
class BiLSTM():
    def __init__(self, input_size, hidden_size,output_size):
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
        
        #正向
        self.lstm_forward = LSTM(input_size, hidden_size,output_size)
        
        #反向
        self.lstm_backward = LSTM(input_size, hidden_size,output_size)
        
    def forward(self,x):
        # 正向LSTM
        output,_,_=self.lstm_forward.forward(x)
        # 反向LSTM,np.flip()是将数组进行翻转
        output_backward,_,_=self.lstm_backward.forward(np.flip(x,1))
        #合并两层的隐藏状态
        combine_output=[np.concatenate((x,y),axis=0) for x,y in zip(output,output_backward)]
        return combine_output
        
class LSTM:
    
    def __init__(self, input_size, hidden_size,output_size):
        """
        :param input_size: 词向量大小
        :param hidden_size: 隐藏层大小
        :param output_size: 输出类别
        """
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
​
        # 初始化权重和偏置 我们把结构图上的W U 拼接在了一起 所以参数是 input_size+hidden_size
        self.w_f = np.random.rand(hidden_size, input_size+hidden_size)
        self.b_f = np.random.rand(hidden_size)
​
        self.w_i = np.random.rand(hidden_size, input_size+hidden_size)
        self.b_i = np.random.rand(hidden_size)
​
        self.w_c = np.random.rand(hidden_size, input_size+hidden_size)
        self.b_c = np.random.rand(hidden_size)
​
        self.w_o = np.random.rand(hidden_size, input_size+hidden_size)
        self.b_o = np.random.rand(hidden_size)
​
        # 输出层
        self.w_y = np.random.rand(output_size, hidden_size)
        self.b_y = np.random.rand(output_size)
​
    def tanh(self,x):
        return np.tanh(x)
​
    def sigmoid(self,x):
        return 1/(1+np.exp(-x))
​
    def forward(self,x):
        h_t = np.zeros((self.hidden_size,)) # 初始隐藏状态
        c_t = np.zeros((self.hidden_size,)) # 初始细胞状态
​
        h_states = [] # 存储每个时间步的隐藏状态
        c_states = [] # 存储每个时间步的细胞状态
​
        for t in range(x.shape[0]):
            x_t = x[t] # 当前时间步的输入
            # concatenate 将x_t和h_t拼接 垂直方向
            x_t = np.concatenate([x_t,h_t])
​
            # 遗忘门
            f_t = self.sigmoid(np.dot(self.w_f,x_t)+self.b_f)
​
            # 输入门
            i_t = self.sigmoid(np.dot(self.w_i,x_t)+self.b_i)
            # 候选细胞状态
            c_hat_t = self.tanh(np.dot(self.w_c,x_t)+self.b_c)
​
            # 更新细胞状态
            c_t = f_t*c_t + i_t*c_hat_t
​
            # 输出门
            o_t = self.sigmoid(np.dot(self.w_o,x_t)+self.b_o)
            # 更新隐藏状态
            h_t = o_t*self.tanh(c_t)
​
            # 保存每个时间步的隐藏状态和细胞状态
            h_states.append(h_t)
            c_states.append(c_t)
​
        # 输出层 对最后一个时间步的隐藏状态进行预测,分类类别
        y_t = np.dot(self.w_y,h_t)+self.b_y
        # 转成张量形式 dim 0 表示行的维度
        output = torch.softmax(torch.tensor(y_t),dim=0)
​
        return np.array(h_states), np.array(c_states), output
    
​
# 测试数据
input_size=3
hidden_size=8
output_size=5
seq_len=4
​
x=np.random.randn(seq_len,input_size)
​
bilstm=BiLSTM(input_size,hidden_size,output_size)
outputs=bilstm.forward(x)        
print(outputs)
print(np.array(outputs).shape)
# ---------------------------------------------------------------------------
import numpy as np
​
# 创建一个包含两个二维数组的列表
inputs = [np.array([[0.1], [0.2], [0.3]]), np.array([[0.4], [0.5], [0.6]])]
​
# 使用 numpy 库中的 np.stack 函数。这会将输入的二维数组堆叠在一起,从而形成一个新的三维数组
inputs_3d = np.stack(inputs)
​
# 将三维数组转换为列表
list_from_3d_array = inputs_3d.tolist()
​
print(list_from_3d_array)

Pytorch

import torch
import torch.nn as nn
​
class BiLSTM(nn.Module):
    def __init__(self, input_size, hidden_size,output_size):
        super(BiLSTM, self).__init__()
        #定义双向LSTM
        self.lstm=nn.LSTM(input_size,hidden_size,bidirectional=True)
        #输出层 因为双向LSTM的输出是双向的,所以第一个参数是隐藏层*2
        self.linear=nn.Linear(hidden_size*2,output_size)
​
    def forward(self,x):
        out,_=self.lstm(x)
        linear_out=self.linear(out)
        return linear_out
    
# 测试数据
input_size=3
hidden_size=8
output_size=5
seq_len=4
batch_size=6
​
x=torch.randn(seq_len,batch_size,input_size)   
model=BiLSTM(input_size,hidden_size,output_size)
outputs=model(x)
print(outputs)
print(outputs.shape)

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

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

相关文章

Python爬虫使用实例-jsyks

目标地址: https://www.jsyks.com/kmy-mnks例如: urlhttps://www.jsyks.com/kmy-mnks # kmy-mnks 科目一-模拟考试 urlhttps://www.jsyks.com/kms-mnks # kms-mnks 科目四-模拟考试一、获取资源 先从本题分析里面得到解析答案【通过div.Exam ul li里面…

面向对象技术——设计模式

目录 层次结构 具体设计模式分类 创建型模式(处理创建对象) 结构型模式(处理类和对象的组合) 行为型模式(描述类或者对象的交互行为) 创建型设计模式 ​编辑 结构型设计模式 行为型设计模式​编辑 …

时序论文17|ICML24 SAMformer:华为新奇视角讨论Transformer时序预测时的收敛优化问题

论文标题:SAMformer: Unlocking the Potential of Transformers in Time Series Forecasting with Sharpness-Aware Minimization and Channel-Wise Attention 论文链接:https://arxiv.org/abs/2402.10198 代码链接:https://github.com/rom…

从零开始:在 VMware ESXi 环境中安装 Rocky Linux 的秘诀

哈喽大家好,欢迎来到虚拟化时代君(XNHCYL)。 “ 大家好,我是虚拟化时代君,一位潜心于互联网的技术宅男。这里每天为你分享各种你感兴趣的技术、教程、软件、资源、福利…(每天更新不间断,福利…

appium中的uiautomatorviewer显示的界面为横屏解决方法

uiautomatorviewer显示的界面为横屏解决方法 解决方法: 修改模拟器的分辨率,比如540:900就可解决了

MySQL基础教程(一):连接数据库和使用表

这个专栏用来讲解 MySQL 数据的基本语法和用法。本教程的目的是方便查询 MySQL 的用法,因此对于原理的讲解会偏少一些,但特点就是会有很多实验操作图。 本专栏使用的源材料是《MySQL必知必会》这本书的源代码。 文章目录 1. 连接 MySQL 数据库2. 创建数…

搭建个人博客--1、前端页面

采用bootstrap前端框架&#xff1a; Anchor - a free Bootstrap UI Kit综合使用bootstrap框架做一个Aotm Blog个人博客_基于bootstrap的博客-CSDN博客 做出模板base.html {% load static %} <!DOCTYPE html> <html langen> <head><meta charset"UT…

Facebook账单户和海外户该如何选择?

近期&#xff0c;有不少小伙伴来咨询广告投放账户的问题&#xff0c;很多人把账单户作为广告投放的选择&#xff0c;那么账单户和海外户哪个更适合你呢&#xff1f;本文将详细探讨这两种账户类型的差异&#xff0c;以及在不同情境下应如何选择&#xff0c;感兴趣的朋友就继续看…

遨游双卫星智能终端,赋能石油行业安全生产和信息化建设

石油&#xff0c;被誉为“工业的血液”&#xff0c;其影响力深远&#xff0c;石油勘探与开发活动往往在人迹罕至的偏远区域展开&#xff0c;如广袤的戈壁滩、浩瀚的海洋&#xff0c;这些区域普遍缺乏健全的公共电信网络基础设施。以往&#xff0c;油田野外作业团队主要依赖短波…

避雷!Google Adsense联盟营销七大投放误区

你是否在使用Google AdSense进行广告投放&#xff1f;你是否想进一步优化你的投放策略&#xff1f;那么这篇文章你不可错过啦&#xff01; Google AdSense为跨境商家提供了一个平台&#xff0c;我们可以通过展示相关广告来赚取收入。然而&#xff0c;即使是最有经验的商家也可…

API项目:模拟接口开发和调用

创建模拟接口 controller 层&#xff1a; 控制层&#xff0c;负责处理用户请求&#xff0c;并根据请求调用相应的业务逻辑&#xff0c;然后返回对应的视图或数据。 model 层&#xff1a; 数据模型层&#xff0c;负责数据的处理和业务逻辑&#xff1b;在 model 层中&#xf…

无人机在矿业领域的应用!

矿区测绘与建模 无人机可以快速、全面地获取矿区的地形地貌数据&#xff0c;生成高精度的二维或三维模型。 这些模型可用于矿区的规划、设计、监测和管理&#xff0c;提高矿山的生产效率。 库存量量化监测 无人机能够捕捉厘米级的地形数据&#xff0c;通过计算得出准确的库…

ADC -模数转换

ADC -模数转换 - 将模拟信号转换为数字信号 目录 ADC -模数转换 - 将模拟信号转换为数字信号 STM32方面使用的AD转化方式是逐次逼近法 ADC 什么叫单次&#xff0c;连续&#xff0c;扫描&#xff0c;中断&#xff1f; 应用&#xff1a;运用STM32中ADC转…

Vue入门-小黑课堂Demo

功能需求&#xff1a; ①列表渲染 ②删除功能 ③添加功能 ④底部统计和清空 页面效果&#xff1a; 代码展示&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" c…

年会工作会议会务报名签到小程序开源版开发

年会工作会议会务报名签到小程序开源版开发 会议管理微信小程序&#xff0c;对会议流程、开支、数量、标准、供应商提供一种标准化的管理方法。以达到量化成本节约&#xff0c;风险缓解和服务质量提升的目的。适用于大型论坛、峰会、学术会议、政府大会、合作伙伴大会、经销商…

大多数人不知道的:线程池CallerRunsPolicy()拒绝策略

总所周知&#xff0c;java里面线程池的四个拒绝策略 AbortPolicy 丢弃并抛出RejectedExecutionException异常 DiscardPolicy 直接丢弃 DiscardOldestPolicy 直接丢弃最前面的任务&#xff0c;尝试执行新任务 CallerRunsPolicy 由调用线程池的线程处理任务&a…

linux安装minianconda

文章目录 &#x1f315;我的配置&#x1f315;从清华镜像源里下载minianaconda&#x1f315;安装&#x1f315;自定义安装位置&#x1f315;是否关闭打开终端默认进入anaconda的设置&#xff1f;&#x1f315;配置清华镜像源 &#x1f315;我的配置 ubuntu 22.04LTS &#x1…

全都燃起来了!黄金周车市销量成绩出炉

文/王俣祺 导语&#xff1a;国庆黄金周对于其他行业可能是个放松的好时机&#xff0c;但对于国内汽车市场而言可能是下半年最关键的“战场”。这几天&#xff0c;全国各地的车展和4S店简直热闹非凡&#xff0c;新能源车尤其抢镜&#xff0c;优惠活动不断&#xff0c;引得消费者…

DAMA数据管理知识体系(第9章 文件和内容管理)

课本内容 9.1 引言 概要 文件和内容管理是指针对存储在关系型数据库之外的数据和信息的采集、存储、访问和使用过程的管理[1]。它的重点在于保持文件和其他非结构化或半结构化信息的完整性&#xff0c;并使这些信息能够被访问。业务驱动因素 法规遵从性要求 法律法规要求组织保…

基于uniapp+django微信小程序 食品安全信息管理系统

目录 项目介绍具体实现截图开发者工具介绍技术路线性能/安全/负载方面开发语言以及框架介绍python-flask核心代码部分展示python-django核心代码部分展示详细视频演示源码获取 项目介绍 食品安全信息管理系统设计的目的是为用户提供食品信息、科普专栏、食品检测、检测结果、交…