Практическое руководство по глубокому обучению 5.2 Доступ к параметрам PyTorch

глубокое обучение PyTorch

Примите участие в 19-м дне ноябрьского испытания обновлений и узнайте подробности события:Вызов последнего обновления 2021 г.

Почему вам нужно извлекать параметры отдельно?

Потому что в процессе обучения наша цель — найти значение параметра, которое минимизирует функцию потерь. После обучения нам нужно убрать эти параметры, чтобы делать прогнозы, или использовать их в другом месте.

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

  • Доступ к параметрам для отладки, диагностики и визуализации.
  • инициализация параметров.
  • Совместное использование параметров между различными компонентами модели.

import torch
from torch import nn

net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
X = torch.rand(size=(2, 4))
net(X)

Это все еще простая реализация многослойного персептрона, а затем получить X в качестве входных данных.

когда прошелSequentialКогда класс определяет модель, мы можем получить доступ к любому уровню модели через индекс.

print(net)

Вы можете видеть, что вывод:

>>
Sequential(
  (0): Linear(in_features=4, out_features=8, bias=True)
  (1): ReLU()
  (2): Linear(in_features=8, out_features=1, bias=True)
)

Мы можем получить нужный слой по порядковому номеру впереди.

print(net[0])
print(net[1])

print(net[2].state_dict())
>>
Linear(in_features=4, out_features=8, bias=True)
ReLU()

OrderedDict([('weight', tensor([[-0.0264, -0.0906,  0.3497,  0.3284, -0.0173,  0.0124,  0.0136,  0.0782]])), ('bias', tensor([0.2243]))])

Неудивительно, что мы видим, что собой представляют первые два слоя.

Что касается третьего вывода, мы видим, что этот слой содержит два параметра.

[
    (
        'weight', 
        tensor([[-0.0264, -0.0906,  0.3497,  0.3284, -0.0173,  0.0124,  0.0136,  0.0782]])
    ),
    (
        'bias', 
        tensor([0.2243])
    )
]
print(type(net[2].bias))
print(type(net[0].weight))
>> 
<class 'torch.nn.parameter.Parameter'>
<class 'torch.nn.parameter.Parameter'>

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

print(net[2].bias)
print(net[0].weight)
Parameter containing:
tensor([-0.1431,  0.1381, -0.2775,  0.0038, -0.0269,  0.0631, -0.1791,  0.1291],
       requires_grad=True)
Parameter containing:
tensor([[-0.4736,  0.2223, -0.0059,  0.4146],
        [-0.1052,  0.2813, -0.2315,  0.2931],
        [-0.4990, -0.1991, -0.1453,  0.0369],
        [-0.4676,  0.0669, -0.0069, -0.4932],
        [-0.4223,  0.0659, -0.3783, -0.1145],
        [-0.0460,  0.2386, -0.1586,  0.2148],
        [-0.0085, -0.3642,  0.0265,  0.0487],
        [ 0.2703, -0.2903,  0.1822, -0.3782]], requires_grad=True)

Соответствующий номер слоя + вызов метода для извлечения смещения или параметров сети.

print(*[(name, param.shape) for name, param in net[0].named_parameters()])

print(*[(name, param.shape) for name, param in net.named_parameters()])

print(*net.named_parameters(),end="\n",sep='\n')

# 这里*是一个解包器 ,用于输出列表的每一个元素
>>
('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))

('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8]))
('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))

('0.weight', Parameter containing:
tensor([[ 0.3700,  0.3270, -0.3741, -0.1365],
        [ 0.2200,  0.0786,  0.1241, -0.2834],
        [ 0.3143,  0.3718,  0.3278,  0.0949],
        [ 0.1565,  0.4639, -0.1515, -0.4962],
        [ 0.3102, -0.0025, -0.0099, -0.4132],
        [ 0.1754, -0.1320, -0.3762, -0.1371],
        [-0.3860, -0.0369,  0.3743, -0.0892],
        [ 0.0280, -0.2877, -0.1884,  0.2915]], requires_grad=True))
('0.bias', Parameter containing:
tensor([ 0.4722, -0.4143,  0.0858, -0.2280,  0.4349,  0.3954,  0.0971, -0.1192],
       requires_grad=True))
('2.weight', Parameter containing:
tensor([[ 0.0984,  0.0207, -0.1292,  0.0530, -0.0693,  0.0413, -0.2231, -0.3125]],
       requires_grad=True))
('2.bias', Parameter containing:
tensor([0.1844], requires_grad=True))

Смотрите здесь для распаковщика:Подробное объяснение упаковки и распаковки Python** — Nuggets (juejin.cn)

Я разделил три выхода.

  • Первый - это имя параметра параметра и форма параметра для слоя 0 распакованной сети.
  • Второй — распаковать имена параметров и формы параметров всех слоев сети.
  • Третий — список параметров для распаковки сети.

Вы также можете получить список параметров следующим образом:

print(net.state_dict()['2.bias'].data)
print(net.state_dict()['0.weight'])
>>
tensor([0.1844])
tensor([[ 0.3700,  0.3270, -0.3741, -0.1365],
        [ 0.2200,  0.0786,  0.1241, -0.2834],
        [ 0.3143,  0.3718,  0.3278,  0.0949],
        [ 0.1565,  0.4639, -0.1515, -0.4962],
        [ 0.3102, -0.0025, -0.0099, -0.4132],
        [ 0.1754, -0.1320, -0.3762, -0.1371],
        [-0.3860, -0.0369,  0.3743, -0.0892],
        [ 0.0280, -0.2877, -0.1884,  0.2915]])

Добавлено оно или нет.dataВы можете напрямую вывести значение параметра.

def block1():
    return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
                         nn.Linear(8, 4), nn.ReLU())

def block2():
    net = nn.Sequential()
    for i in range(4):
        # 在这里嵌套
        net.add_module(f'block {i}', block1())
    net[2] = nn.Linear(4,4)
    return net

X = torch.rand(size=(2, 4))
rgnet = nn.Sequential(block2(), nn.Linear(4, 1))
rgnet(X)

Определите вложенную сеть. Я наугад нарисовал картинку, и она выглядит так.

image.png

print(rgnet)

Выведите эту сеть, вы увидите, что ее структура выглядит следующим образом:

>>
Sequential(
  (0): Sequential(
    (block 0): Sequential(
      (0): Linear(in_features=4, out_features=8, bias=True)
      (1): ReLU()
      (2): Linear(in_features=8, out_features=4, bias=True)
      (3): ReLU()
    )
    (block 1): Linear(in_features=4, out_features=4, bias=True)
    (block 2): Sequential(
      (0): Linear(in_features=4, out_features=8, bias=True)
      (1): ReLU()
      (2): Linear(in_features=8, out_features=4, bias=True)
      (3): ReLU()
    )
  )
  (1): Linear(in_features=4, out_features=1, bias=True)
)

Например:

print(rgnet[0][2][0].bias.data)
print(rgnet.state_dict()['0.block 2.0.bias'])
>>
tensor([-0.1555,  0.4410, -0.4920,  0.1434,  0.1243,  0.4114, -0.0883,  0.1387])
tensor([-0.1555,  0.4410, -0.4920,  0.1434,  0.1243,  0.4114, -0.0883,  0.1387])

В этом случае для получения параметров первым расширением является добавление адреса. Второй способ заключается в том, чтобы сначала указать, в каком блоке. Затем укажите, какой слой на каком блоке.


  1. Подробнее о серии «Практическое глубокое обучение» см. здесь:Колонка «Практическое глубокое обучение» (juejin.cn)

  2. Примечания Адрес Github:DeepLearningNotes/d2l(github.com)

Все еще в процессе обновления......