Играюсь с нейронными сетями. Свёрточными. Но не на всяких там Tensor Flow, а на С++. Со всей математикой с нуля. Та ещё задачка найти вменяемые описания того же обратного распространения в свёрточном слое. Но самое-то весёлое не это. Самое весёлое, это выполнение свёрток на GPU через матричное умножение. Почему через умножение? Потому что эта операция очень хорошо оптимизируется именно для GPU (блок 16x16 кладётся в кэш, общий для всех нитей блока и делается каждой нитью сложение с умножением кусочка). GPU я мучаю через мою любимую CUDA. Так вот, свёртка и обратная свёртка через умножение матриц делается вот так:
Но кроме свёрток ещё нужно обновлять коэффициенты ядер. А это делается уже так:
Только не надо строить эти матрицы заранее. Их легко можно (и нужно!) строить прямо «на лету». Сэкономите дофига памяти GPU.
А как эту свёртку применять в нейронке? А вот так:
Здесь вверху показан прямой проход по сети (Image сворачивается с ядрами Kernel и получается тензор свёртки, с глубиной равной количеству ядер).
В середине показан процесс вычисления поправок к элементам ядер, зная ошибку (Delta).
Ну а внизу показан процесс вычисления ошибок при обратном проходе через свёрточный слой. Тут Delta предыдущего слоя сворачивается с повернутыми на 180 ядрами.
Загрузка GPU у меня сейчас почти 100% на больших свёртках (и температура GPU тоже не маленькая). Скорость вычислений тоже приличная. Но, думаю, Tensor Flow всё же будет быстрее - я не слишком оптимизировал доступ к элементам тензоров.