【发布时间】:2019-02-24 15:06:23
【问题描述】:
我正在尝试使用 PyTorch 构建一个用于预测图像中手指数量的 CNN。网络:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.Layer1 = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=16, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2)),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=128, out_channels=256, kernel_size=(3, 3)),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2)),
nn.Conv2d(in_channels=256, out_channels=16, kernel_size=(1, 1)),
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=128, out_channels=256, kernel_size=(3, 3)),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2)),
nn.Conv2d(in_channels=256, out_channels=16, kernel_size=(1, 1)),
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2)),
nn.Conv2d(in_channels=128, out_channels=16, kernel_size=(1, 1)),
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2)),
nn.Conv2d(in_channels=128, out_channels=16, kernel_size=(1, 1)),
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
nn.ReLU(),
nn.Conv2d(in_channels=128, out_channels=256, kernel_size=(3, 3)),
nn.ReLU(),
)
self.Layer2 = nn.Sequential(
nn.Linear(1536, 100),
nn.Tanh(),
nn.Linear(100, 6),
nn.Softmax()
)
self.optimizer = optimizers.Adadelta(self.parameters())
def forward(self, X):
X = self.Layer1(X)
print(X.shape)
X = self.Layer2(X.reshape(1, 1536))
X = X.squeeze()
return X
def calc_loss(self, X, num):
out = self.forward(X).unsqueeze(dim=0)
print("Output: "+str(out))
target = torch.tensor([num], dtype=torch.int64).cuda()
criterion = nn.CrossEntropyLoss()
loss = criterion(out, target)
return loss
def train_step(self, X, Y):
loss = self.calc_loss(X, Y)
print(loss)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
但是,训练完成后,所有预测的值几乎相同(大约 0.15 ~ 0.18)。
看起来好像网络平均了输出概率以最小化损失,而不是学习实际值。
无论我将 Softmax 用于具有交叉熵损失的最后一层,还是使用具有二元交叉熵、MSE 或 SmoothL1Loss 的 Sigmoid,我都会得到相同的结果。
如果使用 Adam 优化器,我会得到类似的结果,只是在 1e-12 ~ 1e-14 的范围内。
我错过了什么?
【问题讨论】:
-
说实话,你的实现有点混乱,为什么不把模型实现和训练循环分开呢?这将使您的调试更加容易
-
我想将所有网络操作与数据操作分开。所有数据都从不同的文件加载并从该文件馈送到模型。
-
train_step在循环中多次调用上述注释中提到的文件的不同 X 和 Y 值。 -
我明白了。您是否尝试在单个批次上过度拟合您的模型?只是为了测试,以确保一切正常?
-
好的,我再次查看了您的问题,对于
CrossEntropyLoss,您需要不带 Softmax 的原始输出。
标签: python deep-learning computer-vision conv-neural-network pytorch