为 PyTorch 中的简单神经网络增加训练和测试精度

Gol*_*rck 5 python neural-network python-3.x pytorch

我知道这是一个原始问题但是我应该在我的代码中添加什么来输出神经网络的训练准确度以及损失,我查看了 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()
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

至于测试:

# 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))   
Run Code Online (Sandbox Code Playgroud)

输出:

tensor([[0.0026],
        [0.0011],
        [0.9991]], grad_fn=<SigmoidBackward>)
Run Code Online (Sandbox Code Playgroud)

Szy*_*zke 4

要提高准确性,您只需要一行,即:

print("Accuracy: ", ((prediction > 0.5) == y).float().mean().item())
Run Code Online (Sandbox Code Playgroud)

当您使用sigmoid大于的任何值时0.5,将被视为正数,而小于负数的值则被视为负数。(prediction > 0.5)创建一个tensorofbool类型,然后检查其中哪些等于yfloat()是需要的,因为您无法计算meanbool量。item()不需要,但从单值返回 python 值tensor,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())
Run Code Online (Sandbox Code Playgroud)

请注意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)
Run Code Online (Sandbox Code Playgroud)

该输出logits(假设范围为 的非标准化概率)指示您的神经网络对正类 ( ) 或负类的[-inf, inf]置信度。+inf

你必须相应地改变你的损失函数,例如torch.nn.BCEWithLogitsLossmean默认减少,不需要在这里明确说明):

criterion = torch.nn.BCEWithLogitsLoss()
Run Code Online (Sandbox Code Playgroud)

最后,准确度也略有变化。现在任何大于的值都0被认为是正数,因此你可以这样做:

print("Accuracy: ", ((prediction > 0) == y).float().mean().item())
Run Code Online (Sandbox Code Playgroud)

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

编辑

您还应该将您的数据指定为torch.Tensor,torch.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]])
Run Code Online (Sandbox Code Playgroud)

编辑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()
Run Code Online (Sandbox Code Playgroud)