pytorch MNIST 神经网络产生几个非零输出
pytorch MNIST neural network produces several non-zero outputs
我尝试做一个在 MNIST 数据集上运行的神经网络。我主要是在遵循 pytorch.nn 教程。结果,我得到了一个可以学习的模型,但是过程或模型本身有问题。我在输出端收到了多个神经元,而不是一个活跃的神经元。
这是模型本身:
model = nn.Sequential(
nn.Linear(784, 64),
nn.ReLU(),
nn.Linear(64, 10),
nn.ReLU(),
)
这是训练过程:
loss_func = nn.CrossEntropyLoss()
opt = optim.SGD(model.parameters(), lr=lr)
for epoch in range(epochs):
model.train()
for xbt, ybt in train_dl:
pred = model(xbt)
loss = loss_func(pred, ybt)
opt.zero_grad()
loss.backward()
opt.step()
model.eval()
# Validation
if epoch % 10 == 0:
with torch.no_grad():
losses, nums = zip(
*[(loss_func(model(xbv), ybv), len(xbv)) for xbv, ybv in valid_dl]
)
val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)
print(epoch, val_loss)
这是每 10 个周期的平均损失:
0 0.13384412774592638
10 0.0900113809091039
20 0.09795805384699234
30 0.10341344920364791
40 0.10804545368137551
这就是将模型应用于验证集的结果:
[[ 0. 0. 0. ... 28.436266 0. 5.001435 ]
[ 7.3331523 12.666427 31.898096 ... 0. 0. 0. ]
[ 0. 18.116354 8.049953 ... 4.330721 0. 0. ]
...
[ 8.504517 0. 6.302228 ... 0. 0. 0. ]
[ 1.7339934 0. 0. ... 0. 2.1565871 0. ]
[45.750134 0. 6.2685804 ... 2.247082 0. 0. ]]
Shape: (9984, 10)
我尝试更改学习速度、模型层数、迭代次数,但似乎没有任何效果。
这是绝对正常的:
你的输出应该是 [bacth_size, 10]
的形状,因为在每次迭代中你给它输入一批 batch_size
图像并且输出层有 10
个神经元。
解读方式如下:
- 输出张量的每一行都是对批次中一张输入图像的预测。
- 对于一行,如果你只想classify,你的猜测将是该行的argmax。例如,如果
output[0] = [ 0. , 0. , 0. , 2.1, 3.0, 0., 4., 28.436266 0., 5.001435 ]
,则表示您的网络预测该图像属于 class n°7(28.436266 是最大值,在索引 7 处)。
现在,您还可以使用某种概率来解释结果。为此,您需要对输出应用 softmax
图层。然后值 output[i][j]
将被解释为图像 i
属于 class j
.
的概率
最后一层有 10 个带有 ReLU 的神经元,是的,所有神经元都会 fire/activated。在这种情况下,每个神经元对线性激活的输出应用 ReLu
函数。即ReLu(w.x+b)
。有 10 个这样的神经元,它们都会根据其输入给出一定的输出,是的,它们都会得到 fired/activated。从中推断输出的方法是采用与具有最大激活的神经元对应的 class(使用 np.argmax 或 torch.max)。
我尝试做一个在 MNIST 数据集上运行的神经网络。我主要是在遵循 pytorch.nn 教程。结果,我得到了一个可以学习的模型,但是过程或模型本身有问题。我在输出端收到了多个神经元,而不是一个活跃的神经元。
这是模型本身:
model = nn.Sequential(
nn.Linear(784, 64),
nn.ReLU(),
nn.Linear(64, 10),
nn.ReLU(),
)
这是训练过程:
loss_func = nn.CrossEntropyLoss()
opt = optim.SGD(model.parameters(), lr=lr)
for epoch in range(epochs):
model.train()
for xbt, ybt in train_dl:
pred = model(xbt)
loss = loss_func(pred, ybt)
opt.zero_grad()
loss.backward()
opt.step()
model.eval()
# Validation
if epoch % 10 == 0:
with torch.no_grad():
losses, nums = zip(
*[(loss_func(model(xbv), ybv), len(xbv)) for xbv, ybv in valid_dl]
)
val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)
print(epoch, val_loss)
这是每 10 个周期的平均损失:
0 0.13384412774592638
10 0.0900113809091039
20 0.09795805384699234
30 0.10341344920364791
40 0.10804545368137551
这就是将模型应用于验证集的结果:
[[ 0. 0. 0. ... 28.436266 0. 5.001435 ]
[ 7.3331523 12.666427 31.898096 ... 0. 0. 0. ]
[ 0. 18.116354 8.049953 ... 4.330721 0. 0. ]
...
[ 8.504517 0. 6.302228 ... 0. 0. 0. ]
[ 1.7339934 0. 0. ... 0. 2.1565871 0. ]
[45.750134 0. 6.2685804 ... 2.247082 0. 0. ]]
Shape: (9984, 10)
我尝试更改学习速度、模型层数、迭代次数,但似乎没有任何效果。
这是绝对正常的:
你的输出应该是 [bacth_size, 10]
的形状,因为在每次迭代中你给它输入一批 batch_size
图像并且输出层有 10
个神经元。
解读方式如下:
- 输出张量的每一行都是对批次中一张输入图像的预测。
- 对于一行,如果你只想classify,你的猜测将是该行的argmax。例如,如果
output[0] = [ 0. , 0. , 0. , 2.1, 3.0, 0., 4., 28.436266 0., 5.001435 ]
,则表示您的网络预测该图像属于 class n°7(28.436266 是最大值,在索引 7 处)。
现在,您还可以使用某种概率来解释结果。为此,您需要对输出应用 softmax
图层。然后值 output[i][j]
将被解释为图像 i
属于 class j
.
最后一层有 10 个带有 ReLU 的神经元,是的,所有神经元都会 fire/activated。在这种情况下,每个神经元对线性激活的输出应用 ReLu
函数。即ReLu(w.x+b)
。有 10 个这样的神经元,它们都会根据其输入给出一定的输出,是的,它们都会得到 fired/activated。从中推断输出的方法是采用与具有最大激活的神经元对应的 class(使用 np.argmax 或 torch.max)。