Pytorch中使用Transformer对一维序列进行分类源代码。

Pytorch中使用Transformer对一维序列进行分类源代码。


本程序中,使用了6层Encoder模块和最终的全连接层进行序列分类,没有使用Decoder模块和Embeddi


ng模块(Embedding模块是用于文本嵌入的,本程序数据是序列,因此不用做嵌入)。
1、加载数据,调整为模型需要的输入格式。原始数据为Excel, 400条1*500的序列 (心电信号),其
中200条正常,200条异常。将每条1*500的信号reshape成10*50,即序列长度10*维度50。 这里也可以


理解成把序列看成了文本,每个样本由10个单词(序列长度10)组成,每个单词是50个数字(维度50
)。这样做是为了满足Transformer的输入格式。
2、构建Transformer 模型。其中包含6层的Encoder层和最终的全连接层。.
3、训练测试

PyTorch中使用Transformer对一维序列进行分类项目介绍

项目名称

PyTorch Transformer for 1D Sequence Classification

项目概述

本项目使用PyTorch实现了一个基于Transformer的模型,用于对一维序列进行分类。具体来说,我们处理的是心电信号数据,每个样本是一个长度为500的一维序列。为了适应Transformer模型的输入格式,我们将每个序列reshape成10*50的形状,即序列长度为10,每个时间步的特征维度为50。模型包含6层Encoder模块和一个最终的全连接层,用于将编码后的特征映射到分类结果。

项目特点
  • 数据处理:将原始的心电信号数据从Excel文件加载,并调整为适合Transformer模型的输入格式。
  • 模型构建:构建了一个包含6层Encoder的Transformer模型,不使用Decoder模块和Embedding模块。
  • 训练与测试:提供了完整的训练和测试流程,包括数据加载、模型训练、评估和预测。
项目结构
transformer_sequence_classification/
├── src/                            # 源代码目录
│   ├── data_loader.py              # 数据加载器
│   ├── model.py                    # Transformer模型定义
│   ├── train.py                    # 训练脚本
│   ├── test.py                     # 测试脚本
│   ├── utils.py                    # 辅助函数
├── data/                           # 数据目录
│   ├── ecg_data.xlsx               # 原始心电信号数据
├── README.md                       # 项目说明
└── requirements.txt                # 依赖库文件
主要模块及功能
  1. data_loader.py

    • 功能:加载和预处理数据。
    • 内容
      • load_data函数:从Excel文件中读取数据。
      • preprocess_data函数:将数据reshape成适合Transformer的输入格式(10*50)。
      • create_data_loaders函数:创建训练和验证数据加载器。
  2. model.py

    • 功能:定义Transformer模型。
    • 内容
      • TransformerModel类:包含6层Encoder和一个全连接层。
      • EncoderLayer类:单个Encoder层。
      • PositionalEncoding类:位置编码。
      • forward方法:前向传播过程。
  3. train.py

    • 功能:训练模型。
    • 内容
      • train_model函数:训练模型的主要逻辑。
      • evaluate函数:在验证集上评估模型性能。
      • main函数:主入口点,负责调用上述函数并管理整个训练过程。
  4. test.py

    • 功能:测试模型。
    • 内容
      • test_model函数:在测试集上测试模型性能。
      • main函数:主入口点,负责调用上述函数并管理整个测试过程。
  5. utils.py

    • 功能:提供辅助函数。
    • 内容
      • get_device函数:获取可用的计算设备(CPU或GPU)。
      • set_seed函数:设置随机种子以保证实验的可重复性。
详细代码示例
1. 数据加载与预处理 (data_loader.py)
import pandas as pd
from torch.utils.data import Dataset, DataLoader
import torch

def load_data(file_path):
    df = pd.read_excel(file_path)
    X = df.iloc[:, :-1].values
    y = df.iloc[:, -1].values
    return X, y

def preprocess_data(X, y):
    X = X.reshape(-1, 10, 50)  # Reshape to (batch_size, seq_len, feature_dim)
    X = torch.tensor(X, dtype=torch.float32)
    y = torch.tensor(y, dtype=torch.long)
    return X, y

def create_data_loaders(X, y, batch_size=32, test_size=0.2):
    from sklearn.model_selection import train_test_split
    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=test_size, random_state=42)
    
    train_dataset = torch.utils.data.TensorDataset(X_train, y_train)
    val_dataset = torch.utils.data.TensorDataset(X_val, y_val)
    
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
    
    return train_loader, val_loader
2. Transformer模型定义 (model.py)
import torch
import torch.nn as nn
import math

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_len=5000):
        super(PositionalEncoding, self).__init__()
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0).transpose(0, 1)
        self.register_buffer('pe', pe)

    def forward(self, x):
        x = x + self.pe[:x.size(0), :]
        return x

class EncoderLayer(nn.Module):
    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):
        super(EncoderLayer, self).__init__()
        self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)
        self.linear1 = nn.Linear(d_model, dim_feedforward)
        self.dropout = nn.Dropout(dropout)
        self.linear2 = nn.Linear(dim_feedforward, d_model)
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout1 = nn.Dropout(dropout)
        self.dropout2 = nn.Dropout(dropout)
        self.activation = nn.ReLU()

    def forward(self, src, src_mask=None, src_key_padding_mask=None):
        src2 = self.self_attn(src, src, src, attn_mask=src_mask, key_padding_mask=src_key_padding_mask)[0]
        src = src + self.dropout1(src2)
        src = self.norm1(src)
        src2 = self.linear2(self.dropout(self.activation(self.linear1(src))))
        src = src + self.dropout2(src2)
        src = self.norm2(src)
        return src

class TransformerModel(nn.Module):
    def __init__(self, input_dim, d_model, nhead, num_encoder_layers, dim_feedforward, num_classes, dropout=0.1):
        super(TransformerModel, self).__init__()
        self.input_proj = nn.Linear(input_dim, d_model)
        self.pos_encoder = PositionalEncoding(d_model)
        encoder_layer = EncoderLayer(d_model, nhead, dim_feedforward, dropout)
        self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_encoder_layers)
        self.fc = nn.Linear(d_model, num_classes)
        self.init_weights()

    def init_weights(self):
        initrange = 0.1
        self.input_proj.weight.data.uniform_(-initrange, initrange)
        self.fc.bias.data.zero_()
        self.fc.weight.data.uniform_(-initrange, initrange)

    def forward(self, src):
        src = self.input_proj(src)
        src = self.pos_encoder(src)
        output = self.transformer_encoder(src)
        output = output.mean(dim=0)  # Global average pooling
        output = self.fc(output)
        return output
3. 训练脚本 (train.py)
import torch
import torch.optim as optim
import torch.nn.functional as F
from data_loader import load_data, preprocess_data, create_data_loaders
from model import TransformerModel
from utils import get_device, set_seed

def train_model(model, train_loader, val_loader, epochs=10, lr=0.001):
    device = get_device()
    model.to(device)
    optimizer = optim.Adam(model.parameters(), lr=lr)
    criterion = nn.CrossEntropyLoss()

    for epoch in range(epochs):
        model.train()
        total_loss = 0.0
        for batch_idx, (data, target) in enumerate(train_loader):
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            total_loss += loss.item()

        avg_loss = total_loss / len(train_loader)
        print(f'Epoch {epoch+1}/{epochs}, Loss: {avg_loss:.4f}')

        # Evaluate on validation set
        model.eval()
        correct = 0
        with torch.no_grad():
            for data, target in val_loader:
                data, target = data.to(device), target.to(device)
                output = model(data)
                pred = output.argmax(dim=1, keepdim=True)
                correct += pred.eq(target.view_as(pred)).sum().item()

        accuracy = 100. * correct / len(val_loader.dataset)
        print(f'Validation Accuracy: {accuracy:.2f}%')

def main():
    set_seed(42)
    X, y = load_data('data/ecg_data.xlsx')
    X, y = preprocess_data(X, y)
    train_loader, val_loader = create_data_loaders(X, y, batch_size=32, test_size=0.2)

    model = TransformerModel(input_dim=50, d_model=128, nhead=8, num_encoder_layers=6, dim_feedforward=256, num_classes=2)
    train_model(model, train_loader, val_loader, epochs=10, lr=0.001)

if __name__ == '__main__':
    main()
4. 测试脚本 (test.py)
import torch
from data_loader import load_data, preprocess_data, create_data_loaders
from model import TransformerModel
from utils import get_device, set_seed

def test_model(model, test_loader):
    device = get_device()
    model.to(device)
    model.eval()
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            pred = output.argmax(dim=1, keepdim=True)
            correct += pred.eq(target.view_as(pred)).sum().item()

    accuracy = 100. * correct / len(test_loader.dataset)
    print(f'Test Accuracy: {accuracy:.2f}%')

def main():
    set_seed(42)
    X, y = load_data('data/ecg_data.xlsx')
    X, y = preprocess_data(X, y)
    _, test_loader = create_data_loaders(X, y, batch_size=32, test_size=0.2)

    model = TransformerModel(input_dim=50, d_model=128, nhead=8, num_encoder_layers=6, dim_feedforward=256, num_classes=2)
    model.load_state_dict(torch.load('model.pth'))
    test_model(model, test_loader)

if __name__ == '__main__':
    main()
5. 辅助函数 (utils.py)
import torch

def get_device():
    return torch.device("cuda" if torch.cuda.is_available() else "cpu")

def set_seed(seed=42):
    torch.manual_seed(seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed_all(seed)
使用说明
  1. 环境准备

    • 安装依赖库:
      pip install -r requirements.txt
  2. 数据准备

    • 确保数据文件ecg_data.xlsx位于data/目录下。
  3. 训练模型

    • 运行训练脚本:
      python train.py
  4. 测试模型

    • 运行测试脚本:
      python test.py
注意事项
  • 数据预处理:确保数据预处理步骤正确无误,特别是reshape操作。
  • 超参数调整:根据实际情况调整学习率、批大小等超参数,以获得最佳训练效果。
  • 硬件要求:建议使用GPU进行训练,以加快训练速度。如果没有足够的计算资源,可以考虑使用云服务提供商的GPU实例。
  • 平衡数据:注意数据集中各类别之间的不平衡问题,可以通过过采样、欠采样或使用类别权重等方式来解决。

通过上述步骤,你可以成功地使用Transformer模型对一维序列进行分类。这个项目不仅适用于心电信号分类,还可以应用于其他类似的一维序列分类任务。希望这个项目能帮助你更好地理解和应用Transformer模型。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值