Я пытаюсь построить CNN для прогнозирования количества пальцев в изображении, используя PyTorch.Сеть:
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 для последнего слоя с кросс-энтропийной потерей, или Sigmoid с двоичной кросс-энтропией, MSE или SmoothL1Loss.
В случае использования оптимизатора Адама я получаю аналогичные результаты, только в диапазоне 1e-12 ~ 1e-14.
Чего мне не хватает?