pytorch 培训和验证准确性完全不变

vfh0ocws  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(143)

我正试图从一篇研究论文中重建一个模型。没有错误发生,但准确性度量不会改变。我尝试了很多不同的解决方案,其中大多数通常以错误告终,我不得不追踪,直到我失去希望。
数据是使用PyTorch Geometric创建的图形。我确保数据是有效的,没有任何问题。每个图有18个节点,每个节点有18个特征。图是稀疏的,边的数量从一个图到另一个图是不同的。图的边被加权。
为了您的方便,完整的代码沿着数据可以在Colab上找到。
如果你喜欢代码在这里。需要构建的模型:

class GCNModel(nn.Module):
    def __init__(self):
        super(GCNModel, self).__init__()
        # Block1

        self.conv1 = GCNConv(in_channels=18, out_channels=64)  # Graph Convolution
        self.relu1 = nn.ReLU()
        self.conv2 = GCNConv(in_channels=64, out_channels=32)  # Graph Convolution
        self.relu2 = nn.ReLU()
        self.pool = global_mean_pool

        # Block2
        self.fc1 = nn.Linear(32, 32)     # Fully Connected
        self.dropout1 = nn.Dropout(0.3)  # Dropout layer with p=0.3
        self.relu3 = nn.ReLU()

        self.fc2 = nn.Linear(32, 16)     #  Fully Connected
        self.dropout2 = nn.Dropout(0.3)  # Dropout layer with p=0.3
        self.relu4 = nn.ReLU()

        self.fc3 = nn.Linear(16, 1)       # Fully Connected

    def forward(self, data):
        x, edge_index, edge_attr, batch = data.x, data.edge_index, data.edge_attr, data.batch

        # Block1
        x = self.conv1(x, edge_index, edge_attr)  # Pass edge_attr to the convolution
        x = self.relu1(x)

        # ReLU Graph Convolution
        x = self.conv2(x, edge_index, edge_attr)  # Pass edge_attr to the convolution
        x = self.relu2(x)

        # Average pooling along the spatial dimension
        x = self.pool(x, batch)

        # Block2 Fully Connected
        x = self.fc1(x)
        x = self.dropout1(x)  # Apply dropout
        x = self.relu3(x)

        # ReLU Fully Connected
        x = self.fc2(x)
        x = self.dropout2(x)  # Apply dropout
        x = self.relu4(x)

        # ReLU Fully Connected
        x = self.fc3(x)

        return x

培训、验证和测试程序:

# Instantiate GCNModel
model = GCNModel()

# Define optimizer and learning rate
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=0.0001)

# Define your loss function
criterion = nn.CrossEntropyLoss()

# Define the data loaders
train_loader = DataLoader(data_train, batch_size=64, shuffle=True)
val_loader = DataLoader(data_val, batch_size=64, shuffle=False)
test_loader = DataLoader(data_test, batch_size=64, shuffle=False)

# Training loop
def train(epoch):
    model.train()
    for data in train_loader:
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, data.y.view(-1, 1).float())
        loss.backward()
        optimizer.step()

# Function to compute accuracy
def compute_accuracy(loader):
    model.eval()
    predictions = []
    labels = []
    with torch.no_grad():
        for data in loader:
            output = model(data)
            predictions.extend(torch.argmax(output, axis=1).cpu().numpy())  # Use argmax for predicted labels
            labels.extend(data.y.cpu().numpy())
    accuracy = accuracy_score(labels, predictions)
    return accuracy

# Training and validation
num_epochs = 50  # Train for 50 epochs
for epoch in range(1, num_epochs + 1):
    train(epoch)
    train_acc = compute_accuracy(train_loader)  # Compute accuracy on training data
    val_acc = compute_accuracy(val_loader)
    print(f"Epoch [{epoch}/{num_epochs}], Train Acc: {train_acc:.4f}, Val Acc: {val_acc:.4f}")

# Testing
test_acc = compute_accuracy(test_loader)
print(f"Testing Accuracy: {test_acc:.4f}")

输出量:

Epoch [1/50], Train Acc: 0.4471, Val Acc: 0.4470
Epoch [2/50], Train Acc: 0.4471, Val Acc: 0.4470
.
.
.
Epoch [50/50], Train Acc: 0.4471, Val Acc: 0.4470

谢谢你的帮助

xjreopfe

xjreopfe1#

这是因为根据你的代码,最后一层以一个完全连接的层结束,你错过了输入Softmax层进行预测,因此模型并没有真正学习到任何重要的东西。修改代码的forward方法,在最后一层添加softmax,如下所示:

class GCNModel(nn.Module):
    # ... (other parts of the code)

    def forward(self, data):
        # ... (previous parts of the forward method)

        # ReLU Fully Connected
        x = self.fc2(x)
        x = self.dropout2(x)
        x = self.relu4(x)

        # Softmax Fully Connected (for multiclass classification)
        x = self.fc3(x)
        x = torch.softmax(x)  # Apply softmax activation

        return x

编辑2:我还发现了一些与您构建的模型不一致的地方,根据您提供的模型配置,正确的模型应该如下所示:

import torch
import torch.nn as nn
import torch.nn.functional as F

class GraphConvolutionLayer(nn.Module):
    def __init__(self, in_features, out_features):
        super(GraphConvolutionLayer, self).__init__()
        self.linear = nn.Linear(in_features, out_features)

    def forward(self, x, adjacency_matrix):
        batch_size, num_nodes, _ = x.size()

        x = self.linear(x)
        x = torch.bmm(adjacency_matrix, x)

        return x

class GCNNModel(nn.Module):
    def __init__(self):
        super(GCNNModel, self).__init__()
        self.layers = nn.ModuleList([
            GraphConvolutionLayer(in_features=18, out_features=64),
            nn.ReLU(),
            GraphConvolutionLayer(in_features=64, out_features=32),
            nn.ReLU(),
            nn.AvgPool2d(1, 32)
        ])
        
        self.fc_layers = nn.ModuleList([
            nn.Linear(in_features=32, out_features=32),  # Fully connected layer
            nn.ReLU(),
            nn.Linear(in_features=32, out_features=16),  # Fully connected layer
            nn.ReLU(),
            nn.Linear(in_features=16, out_features=1),   # Fully connected layer
            nn.Softmax(dim=1)  # Softmax layer
        ])

    def forward(self, x, adjacency_matrix):
        for layer in self.layers:
            x = layer(x, adjacency_matrix)
        
        # Average pooling along the spatial dimension
        x = torch.mean(x, dim=1, keepdim=True)
        
        for layer in self.fc_layers:
            x = layer(x)
        
        return x

# Create the GCNN model with both blocks
model = GCNNModel()

print(model)

打印输出:

GCNNModel(
  (layers): ModuleList(
    (0): GraphConvolutionLayer(
      (linear): Linear(in_features=18, out_features=64, bias=True)
    )
    (1): ReLU()
    (2): GraphConvolutionLayer(
      (linear): Linear(in_features=64, out_features=32, bias=True)
    )
    (3): ReLU()
    (4): AvgPool2d(kernel_size=1, stride=32, padding=0)
  )
  (fc_layers): ModuleList(
    (0): Linear(in_features=32, out_features=32, bias=True)
    (1): ReLU()
    (2): Linear(in_features=32, out_features=16, bias=True)
    (3): ReLU()
    (4): Linear(in_features=16, out_features=1, bias=True)
    (5): Softmax(dim=1)
  )
)

你看,现在跟你的型号配置匹配了:

mm9b1k5b

mm9b1k5b2#

问题已解决。它需要编辑模型并从头开始重写。我也使用SkLearn来计算准确度。代码可以在上面提供的Colab链接中找到,只要它可以在线获得。

相关问题