Pytorch 如何检查BCELoss Pyrotch的准确性?

Pytorch 如何检查BCELoss Pyrotch的准确性?,pytorch,Pytorch,我正在尝试使用Pytorch获取HeartDisease.csv并预测患者是否患有心脏病。。。.csv提供13个输入和1个目标 我正在使用BCELoss,我在理解如何编写精度检查函数方面遇到了困难 我的num_样本正确,但我的num_不正确。我认为这是不理解张量预测的结果。现在我的数字正确率通常超过8000,而我的数字样本是303 对于如何编写此检查精度函数的任何见解,我们将不胜感激 这是我在谷歌合作实验室写的 #imports import torch import torch.nn as n

我正在尝试使用Pytorch获取HeartDisease.csv并预测患者是否患有心脏病。。。.csv提供13个输入和1个目标

我正在使用BCELoss,我在理解如何编写精度检查函数方面遇到了困难

我的num_样本正确,但我的num_不正确。我认为这是不理解张量预测的结果。现在我的数字正确率通常超过8000,而我的数字样本是303

对于如何编写此检查精度函数的任何见解,我们将不胜感激

这是我在谷歌合作实验室写的

#imports
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
import pandas as pd

#create fully connected network
class NN(nn.Module):
  def __init__(self, input_size, num_classes):
    super(NN, self).__init__()
    self.outputs = nn.Linear(input_size, 1)

  def forward(self, x):
     x = self.outputs(x)
     return torch.sigmoid(x) 

#set device
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

#hyperparameters
input_size = 13 # 13 inputs
num_classes = 1 # heartdisease or not
learning_rate = 0.001
batch_size = 64
num_epochs = 1

#load data
class MyDataset(Dataset):
    def __init__(self, root, n_inp):
        self.df = pd.read_csv(root)
        self.data = self.df.to_numpy()
        self.x , self.y = (torch.from_numpy(self.data[:,:n_inp]),
                           torch.from_numpy(self.data[:,n_inp:]))
    def __getitem__(self, idx):
        return self.x[idx, :], self.y[idx,:]
    def __len__(self):
        return len(self.data)

train_dataset = MyDataset("heart.csv", input_size)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle =True)
test_dataset = MyDataset("heart.csv", input_size)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle =True)

#initialize network
model = NN(input_size=input_size, num_classes=num_classes).to(device)

#loss and optimizer
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

#train network
for epoch in range(num_epochs):
  for batch_idx, (data, targets) in enumerate(train_loader):
    #get data to cuda if possible
    data = data.to(device=device)
    targets = targets.to(device=device)

    #forward
    scores = model(data.float())
    targets = targets.float()
    loss = criterion(scores, targets)

    #backward
    optimizer.zero_grad()
    loss.backward()

    #grad descent or adam step
    optimizer.step()

#check accuracy of model
def check_accuracy(loader, model):
  num_correct = 0
  num_samples = 0
  model.eval()

  with torch.no_grad():
    for x, y in loader:
      x = x.to(device=device)
      y = y.to(device=device)

      scores = model(x.float())
      _, predictions = scores.max(1)
      num_correct += (predictions == y).sum()
      num_samples += predictions.size(0)
    
    print("Got {} / {} with accuracy {}".format(num_correct, num_samples, float(num_correct)/float(num_samples)*100))

  model.train()

print("checking accuracy on training data")
check_accuracy(train_loader, model)

print("checking accuracy on test data")
check_accuracy(test_loader, model)

注意:不要欺骗自己。单一线性层+乙状结肠+BCE损失=逻辑回归。这是一个线性模型,所以在将其称为“神经网络”时请注意,这是一个通常用于类似网络的术语,但至少有一个隐藏层和非线性激活

模型的
forward()
函数末尾的
sigmoid
层返回一个(N,1)大小的张量,其中N是批量大小。换句话说,它为每个数据点返回一个标量。每个标量都是介于0和1之间的值(这是sigmoid函数的范围)

其思想是将这些标量解释为与正类相对应的概率。假设1对应心脏病,0对应无心脏病;心脏病为阳性,无心脏病为阴性。现在假设分数为0.6。这可能被解释为相关标签为心脏病的概率为60%,相关标签为无心脏病的概率为40%。这种对乙状结肠输出的解释是BCE丢失的原因(最终只是负对数可能性)

所以你可以做的是检查你的分数是否大于0.5。如果是,预测心脏病。如果不是,则预测没有心脏病

现在,您正在计算维度1的最大分数,这没有任何作用,因为维度1的大小已经是1;取单个值的最大值只会得到该值

试着这样做:

def check_accuracy(loader, model):
  num_correct = 0
  num_samples = 0
  model.eval()

  with torch.no_grad():
    for x, y in loader:
      x = x.to(device=device)
      y = y.to(device=device)

      scores = model(x.float())
      // Create a Boolean tensor (True for scores > 0.5, False for others)
      // and then cast it to a long tensor (Trues -> 1, Falses -> 0)
      predictions = (scores > 0.5).long()
      num_correct += (predictions == y).sum()
      num_samples += predictions.size(0)
    
    print("Got {} / {} with accuracy {}".format(num_correct, num_samples, float(num_correct)/float(num_samples)*100))

  model.train()

您可能还希望将预测张量和目标张量压缩为(N)而不是(N,1),尽管我不确定这在您的情况下是否有必要。

这是有道理的,跨一维计算最大值是多余的,但当我去掉时。最大值(1)我得到值错误:太多值无法解压缩(预期2)编辑:我删除了,我的程序似乎运行良好如果这个答案解决了你的问题,我会要求你将它标记为正确。如果这个答案不能解决你的问题,但你自己解决了,请写下你自己的答案并标记为正确。这样,这个问题就不会出现在未回答的标签上。