import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

# 定义CNN模型
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3)
        self.fc1 = nn.Linear(32 * 6 * 6, 128)
        
    def forward(self, x):
        x = x.unsqueeze(1)  # 将输入数据转换为图片格式,添加一个通道维度
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2)
        x = x.view(-1, 32 * 6 * 6)
        x = F.relu(self.fc1(x))
        return x

# 定义BiGRU模型
class BiGRU(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(BiGRU, self).__init__()
        self.gru = nn.GRU(input_size, hidden_size, num_layers, batch_first=True, bidirectional=True)
        
    def forward(self, x):
        _, h = self.gru(x)
        h = h.permute(1, 0, 2).contiguous().view(x.size(0), -1)
        return h

# 定义融合模型
class FusionModel(nn.Module):
    def __init__(self, input_size):
        super(FusionModel, self).__init__()
        self.cnn = CNN()
        self.gru = BiGRU(input_size, 64, 2)
        self.fc = nn.Linear(128 + 128, 8)
        
    def forward(self, x):
        img_data = x[:, :23]  # 提取图片数据的特征
        seq_data = x[:, 23:]  # 提取序列数据的特征
        
        img_feat = self.cnn(img_data)
        seq_feat = self.gru(seq_data)
        
        feat = torch.cat((img_feat, seq_feat), dim=1)  # 进行特征融合
        output = self.fc(feat)
        return output

# 读取数据集
def load_dataset(file_path):
    dataset = []
    with open(file_path, 'r') as f:
        lines = f.readlines()
        for line in lines:
            line = line.strip().split(',')
            features = list(map(float, line[:-1]))
            label = int(line[-1])
            dataset.append((features, label))
    return dataset

# 数据预处理
def preprocess_data(dataset):
    max_value = np.max(dataset, axis=0)
    min_value = np.min(dataset, axis=0)
    dataset = (dataset - min_value) / (max_value - min_value)  # 归一化
    return dataset

# 划分数据集
def split_dataset(dataset, train_ratio, valid_ratio):
    train_size = int(len(dataset) * train_ratio)
    valid_size = int(len(dataset) * valid_ratio)

    train_data = dataset[:train_size]
    valid_data = dataset[train_size:train_size+valid_size]
    test_data = dataset[train_size+valid_size:]

    return train_data, valid_data, test_data

# 将数据集转换为张量
def convert_to_tensor(dataset):
    features, labels = zip(*dataset)
    features = torch.tensor(features, dtype=torch.float32)
    labels = torch.tensor(labels, dtype=torch.long)
    return features, labels

# 训练模型
def train(model, train_loader, valid_loader, criterion, optimizer, num_epochs):
    for epoch in range(num_epochs):
        model.train()
        train_loss = 0.0
        for inputs, labels in train_loader:
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            train_loss += loss.item() * inputs.size(0)
        
        # 在验证集上评估模型
        model.eval()
        valid_loss = 0.0
        valid_acc = 0.0
        with torch.no_grad():
            for inputs, labels in valid_loader:
                outputs = model(inputs)
                loss = criterion(outputs, labels)
                valid_loss += loss.item() * inputs.size(0)
                _, preds = torch.max(outputs, 1)
                valid_acc += torch.sum(preds == labels.data)
        
        train_loss = train_loss / len(train_loader.dataset)
        valid_loss = valid_loss / len(valid_loader.dataset)
        valid_acc = valid_acc / len(valid_loader.dataset)
        
        print(f'Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss:.4f}, Valid Loss: {valid_loss:.4f}, Valid Acc: {valid_acc.item()*100:.2f}%')

# 测试模型
def test(model, test_loader):
    model.eval()
    test_acc = 0.0
    with torch.no_grad():
        for inputs, labels in test_loader:
            outputs = model(inputs)
            _, preds = torch.max(outputs, 1)
            test_acc += torch.sum(preds == labels.data)
    test_acc = test_acc / len(test_loader.dataset)
    print(f'Test Acc: {test_acc.item()*100:.2f}%')

# 设置超参数
batch_size = 32
learning_rate = 0.001
num_epochs = 10

# 加载并预处理数据集
dataset = load_dataset('data.txt')
dataset = preprocess_data(dataset)

# 划分数据集
train_data, valid_data, test_data = split_dataset(dataset, 0.7, 0.1)

# 转换为张量
train_features, train_labels = convert_to_tensor(train_data)
valid_features, valid_labels = convert_to_tensor(valid_data)
test_features, test_labels = convert_to_tensor(test_data)

# 创建数据加载器
train_dataset = torch.utils.data.TensorDataset(train_features, train_labels)
valid_dataset = torch.utils.data.TensorDataset(valid_features, valid_labels)
test_dataset = torch.utils.data.TensorDataset(test_features, test_labels)

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

# 创建模型并定义损失函数和优化器
model = FusionModel(23)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 训练模型
train(model, train_loader, valid_loader, criterion, optimizer, num_epochs)

# 测试模型
test(model, test_loader)

请注意,上述代码中的模型结构和超参数可能需要根据实际情况进行调整。

基于CNN和BiGRU的特征融合模型用于多分类任务

原文地址: https://www.cveoy.top/t/topic/lHFE 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录