基于CNN和BiGRU特征融合的八分类模型

本文介绍了一种基于CNN和BiGRU特征融合的八分类模型,该模型使用CNN和BiGRU并行提取特征,并将其进行融合,最终通过全连接层进行八分类。代码使用PyTorch实现,并包含训练和测试过程。

数据集

在一个txt文件夹中有如下格式的数据集,每条样本前23位为特征值,最后一位为分类标签,标签共有8个类别:

7,7,183,233,10,10,3,10,3,10,0,25,21,42,194,0,0,2,1,0,0,32,1.23,4
7,7,183,233,10,10,3,10,3,10,0,25,21,0,0,2,78,2,1,0,0,86.6685638427734,1.25,4
7,7,183,233,10,10,3,10,3,10,0,25,21,90,80,20,10,2,1,0,0,86.64013671875,1.30,0
7,7,183,233,10,10,3,10,3,10,0,25,21,90,80,20,10,2,1,0,0,86.4980087280273,1.10,0
7,0,183,0,9,0,3,10,3,0,0,25,123,90,80,20,10,0,1,0,1,0,1.00,7
7,0,183,0,9,0,3,10,3,0,0,25,123,90,80,20,10,0,1,0,1,0,1.00,7

模型结构

模型使用CNN和BiGRU并行作为特征提取器,其中输入CNN的数据需要将其转化为图片格式,然后将两提取器的结果进行拼接特征融合,再使用全连接层对融合的结果进行八分类。

CNN模型

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)
        self.relu = nn.ReLU()
        self.maxpool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
        self.fc = nn.Linear(32*7*7, 128)
        
    def forward(self, x):
        x = self.conv1(x)
        x = self.relu(x)
        x = self.maxpool(x)
        x = self.conv2(x)
        x = self.relu(x)
        x = self.maxpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

BiGRU模型

class BiGRU(nn.Module):
    def __init__(self):
        super(BiGRU, self).__init__()
        self.gru = nn.GRU(input_size=23, hidden_size=64, num_layers=2, batch_first=True, bidirectional=True)
        self.fc = nn.Linear(128, 128)
        
    def forward(self, x):
        _, h = self.gru(x)
        x = h.permute(1, 0, 2).reshape(x.size(0), -1)
        x = self.fc(x)
        return x

特征融合模型

class FusionModel(nn.Module):
    def __init__(self):
        super(FusionModel, self).__init__()
        self.cnn = CNN()
        self.bigru = BiGRU()
        self.fc = nn.Linear(256, 8)
        
    def forward(self, x):
        cnn_output = self.cnn(x)
        bigru_output = self.bigru(x)
        fusion_output = torch.cat((cnn_output, bigru_output), dim=1)
        output = self.fc(fusion_output)
        return output

数据加载

# Define a custom dataset
class CustomDataset(Dataset):
    def __init__(self, file_path):
        self.data = pd.read_csv(file_path, header=None)
        self.transform = transforms.Compose([
            transforms.ToPILImage(),
            transforms.Resize((28, 28)),
            transforms.ToTensor()
        ])
        
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, idx):
        features = self.data.iloc[idx, :23].values.astype(np.float32)
        label = self.data.iloc[idx, 23]
        features = self.transform(features.reshape(1, 23))
        return features, label

# Load the dataset
train_dataset = CustomDataset('train.txt')
val_dataset = CustomDataset('val.txt')
test_dataset = CustomDataset('test.txt')

# Define the dataloaders
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=64)
test_loader = DataLoader(test_dataset, batch_size=64)

模型训练

# Initialize the model
model = FusionModel()

# Define the loss function and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Training loop
num_epochs = 10
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

for epoch in range(num_epochs):
    model.train()
    train_loss = 0.0
    train_correct = 0
    
    for inputs, labels in train_loader:
        inputs = inputs.to(device)
        labels = labels.to(device)
        
        optimizer.zero_grad()
        
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        
        _, preds = torch.max(outputs, 1)
        train_loss += loss.item() * inputs.size(0)
        train_correct += torch.sum(preds == labels.data)
        
        loss.backward()
        optimizer.step()
        
    train_loss = train_loss / len(train_dataset)
    train_acc = train_correct.double() / len(train_dataset)
    
    model.eval()
    val_loss = 0.0
    val_correct = 0
    
    for inputs, labels in val_loader:
        inputs = inputs.to(device)
        labels = labels.to(device)
        
        with torch.no_grad():
            outputs = model(inputs)
            loss = criterion(outputs, labels)
        
            _, preds = torch.max(outputs, 1)
            val_loss += loss.item() * inputs.size(0)
            val_correct += torch.sum(preds == labels.data)
    
    val_loss = val_loss / len(val_dataset)
    val_acc = val_correct.double() / len(val_dataset)
    
    print(f'Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f}, Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.4f}')

模型测试

# Testing loop
model.eval()
test_correct = 0

for inputs, labels in test_loader:
    inputs = inputs.to(device)
    labels = labels.to(device)

    with torch.no_grad():
        outputs = model(inputs)

        _, preds = torch.max(outputs, 1)
        test_correct += torch.sum(preds == labels.data)

test_acc = test_correct.double() / len(test_dataset)
print(f'Test Acc: {test_acc:.4f}')

总结

本文介绍了一种基于CNN和BiGRU特征融合的八分类模型,并使用PyTorch实现了模型训练和测试过程。该模型通过融合CNN和BiGRU的特征,能够更好地提取数据信息,提高分类效果。

基于CNN和BiGRU特征融合的八分类模型

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

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