Продолжаем вопрос №2:
Итак, R, G и B-матрицы изначально идут каждая своим путем обработки, у каждого канала свой набор сверточных ядер. (Кстати, более того, на каждой операции свертки могут быть разветвления - одно и то же входное изображение подвергается свертке с разными ядрами. В пулинге разветвлений нет: сколько веток пришло от сверточного слоя, столько веток и выходит из слоя пулинга. На последующем сверточном слое вновь разветвление, при чем надо понимать, что разветвляются разветвления, то есть итоговое количество веток равно
, где
и
- это количество разветвлений на первом и втором сверточных слоях соответственно. В каждой ветке - матрица. И все это умножить на 3 - число цветовых каналов.)
Как только сверточно-пулинговые слои закончились, нужно все матрицы векторизовать или сплющить (flatten), то есть выстроить элементы в ряд (вектор). Все вектора склеить в один большой вектор. Это и будет входом в полносвязный слой. Порядок векторизации не важен, так как полносвязный слой ИЗНАЧАЛЬНО симметричен по отношению к входным признакам и никак не учитывает их взаимный порядок. Главное чтобы порядок векторизации в процессе обучения и эксплуатации не изменялся.
P.S. В некоторых случаях удается обойтись без полносвязного слоя, такие сверточные сети называют nonFC (non-full-connection-layer) или как-то так. Это когда в последнем слое получаются маленькие матрицы типа 5х5, 4х4 или 3х3 - к ним применяется свертка (без ReLU и пулинга!), на выходе которой матрица-число 1х1 - выход всей сети (ответ). Например, классическая CNN LeNet-1 относится к такому типу сетей.
-- 14.12.2018, 06:49 --Кстати говоря, при написании кода изначально матрицы в каждом слое всех трех цветовых каналов можно рассматривать как один большой одномерный массив и проходиться по нему с помощью нескольких указателей (у каждой матрицы свой указатель) и тогда никакой специальной операции flatten делать не придется. Это ускорит алгоритм.