基于Pytorch的LSTM网络全流程实验(自带数据集,可直接运行出结果,替换自己的数据集即可使用)

文章目录

    • LSTM代码
    • 双向LSTM,需要修改哪几个参数?

LSTM代码

import numpy as np
import matplotlib.pyplot as plt

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import DataLoader, TensorDataset

from sklearn.model_selection import train_test_split


# 生成数据集
def generate_data(num_samples, seq_length):
    # 生成正弦波形数据(类别0)
    half_num_samples=num_samples//2 # 整除
    x_sin = np.array([np.sin(0.06 * np.arange(seq_length) + np.random.rand()) for _ in range(half_num_samples)])
    y_sin = np.zeros(half_num_samples, dtype=np.int64)
    
    # 生成余弦波形数据(类别1),频率略有不同
    x_cos = np.array([np.cos(0.05 * np.arange(seq_length) + np.random.rand()) for _ in range(half_num_samples)])
    y_cos = np.ones(half_num_samples, dtype=np.int64)
    
    # 合并数据
    x = np.concatenate((x_sin, x_cos), axis=0)
    y = np.concatenate((y_sin, y_cos), axis=0)
    
    # 打乱数据
    indices = np.arange(num_samples)
    np.random.shuffle(indices)
    x = x[indices]
    y = y[indices]
    
    # 转换为pytorch张量,LSTM需要3D tensor [batch, seq_len, features],
    # 所以用unsqueeze(2)在第二个维度上增加一个维度
    x_tensor = torch.tensor(x, dtype=torch.float32).unsqueeze(2)  
    print('x_tensor.shape:',x_tensor.shape) # x_tensor.shape: torch.Size([1000, 100, 1])
    y_tensor = torch.tensor(y, dtype=torch.int64) # y_tensor.shape: torch.Size([1000])
    print('y_tensor.shape:',y_tensor.shape)
    
    return x_tensor, y_tensor

# LSTM分类模型
class LSTMClassifier(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim, n_layers):
        super(LSTMClassifier, self).__init__()
        self.hidden_dim = hidden_dim
        self.n_layers = n_layers
        
        # LSTM Layer
        self.lstm = nn.LSTM(input_dim, hidden_dim, n_layers, batch_first=True)
        
        # 全连接层(Fully connected layer)
        self.fc = nn.Linear(hidden_dim, output_dim)
    
    # forward方法在模型训练时会自动调用
    def forward(self, x):
        # 用零初始化隐藏层的状态
        h0 = torch.zeros(self.n_layers, x.size(0), self.hidden_dim).requires_grad_()
        
        # 用零初始化细胞状态
        c0 = torch.zeros(self.n_layers, x.size(0), self.hidden_dim).requires_grad_()
        
        out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach()))
        
        out = self.fc(out[:, -1, :])
        return out

# 训练模型
def train_model(model, train_loader, criterion, optimizer, num_epochs):
    for epoch in range(num_epochs):
        for i, (sequences, labels) in enumerate(train_loader):
            # Forward pass
            outputs = model(sequences)
            loss = criterion(outputs, labels)
            
            # Backward and optimize
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            
            if (i+1) % 100 == 0:
                print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}], Loss: {loss.item():.4f}')

# 评估模型
def evaluate_model(model, test_loader):
    model.eval()  # Set model to evaluation mode
    with torch.no_grad():
        correct = 0
        total = 0
        for sequences, labels in test_loader:
            outputs = model(sequences)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
            
        print(f'Accuracy of the model on the test sequences: {100 * correct / total} %')




if __name__=='__main__':
    # ----------------- 生成样本数据 ----------------- 
    num_samples = 1000  # 训练总样本数
    seq_length = 100    # 每个样本的序列长度(可以看作是特征的长度)
    x_data,y_data = generate_data(num_samples, seq_length) # 产生总的样本
    x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=2) 
    # ----------------- 数据加载器 ----------------- 
    batch_size=64
    train_loader = DataLoader(TensorDataset(x_train, y_train), batch_size=batch_size, shuffle=True)
    test_loader = DataLoader(TensorDataset(x_test, y_test), batch_size=batch_size, shuffle=False)

    # ----------------- 可视化数据 ----------------- 
    plt.figure(figsize=(12, 6))
    for i in range(6):
        plt.subplot(2, 3, i+1)
        plt.plot(x_train[i].numpy().flatten(), label=f"Class {y_train[i].item()}")
        plt.legend()
    plt.tight_layout()
    plt.show() # 不想看数据,可以注释掉这行

    # ----------------- 超参设定 ----------------- 
    input_dim = 10    # 输入特征的维数
    hidden_dim = 50   # LSTM 隐藏层的维度
    output_dim = 2    # 输出的维度(分类的类别数)
    n_layers = 1      # 堆叠的 LSTM 层的数量(默认为1层)

    # ----------------- 创建模型 ----------------- 
    model = LSTMClassifier(input_dim=1, hidden_dim=50, output_dim=2, n_layers=1)
    criterion = nn.CrossEntropyLoss() # 损失函数
    optimizer = optim.Adam(model.parameters(), lr=0.01) # 优化器

    # ----------------- 训练模型 ----------------- 
    train_model(model, train_loader, criterion, optimizer, num_epochs=10)

    # ----------------- 评估模型 ----------------- 
    evaluate_model(model, test_loader)
    

双向LSTM,需要修改哪几个参数?

需要在 nn.LSTM 的构造函数中设置 bidirectional=True。此外,由于双向 LSTM 在每个时间步将会有两个隐藏状态(正向和反向),因此全连接层的输入特征数需要调整为 2 * hidden_size

下面是对您的代码的修改部分,以及需要注意的几个点:

  1. nn.LSTM 中设置 bidirectional=True来启用双向功能。
  2. h0c0 的尺寸都乘以了 2,因为对于每一层 LSTM,我们现在有两个隐藏层状态(一个用于前向传播,一个用于后向传播)。
  3. 调整全连接层的输入特征数,由 hidden_size 改为 2 * hidden_size,以适应双向输出。

修改后的代码如下:

import torch
import torch.nn as nn

# 定义LSTM网络
class LSTM_Model(nn.Module):
    """
    input_size:输入特征的维数
    hidden_size:LSTM 隐藏层的维度
    num_layers:堆叠的 LSTM 层的数量
    class_num: 分类的类别数
    batch_first: 输入和输出的维度顺序是否为 (batch, seq, feature)
    """
    def __init__(self, input_size, hidden_size, num_layers, class_num):
        super(LSTM_Model, self).__init__()
        self.hidden_size = hidden_size 
        self.num_layers = num_layers
        # 修改为双向LSTM
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, bidirectional=True)
        # 修改全连接层输入特征数为 2 * hidden_size
        self.fc = nn.Linear(in_features=2 * hidden_size, out_features=class_num)

    def forward(self, x):
        DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        # 初始化隐藏层状态全为0
        h0 = torch.zeros(self.num_layers * 2, x.size(0), self.hidden_size).requires_grad_().to(DEVICE)  # 注意乘以2,因为是双向
        c0 = torch.zeros(self.num_layers * 2, x.size(0), self.hidden_size).requires_grad_().to(DEVICE)  # 注意乘以2,因为是双向
        x = x.view(x.size(0), 1, -1)
        out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach()))
        # 只需要最后一层隐层的状态,考虑双向,所以取最后一步的输出
        out = self.fc(out[:, -1, :])  # 这里不用改变
        return out

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#设计树形程序界面的方法:创建特殊窗体

目录 1.TreeView控件 2.实例 (1)Resources.Designer.cs (2)Form1.Designer.cs (3)Form1.cs (4)生成效果 以树形来显示程序的菜单,可以更直观、更快捷地对窗体进行…

PostgreSQL大版本如何升级?

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…

算法训练营day25

零、回溯算法理论 参考链接13.1 回溯算法 - Hello 算法 (hello-algo.com) 1.尝试与回退 之所以称之为回溯算法,是因为该算法在搜索解空间时会采用“尝试”与“回退”的策略。当算法在搜索过程中遇到某个状态无法继续前进或无法得到满足条件的解时,它会…

vue使用海康控件开发包——浏览器直接查看海康监控画面

1、下载控件开发包 2、安装插件(双击/demo/codebase/HCWebSDKPlugin.exe进行安装) 3、打开/demo/index.html文件 4、在页面上输入你的海康监控的登录信息进行预览 如果有监控画面则可以进行下面的操作 注意:以下操作都在Vue项目进行 5、复…

【Unity】shader中参数传递

1、前言 unity shader这个对于我来说是真的有点难,今天这篇文章主要还是总结下最近学习到的一些东西,避免过段时间忘记了,可能有不对,欢迎留言纠正。 2、参数传递的两种方式 2.1 语义传递 语义传递这个相对来说是简单的 shad…

ENVI不同版本个人使用对比

ENVI不同版本个人使用对比 文章目录 ENVI不同版本个人使用对比前言对比5.3学习版5.6学习版6.0试用版 总结 前言 目前来看,流传较广的可供大家免费获取的ENVI版本主要是5.3学习版 5.6学习版 6.0学习版这三个版本,不同的版本有不同特色,在此做…

21.7K Star力荐!跨平台的开源免费可视化爬虫,让数据采集不再是难题!

朋友们!你是否曾梦想着轻松地从网上抓取数据,却苦于编程技能的门槛?现在,有了EasySpider,这一切都变得触手可及!这不仅仅是一个工具,它是一个革命性的网络爬虫神器,让你能够像专业人士一样,无需编写一行代码,就能轻松设计和执行爬虫任务。无论是动态内容还是复杂页面…

【介绍下分布式系统】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

Spring Boot框架强大的事件驱动模型(ApplicationEvent)

文章目录 前言应用场景异步处理事务边界外的操作跨微服务通信系统监控与日志聚合UI更新生命周期管理工作流或业务流程缓存同步 小试牛刀定义事件实现事件处理器注册事件处理器发布事件测试事件 写在最后 前言 在Spring Boot应用中,事件处理器是指那些处理特定类型事…

实时采集麦克风并播放(springboot+webscoekt+webrtc)

项目技术 springbootwebscoektwebrtc 项目介绍 项目通过前端webrtc采集麦克风声音,通过websocket发送后台,然后处理成g711-alaw字节数据发生给广播UDP并播放。 后台处理项目使用线程池(5个线程)接受webrtc数据并处理g711-alaw字节数组放到Map容器中&…

将针孔模型相机 应用到3DGS

Motivation 3DGS 的 投影采用的是 CG系的投影矩阵 P P P, 默认相机的 principal point (相机光心) 位于图像的中点处。但是 实际应用的 绝大多数的 相机 并不满足这样一个设定, 因此我们 需要根据 f , c x , c y {f,c_x, c_y} f,cx​,cy​ 这几个参数重新构建3D …

Linux 安装 nvm,并使用 Jenkins 打包前端

文章目录 nvm是什么nvm下载nvm安装设置 nvm 环境变量设置 Jenkins 打包命令 nvm是什么 nvm全英文也叫node.js version management,是一个nodejs的版本管理工具。nvm和n都是node.js版本管理工具,为了解决node.js各种版本存在不兼容现象可以通过它可以安装…

电脑提示msvcp100.dll丢失的解决方法,多种有效的解决方法分享

在日常使用电脑进行工作的时候,我们常常依赖于各种高效软件来辅助完成任务,提升工作效率。然而,当你满怀期待地双击启动某个至关重要的办公软件时,屏幕上却弹出了一个令人措手不及的错误提示:“msvcp100.dll文件丢失”…

二. 搭建Nginx 直播流程服务器

目录 1. 前言 2. 安装 Nginx 依赖 3.下载源码 4. 编译安装 5.配置 rtmp 服务 6.验证配置 1. 前言 服务器由 NGINXRTMP 构成。 NGINX 是 HTTP 服务器, RTMP 是附加模块。 其中 NGINX 我选择的是用 源码编译方式 进行安装,因为这种方式可以自定义…

基于python语言气象水文数据处理及精美科研绘图实践技术

Python是功能强大、免费、开源,实现面向对象的编程语言,Python能够运行在Linux、Windows、Macintosh、AIX操作系统上及不同平台(x86和arm),Python简洁的语法和对动态输入的支持,再加上解释性语言的本质&…

C语言中的三大循环

C语言中为我们提供了三种循环语句,今天我就来与诸君细谈其中之奥妙。循环这一板块总结的内容较多,而且,很重要!(敲黑板!!!),所以诸君一定要对此上心,耐住性子…

修复所有 bug 并不能解决所有问题

原文:jeffpsherman - 2024.04.08 在软件领域,如同在制造业,有些问题是由于 bug 或“特殊原因”引发的,而有些则是“常见原因”,这是由于系统设计和实现的性质所导致的。修复 bug 就是移除特殊原因,消除 bu…

go语言实现简单认证样例

目录 1、代码实现样例 2、postman调用 1、代码实现样例 package mainimport ("net/http""strings""github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin" )var (// 密钥,用于验证 JWT 令牌signingKey []byte("…

上班太闲了,一坐就是一天,有没有什么副业可以干的?

一、别做兼职,做副业 兼职,仅仅是用时间换取报酬,短暂且有限,实质上仍是雇佣劳动。副业则不同,它依托你的独特价值换取长久回报,犹如你的第二事业。 或许你还不太清楚兼职的局限性,以下是一些…

上位机开发PyQt5(一)【创建窗口、窗口标题、气泡、显示图片和图标、显示文字】

目录 一、 第一个Qt窗口 二、PyQt模块简介 三、窗口标题和气泡 setWindowTitle resize setToolTip 四、标签QLabel显示图片和图标 setPixmap setWindowIcon resize(label.pixmap().size()) 五、标签QLabel显示文字 setText QFont setPointSize setFont set…