Количество слоев в списке (net .parameters ()) - PullRequest
1 голос
/ 02 августа 2020

Новое в сверточных нейронных сетях, извините, если это не имеет особого смысла. У меня есть этот код:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


net = Net()

, и я думаю, что у него 5 слоев. Однако, когда я печатаю len ((list (net .parameters ())), я получаю 10. Разве это не список размером 5 с параметрами для каждого слоя?

1 Ответ

1 голос
/ 02 августа 2020

Быстрый ответ: Вы получаете дополнительный массив параметров для каждого слоя, содержащий вектор смещения, связанный со слоем.

Подробный ответ : Я постараюсь направить вы в процессе изучения ваших вопросов.

Кажется, неплохо было бы посмотреть, каковы наши 10 параметров:

for param in net.parameters():
    print(type(param), param.size())

<class 'torch.nn.parameter.Parameter'> torch.Size([6, 3, 5, 5])
<class 'torch.nn.parameter.Parameter'> torch.Size([6])
<class 'torch.nn.parameter.Parameter'> torch.Size([16, 6, 5, 5])
<class 'torch.nn.parameter.Parameter'> torch.Size([16])
<class 'torch.nn.parameter.Parameter'> torch.Size([120, 400])
<class 'torch.nn.parameter.Parameter'> torch.Size([120])
<class 'torch.nn.parameter.Parameter'> torch.Size([84, 120])
<class 'torch.nn.parameter.Parameter'> torch.Size([84])
<class 'torch.nn.parameter.Parameter'> torch.Size([10, 84])
<class 'torch.nn.parameter.Parameter'> torch.Size([10])

Мы можем распознать наши 5 слоев и дополнительную строку для каждого слой. Например, если мы посмотрим на определенный слой c, например, первый сверточный слой, мы получим:

for param in net.conv1.parameters():
    print(type(param), param.size())
<class 'torch.nn.parameter.Parameter'> torch.Size([6, 3, 5, 5])
<class 'torch.nn.parameter.Parameter'> torch.Size([6])

Итак, теперь, когда мы знаем, что у нас есть два массива параметров для каждого слоя, вопрос почему. Первый массив 6*3*5*5 соответствует вашим 6 ядрам размером 5 * 5 с 3 каналами, второй соответствует смещению, связанному с каждым из ваших ядер. С математической точки зрения, чтобы вычислить значение на следующем слое, связанном с данным ядром, вы выполняете свертку между областью под нужным пикселем и ядром и добавляете действительное число. Это число называется смещением, и эмпирически доказано, что использование смещения дает лучшие результаты.

Теперь вы также можете создать слой без смещения, и тогда вы получите только один массив параметров:

layer = nn.Conv2d(3,6,5, bias= False)
for param in layer.parameters():
    print(type(param), param.size())
<class 'torch.nn.parameter.Parameter'> torch.Size([6, 3, 5, 5])
...