【问题标题】:Add Training and Testing Accuracy to a Simple Neural Network in PyTorch在 PyTorch 中为简单的神经网络添加训练和测试精度
【发布时间】:2020-05-26 23:58:38
【问题描述】:

我知道这是一个原始问题,但是我应该在我的代码中添加什么来输出除了损失之外的神经网络的训练准确性,我查看了 PyTorch 教程,他们展示了如何在图像分类,但我不知道如何在我的简单 XOR 求解 NN 中做到这一点,下面是代码:

# Step 1: importing our dependencies
import torch
from torch.autograd import Variable
import numpy as np

# Our data
x = Variable(torch.Tensor([[0, 0, 1], [0, 1, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], 
                           [1, 1, 1], [0, 0, 0]]))
y = Variable(torch.Tensor([[0], [1], [1], [1], [1], [0], [0]]))

# Step 2: building our class model             
class NeuralNetwork(torch.nn.Module):
def __init__(self):
    super(NeuralNetwork, self).__init__()
    self.linear_ij = torch.nn.Linear(3, 4)
    self.linear_jk = torch.nn.Linear(4, 1)

def forward(self, x):
    matmul = self.linear_ij(x)
    activation = torch.sigmoid(matmul)
    matmul = self.linear_jk(activation)
    prediction = torch.sigmoid(matmul)
    return prediction

# Our model
model = NeuralNetwork()

# Constructing the loss function and the optimization algorithm
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=1)

# Step 3: the training process
for epoch in range(10000):

    prediction = model(x)
    loss = criterion(prediction, y)

    if epoch % 1000 == 0 or epoch == 10000 - 1:
        print("epoch ", epoch, ",", "loss: ", loss.item())

    # Backpropagation process
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

这就是它作为输出提供的内容:

epoch  0 , loss:  0.6983293294906616
epoch  1000 , loss:  0.015215665102005005
epoch  2000 , loss:  0.0048239342868328094
epoch  3000 , loss:  0.00280318153090775
epoch  4000 , loss:  0.001963752554729581
epoch  5000 , loss:  0.0015071843517944217
epoch  6000 , loss:  0.0012211233843117952
epoch  7000 , loss:  0.0010254186345264316
epoch  8000 , loss:  0.000883264874573797
epoch  9000 , loss:  0.0007753585232421756
epoch  9999 , loss:  0.0006908221403136849

至于测试:

# Testing our model
model.eval()

x_test = Variable(torch.Tensor([[1, 1, 0], [0, 0, 1], [0, 1, 1]]))
y_test = Variable(torch.Tensor([[0], [0], [1]]))
y_pred = model(x_test)
print(model(x_test))   

输出:

tensor([[0.0026],
        [0.0011],
        [0.9991]], grad_fn=<SigmoidBackward>)

【问题讨论】:

    标签: python python-3.x neural-network pytorch


    【解决方案1】:

    要增加准确性,您只需要一行,即:

    print("Accuracy: ", ((prediction > 0.5) == y).float().mean().item())
    

    当您使用sigmoid 时,任何大于0.5 的值都被视为正值,而低于负值的值。 (prediction &gt; 0.5) 创建一个 bool 类型的 tensor 并检查其中哪些等于 y。需要float(),因为您无法计算bool 张量的meanitem() 不是必需的,但会从单值 tensor 返回 python 值,这样 IMO 看起来更干净。

    您可以对test 执行相同的操作,因此会是:

    model.eval()
    
    x_test = Variable(torch.Tensor([[1, 1, 0], [0, 0, 1], [0, 1, 1]]))
    y_test = Variable(torch.Tensor([[0], [0], [1]]))
    with torch.no_grad():
        y_pred = model(x_test)
        print("Accuracy: ", ((y_pred > 0.5) == y_test).float().mean().item())
    

    请注意torch.no_grad()。当您在其范围内时,此上下文管理器将禁用 autograph。由于您只是通过神经网络传递输入,而不是使用梯度对其进行训练,因此签名不需要成为等式的一部分。

    使用 logits

    不要在你的神经网络中使用最终激活通常是一个好习惯(除非你真的需要它)。因此你的前锋看起来像这样:

    def forward(self, x):
        matmul = self.linear_ij(x)
        activation = torch.sigmoid(matmul)
        # Notice no sigmoid
        return self.linear_jk(activation)
    

    这会输出logits(假设范围为[-inf, inf] 的非归一化概率),表明您的神经网络对它是正类(+inf)还是负类的置信度。

    您必须相应地更改损失函数,例如torch.nn.BCEWithLogitsLossmean 为默认归约,此处无需明确):

    criterion = torch.nn.BCEWithLogitsLoss()
    

    最后,准确性也略有变化。现在任何大于0 的东西都被认为是积极的,因此你可以这样做:

    print("Accuracy: ", ((prediction > 0) == y).float().mean().item())
    

    如果您需要概率,您仍然可以在输出中使用torch.sigmoid,但您甚至可能不需要它(在这种情况下似乎如此)。

    编辑

    您还应该将您的数据指定为torch.Tensortorch.Variable 已弃用(tensors 已经有requires_grad=True),例如:

    x = torch.Tensor(
        [[0, 0, 1], [0, 1, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1], [0, 0, 0]]
    )
    y = torch.Tensor([[0], [1], [1], [1], [1], [0], [0]])
    

    编辑2:

    它应该放在您的丢失打印下方(或上方),例如:

    for epoch in range(10000):
    
        prediction = model(x)
        loss = criterion(prediction, y)
    
        if epoch % 1000 == 0 or epoch == 10000 - 1:
            # Here is fine
            print("Accuracy: ", ((prediction > 0.5) == y).float().mean().item())
            print("epoch ", epoch, ",", "loss: ", loss.item())
    
        # Backpropagation process
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    

    【讨论】:

    • 谢谢,但我收到错误消息:“预期为标量类型字节的对象,但为参数 #2 'other' 获得了标量类型 Float”
    • 你的 pytorch 版本是多少?在1.4.0 上完全没问题。还添加了一个编辑
    • 谢谢我的 PyTorch 版本是 1.0.1,它解释了错误。我想赞成你的回答,但我需要 15 个声望。非常感谢您的详细回答,非常感谢。
    • 没问题,现在您有足够的时间来投票,祝您 StackOverflowing 愉快,并使您的依赖关系保持最新。 :)
    • 编辑了我的答案
    猜你喜欢
    • 2018-10-30
    • 2020-05-20
    • 2017-06-08
    • 1970-01-01
    • 2011-05-11
    • 2020-09-10
    • 2013-05-25
    • 2020-06-07
    • 2020-05-07
    相关资源
    最近更新 更多