transformer——多变量预测PyTorch搭建Transformer实现多变量多步长时间序列预测(负荷预测)——transformer多变量预测

写在最前:

在系统地学习了Transformer结构后,尝试使用Transformer模型对DNA序列数据实现二分类,好久前就完成了这个实验,一直拖着没有整理,今天系统的记录一下,顺便记录一下自己踩过的坑

(需要数据的可以私聊我)

1、数据说明

两个csv文件,共有三列,第一列是id,第二列每个数据都是一长串dna序列,第三列是它们的label,分别是0和1。

数据的data列有点长,此处截了一部分供大家参考:

2、python库准备

此处Transformer我使用了pytorch的,所以需要事先安装pytorch库,这里是一大踩坑点

因为我的电脑配置也是win10+MX350显卡+CUDA10.2,最后安装在conda环境下安装pytorch:

第一次没有指定pytorch版本结果自动装了最新版,然后在python环境下输入print(torch.cuda.is_available()),结果是false。

第二次:将之前的卸载重新安装,此处指定了版本好像是1.10,结果最后还是false。

第三次:百思不得其解,就找了大量的原因,最后用了下面的命令:pip3 install torch1.10.1+cu102 torchvision0.11.2+cu102 torchaudio===0.10.1+cu102 -f https:// download.pytorch.org/whl/cu102/torch_stable.html

然后打印输出:True!!!

3、实验难点

个人感觉实验中最重要的两部分就是dna序列数据的处理和Transformer模型构建。

3.1 DNA数据处理

数据中第二列data列是dna数据,很长一串,需要进行转换。

(1)我刚开始使用了独热编码,代码如下:

def one_hot_encode_sequence(sequence):
    mapping = {'A': [1, 0, 0, 0], 'C': [0, 1, 0, 0], 'G': [0, 0, 1, 0], 'T': [0, 0, 0, 1]}
    encoding = [mapping[base] for base in sequence]
    return np.array(encoding)

# 对DNA序列进行单热编码
# 每个seq是一个序列,序列中的每个base变成[1,0,0,0],再组合成二维
X = np.array([one_hot_encode_sequence(seq) for seq in data3['data']])
y = data3['label'].values

很好理解,就是将ACGT分别映射成[1,0,0,0] [0,1,0,0] [0,0,1,0] [0,0,0,1],但是这样就多了一个维度,打印一下x的shape看看:

直接变三维数据了,然后后面在Transformer阶段,数据维度转换就出了问题:

我想计算loss,刚开始写了loss = criterion(outputs, labels.view(-1, 1)),但是outputs是torch.Size([1, 1001, 1],labels是torch.Size([32]),这两个数据不知道怎么才能转换成同一shape的数据,当时搞了好久也没成功,所以放弃这个编码方案。。。。

(如果有大佬有方法将这两个的size改成一致,欢迎评论区留言!!)

(2)使用嵌入编码

直接上代码:

# 将DNA序列数据转换为整数编码
def integer_encode(seq):
    seq = seq.upper()
    encoding = {'A': 0, 'T': 1, 'C': 2, 'G': 3}
    return np.array([encoding[x] for x in seq])

X = np.array([integer_encode(seq) for seq in X])
y = np.array(y)

很好理解,再看一下X的维度:

很明显比上面的三维数据要好哈哈哈

好用!爱用!!下次还用!!

3.2 Transformer结构

(1)首先需要嵌入位置信息

直接上代码吧,我喜欢做注释,这个注释也很详细,大家自己看就明白了,其实就对应了Transformer论文中PE的公式:

# 定义PositionalEncoding
class PositionalEncoding(nn.Module):
    def __init__(self, d_model, dropout, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)
        
        # pe的维度(位置编码最大长度,模型维度)
        pe = torch.zeros(max_len, d_model)
        # 维度为(max_len, 1):先在[0,max_len]中取max_len个整数,再加一个维度
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        # 位置编码的除数项:10000^(2i/d_model)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-np.log(10000.0) / d_model))
        # sin负责奇数;cos负责偶数
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        
        #维度变换:(max_len,d_model)→(1,max_len,d_model)→(max_len,1,d_model)
        pe = pe.unsqueeze(0).transpose(0, 1)
        # 将pe注册为模型缓冲区
        self.register_buffer('pe', pe)
        
        
    def forward(self, x):
        # 取pe的前x.size(0)行,即
        # (x.size(0),1,d_model) → (x.size(0),d_model),拼接到x上
        x = x + self.pe[:x.size(0), :]
        return self.dropout(x)

(2)然后就是Transformer结构

# 定义Transformer模型
class TransformerModel(nn.Module):
    def __init__(self, input_dim, output_dim, d_model, nhead, num_layers, dim_feedforward, dropout):
        super(TransformerModel, self).__init__()
        # 创建一个线性变换层,维度input_dim4→d_model
        self.embedding = nn.Embedding(input_dim, d_model)  # 使用嵌入层
        # 生成pe
        self.pos_encoder = PositionalEncoding(d_model, dropout)
        # 生成一层encoder
        encoder_layers = nn.TransformerEncoderLayer(d_model=d_model, nhead=nhead, dim_feedforward=dim_feedforward, dropout=dropout)
        # 多层encoder
        self.transformer_encoder = nn.TransformerEncoder(encoder_layers, num_layers=num_layers)
        # 维度d_model→output_dim
        self.fc = nn.Linear(d_model, output_dim)
        self.d_model = d_model

    def forward(self, src):
        src = src.permute(1, 0)
        
        # 缩放
        src = self.embedding(src) * np.sqrt(self.d_model)
        
        # 加上位置嵌入
        src = self.pos_encoder(src)
    
        output = self.transformer_encoder(src)
        
        # 调整输出形状为(batch, seq_len, d_model)
        output = output.permute(1, 0, 2)
        # 对所有位置的表示取平均
        output = torch.mean(output, dim=1)
        # 线性变换
        output = self.fc(output)
        # 使用sigmoid激活函数
        output = torch.sigmoid(output)
        
        return output

4、其余

解决了上面的难点,后面的导包、数据导入预处理划分、数据加载、训练数据、测试数据就不细说了,后面有完整代码大家自己看吧

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split

# data1和data2是包含DNA序列数据的列表,每个数据集有三列分别是id data label,标签分别为0和1
data1 = pd.read_csv(r"D:\桌面\研0\Transformer\0.csv")
data2 = pd.read_csv(r"D:\桌面\研0\Transformer\1.csv")

# 合并
data = pd.concat([data1,data2], ignore_index=True)

X = data['data'].values
y = data['label'].values
print("X.shape:",end='')
print(X.shape)
print("y.shape:",end='')
print(y.shape)



# 将DNA序列数据转换为整数编码
def integer_encode(seq):
    seq = seq.upper()
    encoding = {'A': 0, 'T': 1, 'C': 2, 'G': 3}
    return np.array([encoding[x] for x in seq])

X = np.array([integer_encode(seq) for seq in X])
y = np.array(y)
print("====转换成整数编码后====")
print("X.shape:",end='')
print(X.shape)
print("y.shape:",end='')
print(y.shape)


# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)


# 创建PyTorch数据集和数据加载器
class DNADataset(torch.utils.data.Dataset):
    def __init__(self, X, y):
        self.X = torch.tensor(X, dtype=torch.long)  # 将输入数据转换为长整型
        self.y = torch.tensor(y, dtype=torch.float32)

    def __len__(self):
        return len(self.X)

    def __getitem__(self, idx):
        return self.X[idx], self.y[idx]

train_dataset = DNADataset(X_train, y_train)
test_dataset = DNADataset(X_test, y_test)

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False)



# 定义PositionalEncoding
class PositionalEncoding(nn.Module):
    def __init__(self, d_model, dropout, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)
        
        # pe的维度(位置编码最大长度,模型维度)
        pe = torch.zeros(max_len, d_model)
        # 维度为(max_len, 1):先在[0,max_len]中取max_len个整数,再加一个维度
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        # 位置编码的除数项:10000^(2i/d_model)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-np.log(10000.0) / d_model))
        # sin负责奇数;cos负责偶数
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        
        #维度变换:(max_len,d_model)→(1,max_len,d_model)→(max_len,1,d_model)
        pe = pe.unsqueeze(0).transpose(0, 1)
        # 将pe注册为模型缓冲区
        self.register_buffer('pe', pe)
        
        
    def forward(self, x):
        # 取pe的前x.size(0)行,即
        # (x.size(0),1,d_model) → (x.size(0),d_model),拼接到x上
        x = x + self.pe[:x.size(0), :]
        return self.dropout(x)





# 定义Transformer模型
class TransformerModel(nn.Module):
    def __init__(self, input_dim, output_dim, d_model, nhead, num_layers, dim_feedforward, dropout):
        super(TransformerModel, self).__init__()
        # 创建一个线性变换层,维度input_dim4→d_model
        self.embedding = nn.Embedding(input_dim, d_model)  # 使用嵌入层
        # 生成pe
        self.pos_encoder = PositionalEncoding(d_model, dropout)
        # 生成一层encoder
        encoder_layers = nn.TransformerEncoderLayer(d_model=d_model, nhead=nhead, dim_feedforward=dim_feedforward, dropout=dropout)
        # 多层encoder
        self.transformer_encoder = nn.TransformerEncoder(encoder_layers, num_layers=num_layers)
        # 维度d_model→output_dim
        self.fc = nn.Linear(d_model, output_dim)
        self.d_model = d_model

    def forward(self, src):
        src = src.permute(1, 0)
        
        # 缩放
        src = self.embedding(src) * np.sqrt(self.d_model)
        
        # 加上位置嵌入
        src = self.pos_encoder(src)
    
        output = self.transformer_encoder(src)
        
        # 调整输出形状为(batch, seq_len, d_model)
        output = output.permute(1, 0, 2)
        # 对所有位置的表示取平均
        output = torch.mean(output, dim=1)
        # 线性变换
        output = self.fc(output)
        # 使用sigmoid激活函数
        output = torch.sigmoid(output)
        
        return output




# 初始化模型
model = TransformerModel(input_dim=4, 
                         output_dim=1, 
                         d_model=128, 
                         nhead=4, 
                         num_layers=3, 
                         dim_feedforward=256, 
                         dropout=0.1)
# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练模型
def train(model, iterator, optimizer, criterion):
    # iterator是train_loader= DataLoader(train_dataset, batch_size=32)
    model.train()
    
    for batch in iterator:
        # 初始化,防止梯度爆炸
        optimizer.zero_grad()
        
        X, y = batch
        predictions = model(X)
        
        # 计算修正损失函数
        loss = criterion(predictions.squeeze(), y)
        # 计算当前批数据的损失函数对模型参数的梯度
        loss.backward()
        # 根据梯度更新模型参数
        optimizer.step()

        
        
# 测试模型
def evaluate(model, iterator, criterion):
    print("===========test==========")
    model.eval()
    epoch_loss = 0
    
    with torch.no_grad():# 此处不需要梯度计算
        for batch in iterator:
            X, y = batch
            predictions = model(X)
            loss = criterion(predictions.squeeze(), y)
            epoch_loss += loss.item()
    # 累加loss,再求平均
    return epoch_loss / len(iterator)


# 开始训练
N_EPOCHS = 10

for epoch in range(N_EPOCHS):
    print("第%d轮===================================="%(epoch+1))
    train(model, train_loader, optimizer, criterion)
    test_loss = evaluate(model, test_loader, criterion)
    print(f'Epoch: {epoch+1:02}, Test Loss: {test_loss:.3f}')

我设置的epoch是10轮,每轮都会进行训练和测试,其中batch_size是32,每轮都会打印测试的平均loss,具体如下:

Epoch: 01, Test Loss: 0.641
Epoch: 02, Test Loss: 0.640
Epoch: 03, Test Loss: 0.669
Epoch: 04, Test Loss: 0.639
Epoch: 05, Test Loss: 0.638
Epoch: 06, Test Loss: 0.640
Epoch: 07, Test Loss: 0.638
Epoch: 08, Test Loss: 0.641
Epoch: 09, Test Loss: 0.639
Epoch: 10, Test Loss: 0.638

5、写在最后

第一次自行用Transformer模型实现二分类,过程很曲折,不过最后还好成功实现了。

各位大佬们如果有更好的模型实现思路,欢迎在评论区指教!

如何学习大模型

现在社会上大模型越来越普及了,已经有很多人都想往这里面扎,但是却找不到适合的方法去学习。

作为一名资深码农,初入大模型时也吃了很多亏,踩了无数坑。现在我想把我的经验和知识分享给你们,帮助你们学习AI大模型,能够解决你们学习中的困难。

我已将重要的AI大模型资料包括市面上AI大模型各大白皮书、AGI大模型系统学习路线、AI大模型视频教程、实战学习,等录播视频免费分享出来,需要的小伙伴可以扫取。

一、AGI大模型系统学习路线

很多人学习大模型的时候没有方向,东学一点西学一点,像只无头苍蝇乱撞,我下面分享的这个学习路线希望能够帮助到你们学习AI大模型。

在这里插入图片描述

二、AI大模型视频教程

在这里插入图片描述

三、AI大模型各大学习书籍

在这里插入图片描述

四、AI大模型各大场景实战案例

在这里插入图片描述

五、结束语

学习AI大模型是当前科技发展的趋势,它不仅能够为我们提供更多的机会和挑战,还能够让我们更好地理解和应用人工智能技术。通过学习AI大模型,我们可以深入了解深度学习、神经网络等核心概念,并将其应用于自然语言处理、计算机视觉、语音识别等领域。同时,掌握AI大模型还能够为我们的职业发展增添竞争力,成为未来技术领域的领导者。

再者,学习AI大模型也能为我们自己创造更多的价值,提供更多的岗位以及副业创收,让自己的生活更上一层楼。

因此,学习AI大模型是一项有前景且值得投入的时间和精力的重要选择。

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

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

相关文章

OpenHarmony开发实战:GPIO控制器接口

功能简介 GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。 GPIO接口定义了操作GP…

Echarts 问题集锦

最近公司集中做统计图表,新手小白,真被Echarts折腾地不轻,怕自己年老记忆衰退,特地做一些记录。以备后面查阅。 1、X轴的 数据显示不全,间或不显示 很奇葩,我发现数据里有一个值为0.0,当这条记…

液压件工厂的MES解决方案:智能生产,高效未来

一、引言 虽然我国液压件行业发展迅速,但是大多数液压件生产企业规模小、自主创新能力不足,大部分液压产品处于价值链中低端。且由于技术、工艺、设备及管理等多方面的限制,高端液压件产品研发生产水平不足,无法形成有效的供给&a…

【linux】虚拟机安装 BCLinux-R8-U4-Server-x86_64

目录 一、概述 1.1移动云Linux系统订阅服务 CLS 1.2 大云天元操作系统BC-Linux 二、安装 一、概述 1.1移动云Linux系统订阅服务 CLS 移动云Linux系统订阅服务 CLS (Cloud Linux Service)为使用BC-Linux操作系统的用户提供标准维保服务以及高级技术支…

生物墨水的重要特性

生物打印技术正以前所未有的速度发展,为组织工程和再生医学领域带来了革命性的变革。然而,成功打印出功能性的三维结构,并将其应用于人体,离不开生物墨水这一关键材料。主要特性包括: 物理性质 表面张力: 表面张力影…

基于java+springboot+vue实现的社团管理系统(文末源码+Lw)270

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱,出错率高,信息安全性差&#…

Linux4(Docker)

目录 一、Docker介绍 二、Docker结构 三、Docker安装 四、Docker 镜像 五、Docker 容器 六、Docker 安装nginx 七、Docker 中的MySQL部署 一、Docker介绍 Docker:是给予Go语言实现的开源项目。 Docker的主要目标是“Build,Ship and Run Any App,Anywhere” 也…

LangChain入门学习笔记(七)—— 使用检索提高生成内容质量

大模型训练使用的数据是开放的、广泛的,因此它显得更加的通用。然而在有些应用场景下,用户需要使用自己的数据使得大模型生成的内容更加贴切,也有时候用户的数据是敏感的,无法提供出来给大模型进行通用性的训练。RAG技术就是一种解…

HarmonyOS APP应用开发项目- MCA助手(Day02持续更新中~)

简言: gitee地址:https://gitee.com/whltaoin_admin/money-controller-app.git端云一体化开发在线文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5注:…

Java Lambda语法介绍

目录 一、概述 二、Lambda语法的历史 2.1 Lambda名字的含义 2.2 Lambda的历史 三、Lambda语法的核心接口 3.1 Lambda的四大核心接口 3.1.1 概述 3.1.2 Consumer 接口 3.1.3 Supplier 接口 3.1.4 Function 接口,> 3.1.5 Predicate 接口 四、Lambda的引用 4.1 概…

启航IT世界:高考后假期的科技探索之旅

随着高考的落幕,新世界的大门已经为你们敞开。这个假期,不仅是放松身心的时光,更是为即将到来的IT学习之旅打下坚实基础的黄金时期。以下是一份专为你们准备的IT专业入门预习指南,希望能助你们一臂之力。 一:筑基篇&a…

(18)GPS/指南针(一)

文章目录 前言 1 GPS/指南针 2 RTK GPS 3 GPS驱动程序选项 4 GPS自动切换 5 高级用途 前言 Copter/Plane/Rover 支持与 GPS、指南针和其他定位技术的整合: 1 GPS/指南针 Avionics Anonymous GNSS CompassAvionics Anonymous CompassBeitain BN-220 GPS / B…

昇思MindSpore学习入门-模型训练

模型训练 模型训练一般分为四个步骤: 构建数据集。定义神经网络模型。定义超参、损失函数及优化器。输入数据集进行训练与评估。 现在我们有了数据集和模型后,可以进行模型的训练与评估。 构建数据集 首先从数据集 Dataset加载代码,构建…

RT-Thread Studio与CubeMX联合编程之rtthread stm32h743的使用(十一)spi设备SFUD驱动的使用

我们要在rtthread studio 开发环境中建立stm32h743xih6芯片的工程。我们使用一块stm32h743及fpga的核心板完成相关实验,核心板如图: 1.建立新工程,选择相应的芯片型号及debug引脚及调试器 2.编译下载,可以看到串口打印正常 3.…

超实用的80个网络基础知识!(非常详细)零基础入门到精通,收藏这一篇就够了

点击上方 网络技术干货圈,选择 设为星标 优质文章,及时送达 转载请注明以下内容: 来源:公众号【网络技术干货圈】 作者:圈圈 ID:wljsghq 基础网络概念 1. 网络基础概述 什么是计算机网络 计算机网络是一…

全自动封箱机:如何助力企业实现智能化升级

在飞速发展的工业自动化时代,全自动封箱机以其高效、精准、稳定的特点,成为了生产线上的不可或缺的一员。它不仅大大地提高了生产效率,降低了人工成本,更在产品质量控制、安全性等方面发挥了重要作用。星派将深入探讨全自动封箱机…

基于SpringBoot民宿管理系统设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,…

华为云物联网的使用

这里我们设置三个属性 1.温度DHT11_T 上传 2.湿度DHT11_H 上传 3.风扇motor 远程控制(云平台控制设备端) 发布主题: $oc/devices/{device_id}/sys/properties/report 发布主题时,需要上传数据,这个数据格式是JSON格式…

充气膜羽毛球馆投资需要多少钱—轻空间

充气膜羽毛球馆是一种现代化的运动设施,以其灵活的结构设计和高效的能耗管理受到广泛关注。投资建设一个充气膜羽毛球馆,涉及多个方面的成本,包括基础建设、膜材选择、系统配置以及运营维护费用。轻空间将详细分析投资建设充气膜羽毛球馆的成…

【C++知识点总结全系列 (06)】:STL六大组件详细介绍与总结(配置器、容器、迭代器、适配器、算法、仿函数)

STL六大组件目录 前言1、配置器(1)What(2)Why(3)HowA.调用new和delete实现内存分配与销毁B.STL Allocator (4)allocator类A.WhatB.HowC.allocator的算法 2、容器(1)What(2)Which(有哪些容器)(3)序列容器(顺序容器)A.WhichB.array&…