На вход поданы шесть объектов, поэтому форма ответа равна (6, 1). Количество параметров равно 17: первый слой содержит 2 · 4 + 4 = 12 чисел, второй — 4 · 1 + 1 = 5. У ReLU обучаемых параметров нет, но её присутствие меняет возможности сети. Считать только веса и забывать о функции активации было бы ошибкой: устройство вычисления определяется и параметрами, и самими операциями.
Выражение model.parameters() позволяет перебрать зарегистрированные параметры модели. Оно не создаёт новую копию сети и не выполняет обучение. Когда мы передадим эти параметры оптимизатору, он получит доступ к тем самым весам и смещениям, которые участвуют в прямом проходе. А метод numel(), использованный в примере, просто возвращает количество элементов тензора. Сумма таких количеств и дала нам 17.
У каждой сети есть две связанные, но разные стороны. Архитектура описывает, какие слои существуют и как данные проходят между ними. Параметры содержат конкретные числа внутри этих слоёв. Две сети с одинаковой архитектурой могут отвечать по-разному, если их веса различаются. И наоборот, одних чисел недостаточно, чтобы восстановить вычисление, если неизвестно, в какие слои их поместить.
Как описать собственный порядок вычислений
Для простой цепочки достаточно Sequential. Если мы хотим дать частям сети имена или явно записать логику прохождения данных, можно создать собственный класс на основе nn.Module. В методе __init__ создаются слои, а метод forward описывает прямой проход. Вызов super().__init__() подготавливает служебные механизмы базового модуля, благодаря которым вложенные слои и их параметры учитываются в модели.