Поделиться через


Руководство по языку спецификаций нейронных сетей Net# для Студии машинного обучения (классическая модель)

ОБЛАСТЬ ПРИМЕНЕНИЯ К:Применимо к.Машинное обучение Studio (классическая) Не применяется к.Машинное обучение Azure

Внимание

Поддержка Студии машинного обучения (классической) будет прекращена 31 августа 2024 г. До этой даты рекомендуется перейти на Машинное обучение Azure.

Начиная с 1 декабря 2021 года вы не сможете создавать новые ресурсы Студии машинного обучения (классической). Существующие ресурсы Студии машинного обучения (классической) можно будет использовать до 31 августа 2024 г.

Прекращается поддержка документации по Студии машинного обучения (классической). В будущем она может не обновляться.

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

Спецификацию архитектуры Net# можно использовать во всех модулях нейронной сети в Студии машинного обучения (классической):

В этой статье вы узнаете основные понятия и синтаксис, необходимые для разработки настраиваемой нейронной сети с помощью Net#.

  • Требования к нейронным сетям и определения основных компонентов
  • Синтаксис и ключевые слова языка спецификаций Net#
  • Примеры настраиваемых нейронных сетей, созданных с использованием Net#

Основы нейронных сетей

Структура нейронной сети состоит из узлов, упорядоченных в слои, и взвешенных подключений (или переходов) между узлами. Подключения направленные, и для каждого из них определено по узлу источника и назначения.

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

Net# поддерживает различные виды пакетов подключений, которые позволяют настраивать способ, которым сопоставляется вход со скрытыми слоями и выходами.

Пакет по умолчанию или стандартный пакет называется полным. В таком пакете каждый узел в слое источника подключается к каждому узлу в слое назначения.

В дополнение к этому, Net# поддерживает следующие четыре типа дополнительных пакетов подключения:

  • Фильтрованные пакеты. Используя места назначения узла слоя источника и узла слоя назначения, вы можете задать предикат. Узлы подключаются, если предикат имеет значение True.

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

  • Группирующие пакеты и пакеты нормализации ответов. Эти пакеты аналогичны сверточным пакетам в том смысле, что пользователь определяет небольшие окрестности узлов в слое источника. Различие заключается в том, что в таких пакетах не поддерживается обучение по весам переходов. Вместо этого для определения значения узла назначения к узлу источника применяется предопределенная функция.

Поддерживаемые настройки

Архитектуру моделей нейронных сетей, создаваемых в Студии машинного обучения (классической), можно настраивать в широком диапазоне с помощью Net#. Вы можете:

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

Дополнительные сведения о синтаксисе языка спецификаций см. в разделе Спецификация структуры.

Примеры определения нейронных сетей для некоторых общих задач машинного обучения (от простого к сложному) см. в разделе Примеры.

Общие требования

  • Должен быть точно один выходной слой, как минимум один входной слой, а также ноль или более скрытых слоев.
  • Каждый слой имеет фиксированное количество узлов, концептуально организованных в прямоугольную матрицу произвольных размеров.
  • Входные слои не имеют связанных обученных параметров и представляют собой точку, в которой данные экземпляра входят в сеть.
  • С обучаемыми слоями (скрытыми и выходными) связаны обученные параметры, известные как веса и смещения.
  • Узлы источника и назначения должны находиться в отдельных слоях.
  • Подключения должны быть ациклическими. Другими словами, не должно быть цепочки подключений, ведущей назад к исходному узлу источника.
  • Выходной слой не должен быть слоем источника пакета подключений.

Спецификация структуры

Спецификация структуры нейронной сети состоит из трех разделов: объявления констант, объявления слоев, объявления подключений, а также дополнительного раздела объявления общего доступа. Указанные разделы могут задаваться в любом порядке.

Объявление констант

Объявление констант является необязательным. Этот раздел предоставляет средство, позволяющее задать значения, используемые в определении нейронной сети. Оператор объявления состоит из идентификатора, за которым следует знак равенства и выражение значения.

Например, следующий оператор задает константу x:

Const X = 28;

Для одновременного определения двух или более констант заключите имена и значения идентификаторов в кавычки и разделите их точками с запятой. Например:

Const { X = 28; Y = 4; }

Правая сторона каждого выражения присваивания может быть целым числом, вещественным числом, логическим значением (true/false (истина/ ложь)) или математическим выражением. Например:

Const { X = 17 * 2; Y = true; }

Объявление слоев

Слои нужно обязательно объявить. При этом определяется размер и источник слоя, в том числе его пакеты подключений и атрибуты. Определение начинается с имени слоя (входной, скрытый или выходной), за которым следует размер слоя (набор целых положительных чисел). Например:

input Data auto;
hidden Hidden[5,20] from Data all;
output Result[2] from Hidden all;
  • Произведение измерений представляет собой количество узлов слоя. В нашем примере указано два измерения [5,20]. Это означает, что в слое есть 100 узлов.
  • Слои можно объявлять в любом порядке, с одним исключением: если определяется более одного входного слоя, порядок, в котором они объявляются, должен соответствовать порядку признаков во входных данных.

Чтобы задать автоматическое определение числа узлов в слое, используйте ключевое слово auto. Ключевое слово auto выполняет разные действия в зависимости от слоя.

  • При объявлении входного слоя количество узлов представляет собой количество функций во входных данных.
  • При объявлении скрытого слоя число узлов определяется значением параметра Количество скрытых узлов.
  • При объявлении выходного слоя количество узлов равняется 2 для двухклассной классификации, 1 — для регрессии и равно количеству выходных узлов для многоклассовой классификации.

Например, следующее определение сети позволяет автоматически определять размер всех слоев:

input Data auto;
hidden Hidden auto from Data all;
output Result auto from Hidden all;

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

Поддерживаются следующие выходные функции:

  • sigmoid
  • линейная
  • softmax
  • rlinear
  • square
  • sqrt
  • srlinear
  • abs
  • tanh
  • brlinear

Например, в следующем объявлении используется функция softmax:

output Result [100] softmax from Hidden all;

Объявление подключений

Сразу после определения обучаемого слоя необходимо объявить подключения среди слоев, которые были определены. Объявление пакета подключений начинается с ключевого слова from, за которым следует имя слоя источника пакета, а также указывается вид создаваемого пакета подключений.

В настоящее время поддерживается пять видов пакетов подключений:

  • Полные пакеты, обозначаемые ключевым словом all.
  • Фильтрованные пакеты, обозначаемые ключевым словом where, за которым следует выражение предиката.
  • Сверточные пакеты, обозначаемые ключевым словом convolve, за которым следуют атрибуты свертки.
  • Группирующие пакеты, обозначаемые ключевым словом max pool или mean pool.
  • Пакеты нормализации ответов, обозначаемые ключевым словом response norm.

Полные пакеты

Полный пакет подключения содержит подключение от каждого узла слоя источника к каждому узлу слоя назначения. Это тип сетевого подключения по умолчанию.

Фильтрованные пакеты

Спецификация фильтрованного пакета подключений содержит предикат, выраженный синтаксически, практически так же, как лямбда-выражение в C#. В следующем примере определены два фильтрованных пакета:

input Pixels [10, 20];
hidden ByRow[10, 12] from Pixels where (s,d) => s[0] == d[0];
hidden ByCol[5, 20] from Pixels where (s,d) => abs(s[1] - d[1]) <= 1;
  • В предикате для ByRow, s — параметр, который представляет индекс прямоугольного массива узлов входного слоя Pixels, а d — параметр, который представляет индекс массива узлов скрытого слоя ByRow. Тип двух этих параметров (s и d) представляет кортеж целых чисел со значением длины 2. По сути, параметр s находится в диапазоне всех пар целых чисел с условиями 0 <= s[0] < 10 и 0 <= s[1] < 20, а параметр d — в диапазоне всех пар целых чисел с условиями 0 <= d[0] < 10 и 0 <= d[1] < 12.

  • На правой стороне выражения предиката находится условие. В этом примере для каждого значения s и d, условие которого имеет значение True, предусмотрен переход из узла слоя источника в узел слоя назначения. Таким образом, это выражение фильтра указывает, что пакет содержит подключение от узла, определенного параметром s, к узлу, определенному параметром d, во всех случаях, где s[0] равно d[0].

Дополнительно можно указать набор весов фильтрованного пакета. Значение атрибута Weights должно быть кортежем значений с плавающей запятой, длина которых соответствует числу подключений, определенных пакетом. По умолчанию веса генерируются случайно.

Значения весов группируются по индексу узла назначения. То есть, если первый узел назначения подключен к узлам источника K, первые K элементы кортежа Weights — это весовые коэффициенты для первого узла назначения в порядке индексов источника. Это же правило применяется к остальным узлам назначения.

Параметры веса можно также задать как постоянные величины. Например, если параметры веса вам уже известны, вы можете указать их как постоянные величины, используя следующий синтаксис:

const Weights_1 = [0.0188045055, 0.130500451, ...]

Сверточные пакеты

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

Сверточные пакеты используют прямоугольные ядра, которые перемещаются по измерениям. По сути, каждое ядро определяет набор весов, применяемый в локальных окрестностях, которые называются приложениями ядра. Каждое приложение ядра соответствует узлу в слое источника, который называется центральным узлом. Веса ядра используются совместно во многих подключениях. В сверточных пакетах каждое ядро представляет собой прямоугольник, а все приложения ядра имеют одинаковый размер.

Сверточные пакеты поддерживают следующие атрибуты:

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

Чтобы определить форму и расположение ядер, используйте атрибуты KernelShape, Stride, Padding, LowerPad и UpperPad.

  • KernelShape (обязательный): определяет размерность каждого ядра сверточного пакета. Значение должно быть кортежем положительных целых чисел, длина которых равна арности пакета. Каждый компонент этого кортежа не должен быть больше соответствующего компонента атрибута InputShape.

  • Stride (необязательный): определяет размер шага скольжения свертки (размер одного шага для каждого измерения), т. е. расстояние между центральными узлами. Значение должно быть кортежем положительных целых чисел, длина которых равна арности пакета. Каждый компонент этого кортежа не должен больше соответствующего компонента атрибута KernelShape. Значение по умолчанию: кортеж со всеми компонентами, равными единице.

  • Sharing (необязательный): определяет вес, общий для каждого измерения свертки. Значение может быть одним логическим значением или кортежем логических значений, длина которых представляет собой арность пакета. Одно логическое значение расширяется до кортежа нужной длины со всеми компонентами, равными определенному значению. Значение по умолчанию — кортеж, состоящий из всех значений True.

  • MapCount (необязательный): определяет число карт функций для сверточного пакета. Значение может быть одним положительным целым числом или кортежем положительных целых, длина которых представляет собой арность пакета. Одно целое значение расширяется до кортежа нужной длины с первыми компонентами, равными определенному значению, а оставшимися компонентами, равными единице. Значение по умолчанию равно единице. Общее количество карт функций представляет собой произведение компонентов кортежа. Разложение этого общего количества по компонентам определяет, каким образом группируются значения карт функций в узлах назначения.

  • Weights (необязательный) определяет исходные веса для пакета. Значение должно быть кортежем значений с плавающей запятой, длина которых представляет собой количество ядер, умноженное на количество весов на ядро, как указано ниже в этой статье. Веса по умолчанию генерируются случайно.

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

  • Padding (необязательно): определяет, должен ли вход заполняться с использованием схемы заполнения по умолчанию. Значение может быть одним логическим значением или кортежем логических значений, длина которых представляет собой арность пакета.

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

    Если измерение имеет значение True, источник логически заполняется в этом измерении ячейками с нулевыми значениями для поддержки дополнительных приложений ядра таким образом, чтобы центральные узлы первого и последнего ядер в этом измерении представляли собой первый и последний узел в этом измерении слоя источника. Таким образом, число пустых узлов в каждом измерении определяется автоматически, чтобы точно соответствовать ядрам (InputShape[d] - 1) / Stride[d] + 1 в заполненном слое источника.

    Если измерение имеет значение False, ядра определяются таким образом, чтобы количество оставшихся узлов на каждой стороне было одинаковым (до разницы в 1). Значение по умолчанию этого атрибута: кортеж со всеми компонентами, равными False.

  • UpperPad и LowerPad (необязательно): позволяют более тонко управлять объемом заполнения. Важно! Эти атрибуты могут задаваться тогда и только тогда, когда свойство Padding выше не задается. Значения должны быть кортежами с целыми значениями, длина которых представляет собой арность пакета. При задании этих атрибутов «пустые» узлы добавляются к нижнему и верхнему концам каждого измерения входного слоя. Число узлов, добавленных к нижнему и верхнему концам в каждом измерении, определяется атрибутами LowerPad[i] и UpperPad[i] соответственно.

    Чтобы обеспечить соответствие количества ядер только количеству «реальных», а не «пустых» узлов, должны выполняться следующие условия.

    • Каждый компонент атрибута LowerPad должен быть строго меньше, чем KernelShape[d]/2.

    • Каждый компонент атрибута UpperPad должен быть не больше, чем KernelShape[d]/2.

    • Значение по умолчанию этих атрибутов: кортеж со всеми компонентами, равными 0.

      Значение Padding = true позволяет осуществить заполнение, необходимое для сохранения центра ядра в пределах реального входа. Поэтому формула для вычисления выходного размера немного изменяется. Обычно выходной размер D вычисляется как D = (I - K) / S + 1, где I — входной размер, K — размер ядра, S — шаг и / — деление целого числа (с округлением до нуля). Если задать значение UpperPad = [1, 1], входной размер I будет равен 29, следовательно, D = (29 - 5) / 2 + 1 = 13. Но, если Padding = true, тогда I фактически вытесняется K - 1. Следовательно: D = ((28 + 4) - 5) / 2 + 1 = 27 / 2 + 1 = 13 + 1 = 14. Присвоив значения параметрам UpperPad и LowerPad, вы сможете более точно управлять заполнением, чем это позволяет сделать определение только одного параметра Padding = true.

Дополнительную информацию о сверточных сетях и их приложениях см. в следующих статьях:

Группирующие пакеты

Группирующий пакет применяет геометрию, аналогичную сверточному подключению, но использует предопределенные функции для значений узла источника, чтобы извлечь значение узла назначения. Следовательно, группирующие пакеты не имеют обучаемого состояния (весов или смещений). Группирующие пакеты поддерживают все сверточные атрибуты, кроме Sharing, MapCount и Weights.

Как правило, ядра, суммированные соседними группирующими модулями, не перекрываются. Если Stride[d] равен KernelShape[d] в каждом измерении, то полученный слой представляет собой традиционный локальный группирующий слой, который обычно используется в сверточных нейронных сетях. Каждый узел назначения вычисляет максимальное или среднее значение действий своего ядра в слое источника.

В следующем примере проиллюстрирован группирующий пакет:

hidden P1 [5, 12, 12]
  from C1 max pool {
  InputShape  = [ 5, 24, 24];
   KernelShape = [ 1,  2,  2];
   Stride      = [ 1,  2,  2];
  }
  • Арность пакета равна 3 (длина кортежей InputShape, KernelShape и Stride).
  • Количество узлов в слое источника: 5 * 24 * 24 = 2880.
  • Это стандартный локальный группирующий слой, так как KernelShape = Stride.
  • Количество узлов в слое назначения: 5 * 12 * 12 = 1440.

Дополнительную информацию о группирующих слоях см. в статьях:

Пакеты нормализации ответов

Нормализация ответов — это локальная схема нормализации, которая впервые была предложена Джеффри Хинтоном (Geoffrey Hinton) и др. в статье ImageNet Classification with Deep Convolutional Neural Networks (Классификация ImageNet с помощью глубоких сверточных нейронных сетей).

Нормализация ответов используется для облегчения обобщения в нейронных сетях. Когда один нейрон срабатывает при очень высоком уровне активации, локальный слой нормализации ответа подавляет уровень активации окружающих нейронов. Это выполняется с помощью трех параметров (α, β и k) и сверточной структуры (или формы окрестности). Каждый нейрон в слое назначения y соответствует нейрону x в слое источника. Уровень активации y задается следующей формулой, где f — уровень активации нейрона, Nx — ядро (или набор, содержащий нейроны в окрестности x), как определяется сверточной структурой:

формула сверточной структуры

Пакеты нормализации ответов поддерживают все сверточные атрибуты, кроме Sharing, MapCount и Weights.

  • Если ядро содержит нейроны в той же карте, что и x, схема нормализации называется нормализацией в той же карте. Чтобы определить нормализацию в той же карте, первая координата в InputShape должна иметь значение 1.

  • Если ядро содержит нейроны в той же пространственной позиции, что и x, но нейроны находятся в других картах, схема нормализации называется нормализацией между картами. Этот тип нормализации ответа реализует форму латерального торможения, похожую на форму, найденную у реальных нейронов, создавая конкуренцию за большие уровни активации среди выходов нейронов, вычисленных на различных картах. Чтобы задать межкарточную нормализацию, первая координата должна быть целым числом (больше единицы и не больше количества карт), а остальные координаты должны иметь значения, равные 1.

Так как пакеты нормализации ответов применяют предопределенную функцию к значениям узла источника для определения значения узла назначения, они не имеют обучаемого состояния (веса или смещения)

Примечание.

Узлы в слое назначения соответствуют нейронам, которые представляют центральные узлы ядер. Например, если KernelShape[d] имеет нечетное значение, KernelShape[d]/2 соответствует центральному узлу ядра. Если значение KernelShape[d] четное, центральный узел находится в KernelShape[d]/2 - 1. Таким образом, если для параметра Padding[d] задано значение False, первый и последний узлы KernelShape[d]/2 не имеют соответствующих узлов в слое назначения. Чтобы исключить эту ситуацию, определите атрибут Padding как [true, true, …, true].

В дополнение к четырем атрибутам, описанным выше, пакеты нормализации ответов также поддерживают следующие атрибуты.

  • Alpha (обязательный): определяет значение с плавающей запятой, соответствующее α в указанной выше формуле.
  • Beta (обязательный): определяет значение с плавающей запятой, соответствующее β в указанной выше формуле.
  • Offset (необязательный): определяет значение с плавающей запятой, соответствующее k в указанной выше формуле. Его значение по умолчанию равно 1.

В следующем примере определяется пакет нормализации ответов с использованием этих атрибутов:

hidden RN1 [5, 10, 10]
from P1 response norm {
  InputShape  = [ 5, 12, 12];
  KernelShape = [ 1,  3,  3];
  Alpha = 0.001;
  Beta = 0.75;
  }
  • Слой источника содержит пять карт, каждая размером 12 x 12, и в общей сложности насчитывает 1440 узлов.
  • Значение KernelShape указывает, что это та же карта слоя нормализации, в которой окрестность представлена прямоугольником 3 x 3.
  • По умолчанию атрибут Padding имеет значение False, следовательно, у слоя назначения в каждом измерении буде только 10 узлов. Чтобы включить один узел в слое назначения, соответствующий каждому узлу в слое источника, добавьте Padding = [true, true, true] и измените размер RN1 на [5, 12, 12].

Объявление общего доступа

Net# дополнительно поддерживает определение нескольких пакетов с общими весами. Веса любых двух пакетов могут быть общими, если их структуры одинаковы. Далее описывается синтаксис определения пакетов с общими весами:

share-declaration:
  share    {    layer-list    }
  share    {    bundle-list    }
  share    {    bias-list    }

  layer-list:
    layer-name    ,    layer-name
    layer-list    ,    layer-name

  bundle-list:
    bundle-spec    ,    bundle-spec
    bundle-list    ,    bundle-spec

  bundle-spec:
    layer-name    =>     layer-name

  bias-list:
    bias-spec    ,    bias-spec
    bias-list    ,    bias-spec

  bias-spec:
    1    =>    layer-name

  layer-name:
    identifier

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

Const {
  InputSize = 37;
  HiddenSize = 50;
  }
input {
  Data1 [InputSize];
  Data2 [InputSize];
  }
hidden {
  H1 [HiddenSize] from Data1 all;
  H2 [HiddenSize] from Data2 all;
  }
output Result [2] {
  from H1 all;
  from H2 all;
  }
share { H1, H2 } // share both weights and biases
  • Входные функции разделяются на два входных слоя одинаковых размеров.
  • Скрытые слои далее вычисляют функции более высокого уровня на двух входных слоях.
  • Объявление общего доступа определяет, что H1 и H2 должны вычисляться одинаково из соответствующих входов.

В качестве альтернативы это можно задать с помощью двух отдельных объявлений общего доступа следующим образом:

share { Data1 => H1, Data2 => H2 } // share weights
<!-- -->
    share { 1 => H1, 1 => H2 } // share biases

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

Примеры использования Net#

В этом разделе приводится несколько примеров использования Net# для добавления скрытых слоев, определения способов взаимодействия скрытых слоев с другими слоями и построения сверточных сетей.

Определение простой настраиваемой нейронной сети: пример «Привет, мир!»

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

input Data auto;
hidden H [200] from Data all;
output Out [10] sigmoid from H all;

В примере проиллюстрированы некоторые базовые команды и их порядок.

  • В первой строке определяется входной слой (под названием Data). При использовании ключевого слова auto в нейронную сеть автоматически включаются все столбцы компонентов в примерах ввода.
  • Вторая строка создает скрытый слой. Имя H назначается скрытому слою, который содержит 200 узлов. Этот слой полностью подключен ко входному слою.
  • Третья строка определяет выходной слой (под названием Out), который содержит 10 выходных узлов. Для классификации нейронных сетей используется по одному выходному узлу на класс. Ключевое слово sigmoid указывает выходную функцию, примененную к выходному слою.

Определение нескольких скрытых слоев: пример машинного зрения

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

// Define the input layers
input Pixels [10, 20];
input MetaData [7];

// Define the first two hidden layers, using data only from the Pixels input
hidden ByRow [10, 12] from Pixels where (s,d) => s[0] == d[0];
hidden ByCol [5, 20] from Pixels where (s,d) => abs(s[1] - d[1]) <= 1;

// Define the third hidden layer, which uses as source the hidden layers ByRow and ByCol
hidden Gather [100]
{
from ByRow all;
from ByCol all;
}

// Define the output layer and its sources
output Result [10]
{
from Gather all;
from MetaData all;
}

В примере проиллюстрировано несколько признаков языка спецификаций нейронных сетей

  • В структуре два входных слоя: Pixels и MetaData.
  • Слой Pixels — это слой источника для двух пакетов подключений со слоями назначения: ByRow и ByCol.
  • Слои Gather и Result — это слои назначения в нескольких пакетах подключений.
  • Выходной слой Result — это слой назначения в двух пакетах подключений. Один содержит скрытый слой второго уровня Gather в качестве слоя назначения, а другой — входной слой MetaData в качестве слоя назначения.
  • Скрытые слои ByRow и ByCol определяют отфильтрованные подключения с использованием выражений предиката. Точнее, узел в ByRow с координатами [x, y] подключается к тем узлам в Pixels, у которых первая координата индекса равна первой координате узла (x). Аналогично узел в ByCol с координатами [x, y] подключается к тем узлам в Pixels, у которых вторая координата индекса находится в пределах единицы от второй координаты узла (у).

Определение сверточной сети для многоклассовой классификации: пример распознавания цифр

Определение следующей сети, разработанной для распознавания цифр, показывает некоторые усовершенствованные методы настройки нейронных сетей.

input Image [29, 29];
hidden Conv1 [5, 13, 13] from Image convolve
  {
  InputShape  = [29, 29];
  KernelShape = [ 5,  5];
  Stride      = [ 2,  2];
  MapCount    = 5;
  }
hidden Conv2 [50, 5, 5]
from Conv1 convolve
  {
  InputShape  = [ 5, 13, 13];
  KernelShape = [ 1,  5,  5];
  Stride      = [ 1,  2,  2];
  Sharing     = [false, true, true];
  MapCount    = 10;
  }
hidden Hid3 [100] from Conv2 all;
output Digit [10] from Hid3 all;
  • В структуре один входной слой Image.

  • Ключевое слово convolve указывает, что Conv1 и Conv2 — это сверточные слои. За объявлением каждого из этих слоев следует список атрибутов свертки.

  • В сети есть третий скрытый слой Hid3, который полностью подключен ко второму скрытому слою Conv2.

  • Выходной слой Digit подключен только к третьему скрытому слою Hid3. Ключевое слово all указывает, что выходной слой полностью подключен к Hid3.

  • Количество аргументов свертки: три (длина кортежей InputShape, KernelShape, Stride и Sharing).

  • Число весов на ядро: 1 + KernelShape\[0] * KernelShape\[1] * KernelShape\[2] = 1 + 1 * 5 * 5 = 26 или 26 * 50 = 1300.

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

    NodeCount\[0] = (5 - 1) / 1 + 1 = 5 NodeCount\[1] = (13 - 5) / 2 + 1 = 5 NodeCount\[2] = (13 - 5) / 2 + 1 = 5

  • Общее количество узлов можно определить, используя объявленную размерность слоя [50, 5, 5]: MapCount * NodeCount\[0] * NodeCount\[1] * NodeCount\[2] = 10 * 5 * 5 * 5.

  • Так как Sharing[d] имеет значение False только для d == 0, число ядер равно MapCount * NodeCount\[0] = 10 * 5 = 50.

Благодарности

Язык Net# для изменения архитектуры нейронных сетей был разработан в корпорации Майкрософт Шоном Катценбергером Shon Katzenberger (архитектор, машинное обучение) и Алексеем Каменевым (разработчик программного обеспечения, Microsoft Research). Он используется внутри компании для проектов машинного обучения и различных приложений от приложений распознавания образов до приложений анализа текста. Дополнительные сведения см. в статье Нейронные сети в Студии машинного обучения. Введение в Net#.