<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cga</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cga"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Cga"/>
		<updated>2026-05-19T14:44:06Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80553</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80553"/>
				<updated>2021-01-24T18:29:05Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Inception module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На [https://arxiv.org/abs/1603.07285 Рисунке 1] можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на [https://arxiv.org/abs/1409.4842 рисунке 5]. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|center|700px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80552</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80552"/>
				<updated>2021-01-24T18:28:22Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Свертка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На [https://arxiv.org/abs/1603.07285 Рисунке 1] можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на рисунке 5. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|center|700px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80551</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80551"/>
				<updated>2021-01-24T18:27:22Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Inception module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На Рисунке 1 можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на рисунке 5. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|center|700px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80550</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80550"/>
				<updated>2021-01-24T18:26:47Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Свертка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На Рисунке 1 можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|center|700px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80302</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80302"/>
				<updated>2021-01-23T12:48:43Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|center|700px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80301</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80301"/>
				<updated>2021-01-23T12:48:29Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|center|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80300</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80300"/>
				<updated>2021-01-23T12:46:13Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;div class=&amp;quot;tleft&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|centre|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80299</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80299"/>
				<updated>2021-01-23T12:45:59Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;div class=&amp;quot;tleft&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|center|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80298</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80298"/>
				<updated>2021-01-23T12:45:32Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;div class=&amp;quot;tleft&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80296</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80296"/>
				<updated>2021-01-23T12:40:58Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;div class=&amp;quot;tleft&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80295</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80295"/>
				<updated>2021-01-23T12:40:39Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;div class=&amp;quot;tleft&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png [https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80294</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80294"/>
				<updated>2021-01-23T12:40:04Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;div class=&amp;quot;tleft&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |border|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80293</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80293"/>
				<updated>2021-01-23T12:35:31Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |border|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80292</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80292"/>
				<updated>2021-01-23T12:35:07Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |border|1500px|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80291</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80291"/>
				<updated>2021-01-23T12:34:55Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |border|1400px|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80290</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80290"/>
				<updated>2021-01-23T12:34:43Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |border|1300px|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80289</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80289"/>
				<updated>2021-01-23T12:34:26Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |border|1000px|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80288</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80288"/>
				<updated>2021-01-23T12:34:02Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
[[Файл:Net-comparison.png |border|700px|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80287</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80287"/>
				<updated>2021-01-23T12:27:35Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |border|700px|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80286</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80286"/>
				<updated>2021-01-23T12:26:44Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |border|700px|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80285</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80285"/>
				<updated>2021-01-23T12:25:42Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80284</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80284"/>
				<updated>2021-01-23T12:25:21Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] Сравнение известных нейронных сетей]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80282</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=80282"/>
				<updated>2021-01-23T12:24:45Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png |thumb|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.]]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79418</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79418"/>
				<updated>2021-01-20T20:20:01Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79417</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79417"/>
				<updated>2021-01-20T20:19:45Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|100px Рисунок 11.]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79415</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79415"/>
				<updated>2021-01-20T20:19:35Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px Рисунок 11.]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79413</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79413"/>
				<updated>2021-01-20T20:18:53Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79411</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79411"/>
				<updated>2021-01-20T20:18:13Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px Рисунок 11.]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79407</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79407"/>
				<updated>2021-01-20T20:16:04Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сравнение известных нейронных сетей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px] Рисунок 11.]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79404</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79404"/>
				<updated>2021-01-20T20:15:27Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* AlexNet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Рисунок 10.]Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79402</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79402"/>
				<updated>2021-01-20T20:15:02Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* LeNet-5 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Рисунок 9.]Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Архитектура AlexNet]]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79399</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79399"/>
				<updated>2021-01-20T20:14:18Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Расширенная свертка (aнгл. Dilated convolution) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|Рисунок 8. 1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Архитектура LeNet-5]]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Архитектура AlexNet]]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79398</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79398"/>
				<updated>2021-01-20T20:13:27Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Residual block */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Рисунок 7.]Устройство residual block]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Архитектура LeNet-5]]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Архитектура AlexNet]]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79397</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79397"/>
				<updated>2021-01-20T20:12:59Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Inception module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Рисунок 5.]Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Рисунок 6.]Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Устройство residual block]]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Архитектура LeNet-5]]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Архитектура AlexNet]]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79396</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79396"/>
				<updated>2021-01-20T20:12:17Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Пулинговый слой */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Рисунок 4.] Пример операции пулинга с функцией максимума]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Inception module]]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Inception module с сокращением размерностей]]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Устройство residual block]]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Архитектура LeNet-5]]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Архитектура AlexNet]]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79394</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79394"/>
				<updated>2021-01-20T20:11:22Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Сверточный слой */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 2.]Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Рисунок 3.]Пример свертки с трехмерным ядром]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Пример операции пулинга с функцией максимума]]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Inception module]]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Inception module с сокращением размерностей]]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Устройство residual block]]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Архитектура LeNet-5]]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Архитектура AlexNet]]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79391</id>
		<title>Сверточные нейронные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=79391"/>
				<updated>2021-01-20T20:10:14Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Свертка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref name=LeNet5&amp;gt;[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Yann LeCun — Gradient-Based Learning Applied to Document Recognition, 1998]&amp;lt;/ref&amp;gt;, изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Рисунок 1.]Пример свертки двух матриц размера 5x5 и 3x3]]&lt;br /&gt;
'''Свертка''' (англ. ''convolution'') {{---}} операция над парой матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;n_x\times n_y&amp;lt;/math&amp;gt;) и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (размера &amp;lt;math&amp;gt;m_x \times m_y&amp;lt;/math&amp;gt;), результатом которой является матрица &amp;lt;math&amp;gt;C = A * B&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;(n_x-m_x+1)\times (n_y-m_y+1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Каждый элемент результата вычисляется как скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и некоторой подматрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; такого же размера (подматрица определяется положением элемента в результате).&lt;br /&gt;
То есть, &amp;lt;math&amp;gt;C_{i,j} = \sum_{u = 0}^{m_x-1}\sum_{v = 0}^{m_y - 1}A_{i+u,j+v}B_{u,v}&amp;lt;/math&amp;gt;. На изображении справа можно видеть, как матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; «двигается» по матрице &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, и в каждом положении считается скалярное произведение матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и той части матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, на которую она сейчас наложена. Получившееся число записывается в соответствующий элемент результата.&lt;br /&gt;
&lt;br /&gt;
Логический смысл свертки такой {{---}} чем больше величина элемента свертки, тем больше эта часть матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; была похожа на матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (похожа в смысле скалярного произведения). Поэтому матрицу &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; называют ''изображением'', а матрицу &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; {{---}} ''фильтром'' или ''образцом''.&lt;br /&gt;
&lt;br /&gt;
== Структура сверточной нейронной сети ==&lt;br /&gt;
В сверточной нейронной сети выходы промежуточных слоев образуют матрицу (изображение) или набор матриц (несколько слоёв изображения). Так, например, на вход сверточной нейронной сети можно подавать три слоя изображения (R-, G-, B-каналы изображения). Основными видами слоев в сверточной нейронной сети являются сверточные слои (англ. ''convolutional layer''), пулинговые слои (англ. ''pooling layer'') и [[:Нейронные_сети,_перцептрон|полносвязные слои]] (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|[https://arxiv.org/abs/1603.07285 Пример свертки двух матриц с дополнением нулями и сдвигом 2]]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|[http://www.machinelearning.ru/wiki/images/1/1b/DL16_lecture_3.pdf Пример свертки с трехмерным ядром]]]&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. ''bias''). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
* В одном сверточном слое может быть несколько сверток. В этом случае для каждой свертки на выходе получится своё изображение. Например, если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а в слое было &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сверток с ядром размерности &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;n\times(w - k_x + 1)\times(h - k_y + 1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Ядра свертки могут быть трёхмерными. Свертка трехмерного входа с трехмерным ядром происходит аналогично, просто скалярное произведение считается еще и по всем слоям изображения. Например, для усреднения информации о цветах исходного изображения, на первом слое можно использовать свертку размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх);&lt;br /&gt;
&lt;br /&gt;
* Можно заметить, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения участвуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. ''padding''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения. Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution''). Среди способов, которыми можно заполнить новые пиксели, можно выделить следующие:&lt;br /&gt;
** ''zero shift'': &amp;lt;code&amp;gt;00[ABC]00&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''border extension'': &amp;lt;code&amp;gt;AA[ABC]CC&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''mirror shift'': &amp;lt;code&amp;gt;BA[ABC]CB&amp;lt;/code&amp;gt;;&lt;br /&gt;
** ''cyclic shift'': &amp;lt;code&amp;gt;BC[ABC]AB&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Еще одним параметром сверточного слоя является ''сдвиг'' (англ. ''stride''). Хоть обычно свертка применяется подряд для каждого пикселя, иногда используется сдвиг, отличный от единицы {{---}} скалярное произведение считается не со всеми возможными положениями ядра, а только с положениями, кратными некоторому сдвигу &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Тогда, если если вход имел размерность &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt;, а ядро свертки имело размерность &amp;lt;math&amp;gt;k_x\times k_y&amp;lt;/math&amp;gt; и использовался сдвиг &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;, то выход будет иметь размерность &amp;lt;math&amp;gt;\lfloor\frac{w - k_x}{s} + 1\rfloor\times\lfloor\frac{h - k_y}{s} + 1\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Пулинговый слой ===&lt;br /&gt;
[[Файл:Maxpool.jpeg|upright=1.0|thumb|[https://www.slideshare.net/YUNGKUEICHEN/convolutional-neural-network-cnn-image-recognition Пример операции пулинга с функцией максимума]]]&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция. Чаще всего используется функция максимума (англ. ''max pooling'') или (взвешенного) среднего (англ. ''(weighted) average pooling''). Обучаемых параметров у этого слоя нет. Основные цели пулингового слоя:&lt;br /&gt;
* уменьшение изображения, чтобы последующие свертки оперировали над большей областью исходного изображения;&lt;br /&gt;
* увеличение инвариантности выхода сети по отношению к малому переносу входа;&lt;br /&gt;
* ускорение вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Inception module ===&lt;br /&gt;
[[Файл:Inception.png|upright=1.0|thumb|[https://arxiv.org/abs/1409.4842 Inception module]]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|[https://arxiv.org/pdf/1409.4842.pdf Inception module с сокращением размерностей]]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref name=GoogLeNet&amp;gt;[https://arxiv.org/pdf/1409.4842.pdf Going deeper with convolutions]&amp;lt;/ref&amp;gt;, в которой была представлена сеть GoogLeNet. Основная цель этого модуля заключается в следующем. Авторы предположили, что каждый элемент предыдущего слоя соответствует определенной области исходного изображения. Каждая свертка по таким элементам будет увеличивать область исходного изображения, пока элементы на последних слоях не будут соответствовать всему изображению целиком. Однако, если с какого-то момента все свертки станут размером &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, то не найдется элементов, которые покрывали бы все исходное изображение, поэтому было бы невозможно находить большие признаки на изображении. Чтобы решить эту проблему, авторы предложили так называемый inception module {{---}} конкатенацию выходов для сверток размера &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;5\times 5&amp;lt;/math&amp;gt;, а также операции max pooling'а с ядром &amp;lt;math&amp;gt;3\times 3&amp;lt;/math&amp;gt;. К сожалению, подобный наивный подход (англ. ''naive inception module'') приводит к резкому увеличению слоев изображения, что не позволяет построить с его использованием глубокую нейронную сеть. Для этого авторы предложили использовать модифицированный inception module с дополнительным уменьшением размерности {{---}} дополнительно к каждому фильтру они добавили слой свертки &amp;lt;math&amp;gt;1\times 1&amp;lt;/math&amp;gt;, который схлопывает все слои изображения в один. Это позволяет сохранить малое число слоев, с сохранением полезной информации о изображении.&lt;br /&gt;
&lt;br /&gt;
=== Residual block ===&lt;br /&gt;
[[Файл:Residual.png|upright=1.0|thumb|[https://arxiv.org/pdf/1512.03385.pdf Устройство residual block]]]&lt;br /&gt;
Двумя серьезными проблемами в обучении глубоких нейронных сетей являются исчезающий градиент (англ. ''vanishing gradient'') и взрывающийся градиент (англ. ''exploding gradient''). Они возникают из-за того, что при дифференцировании по цепному правилу, до глубоких слоев нейронной сети доходит очень маленькая величина градиента (из-за многократного домножения на небольшие величины на предыдущих слоях). Для борьбы с этой проблемой был предложен так называемый ''residual block''&amp;lt;ref name=ResNet&amp;gt;[https://arxiv.org/pdf/1512.03385.pdf Deep residual learning for image recognition]&amp;lt;/ref&amp;gt;. Идея заключается в том, чтобы взять пару слоёв (например, сверточных), и добавить дополнительную связь, которая проходит мимо этих слоёв. Пусть &amp;lt;math&amp;gt;z^{(k)}&amp;lt;/math&amp;gt; {{---}} выход &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ого слоя до применения функции активации, а &amp;lt;math&amp;gt;a^{(k)}&amp;lt;/math&amp;gt; {{---}} выход после. Тогда residual block будет выполнять следующее преобразование: &amp;lt;math&amp;gt;a^{(k + 2)} = g(z^{(k + 2)} + a^{(k)})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; {{---}} функция активации.&lt;br /&gt;
&lt;br /&gt;
На самом деле, такая нейронная сеть обучается предсказывать функцию &amp;lt;math&amp;gt;\mathcal{F}(x) - x&amp;lt;/math&amp;gt;, вместо функции &amp;lt;math&amp;gt;\mathcal{F}(x)&amp;lt;/math&amp;gt;, которую изначально нужно было предсказывать. Для компенсации этой разницы и вводится это замыкающее соединение (англ. ''shortcut connection''), которое добавляет недостающий &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; к функции. Предположение авторов, которые предложили residual block, заключалось в том, что такую разностную функцию будет проще обучать, чем исходную. Если рассматривать крайние случаи, то если &amp;lt;math&amp;gt;\mathcal{F}(x) = x&amp;lt;/math&amp;gt;, такую сеть обучить нулю всегда возможно, в отличие от обучения множества нелинейных слоёв линейному преобразованию.&lt;br /&gt;
&lt;br /&gt;
== Другие виды сверток ==&lt;br /&gt;
&lt;br /&gt;
=== Расширенная свертка (aнгл. Dilated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Данная свертка похожа на пуллинг и свертку с шагом, но позволяет:&lt;br /&gt;
# Экспоненциально расширить рецептивное поле без потери качества изображения.&lt;br /&gt;
# Получить большее рецептивное поле при тех же затратах на вычисления и расходах памяти, при этом сохранив качество изображения.&lt;br /&gt;
&lt;br /&gt;
Формула свертки:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;O_{x, y} = \sum\limits_{i, j} W_{i,j} \sum\limits_{\substack{t, k \\ |t - i| &amp;lt; l \\ |k - j| &amp;lt; l}} I_{t, k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки, &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; {{---}} коэффициент расширения.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
 |-&lt;br /&gt;
 |[[Файл:Dilated_convolution.png|border|700px|thumb|left|1-, 2- и 4-расширенные свертки с классическими ядрами 3x3, 5x5 и 9x9 соответственно. Красные точки обозначают ненулевые веса, остальные веса ядра равны нулю. Выделенные синие области обозначают рецептивные поля.]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Частичная свертка (aнгл. Partial convolution) ===&lt;br /&gt;
&lt;br /&gt;
Частичная свертка позволяет работать с бинарной маской, дающей дополнительную информацию о входном изображении. Например, маска может указывать на испорченные пиксели в задаче [[Вписывание части изображения|вписывание части изображения]].&lt;br /&gt;
&lt;br /&gt;
Значения обновляются по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;x' = \begin{cases} W^T(X\odot M)\frac{sum(1)}{sum(M)}+b, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} бинарная маска; &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; {{---}} ядро свертки; &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}}  гиперпараметр&lt;br /&gt;
&lt;br /&gt;
Поэлементное перемножение &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; позволяет получить результат, зависящий только от значений с единичной маской, а &amp;lt;tex&amp;gt;\frac{sum(1)}{sum(M)}&amp;lt;/tex&amp;gt; служит для нормализации этого результата.&lt;br /&gt;
&lt;br /&gt;
Обновление маски происходит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;m' = \begin{cases} 1, &amp;amp; \mbox{if } sum(M)&amp;gt;0 \\ 0, &amp;amp; \mbox{otherwise} \end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из формулы, дополнительная информация, вносимая маской, постепенно затухает при переходе от слоя к слою. То есть со временем маска полностью заполняется единицами.&lt;br /&gt;
&lt;br /&gt;
=== Стробированная свертка (aнгл. Gated convolution) ===&lt;br /&gt;
&lt;br /&gt;
Главная особенность данной свертки {{---}} сохранение дополнительной информации об изображении во всех слоях (например, маски испорченных областей). &lt;br /&gt;
&lt;br /&gt;
В данном случае вместо того, чтобы работать с жесткой маской, которая обновляется по некоторым правилам, стробированная свертка учится автоматически извлекать маску из данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\begin{array}{rcl} Gating_{y,x} &amp;amp; = &amp;amp; \sum \sum W_1 \cdot I \\ Feature_{y,x} &amp;amp; = &amp;amp; \sum \sum W_2 \cdot I \\ O_{y,x} &amp;amp; = &amp;amp; \phi (Feature_{y,x}) \odot \sigma (Gating_{y,x}) \end{array}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;W_2&amp;lt;/tex&amp;gt;  {{---}} два разных ядра свертки, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; {{---}} входные данные, &amp;lt;tex&amp;gt;O&amp;lt;/tex&amp;gt; {{---}} выходные данные,  &amp;lt;tex&amp;gt;\phi&amp;lt;/tex&amp;gt; {{---}} функция активации, &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} сигмоидная функция, &amp;lt;tex&amp;gt;\odot&amp;lt;/tex&amp;gt; {{---}} поэлементное перемножение.&lt;br /&gt;
&lt;br /&gt;
Данная свертка учится динамическому отбору признаков для изображения и для каждой логической области маски, значительно улучшая качество выходных данных. &lt;br /&gt;
&lt;br /&gt;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|[http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf Архитектура LeNet-5]]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном&amp;lt;ref name=LeNet5/&amp;gt;, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Архитектура AlexNet]]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%&amp;lt;ref name=AlexNet&amp;gt;[https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf ImageNet Classification with Deep Convolutional Neural Networks]&amp;lt;/ref&amp;gt;. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19&amp;lt;ref name=VGG&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]&amp;lt;/ref&amp;gt;. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;br /&gt;
&lt;br /&gt;
=== GoogLeNet ===&lt;br /&gt;
Также известный как ''inception network'' {{---}} победитель соревнования ImageNet 2014-ого года, набравший 93.3% точности&amp;lt;ref name=GoogLeNet/&amp;gt;. Состоит в основном из inception модулей. В сумме содержит 22 слоя с настраиваемыми параметрами (+5 пулинговых слоев).&lt;br /&gt;
&lt;br /&gt;
=== ResNet ===&lt;br /&gt;
Победитель соревнования ImageNet 2015-ого года. Сеть-победитель содержала более 150 слоёв&amp;lt;ref name=ResNet/&amp;gt; и набрала 96.43% точности.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение известных нейронных сетей ===&lt;br /&gt;
[[Файл:Net-comparison.png|border|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Примеры кода ==&lt;br /&gt;
===Scala===&lt;br /&gt;
Пример кода с библиотекой DeepLearning.scala&amp;lt;ref&amp;gt;[https://deeplearning.thoughtworks.school/index.html DeepLearning.scala]&amp;lt;/ref&amp;gt;&lt;br /&gt;
    // Загрузка датасета&lt;br /&gt;
    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
    // Определение слоёв&lt;br /&gt;
    def myNeuralNetwork(input: INDArray):  INDArrayLayer = {&lt;br /&gt;
        val cnnLayer = maxPool(relu(conv2d(input.reshape(input.shape()(0), Cifar10.NumberOfChannels, PixelHeight, PixelWidth), cnnWeight, cnnBias, (KernelHeight, KernelWidth), (Stride, Stride), (Padding, Padding))), (PoolSize, PoolSize))&lt;br /&gt;
        val affineRuleOfCnnLayer = relu(affine(cnnLayer.reshape(input.shape()(0), NumFilters * (PixelHeight / PoolSize) * (PixelWidth / PoolSize)), affineWeight, affineBias))&lt;br /&gt;
        val affineOfaffineRuleOfCnnLayer = affine(affineRuleOfCnnLayer.reshape(input.shape()(0), HiddenDim), affineLastWeight, affineLastBias)&lt;br /&gt;
        val softmaxValue = softmax(affineOfaffineRuleOfCnnLayer)&lt;br /&gt;
        softmaxValue&lt;br /&gt;
    }&lt;br /&gt;
    // Определение функции потерь&lt;br /&gt;
    def lossFunction(input: INDArray, expectOutput: INDArray): DoubleLayer = { &lt;br /&gt;
        val probabilities = myNeuralNetwork(input)&lt;br /&gt;
        -(hyperparameters.log(probabilities) * expectOutput).mean   &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    class Trainer(batchSize: Int, numberOfEpoches: Int = 5) {&lt;br /&gt;
        import scalaz.std.anyVal._&lt;br /&gt;
        import scalaz.syntax.all._&lt;br /&gt;
        @volatile&lt;br /&gt;
        private var isShuttingDown: Boolean = false&lt;br /&gt;
        private val lossBuffer = scala.collection.mutable.Buffer.empty[Double]&lt;br /&gt;
        def plotLoss(): Unit = Seq(Scatter(lossBuffer.indices, lossBuffer)).plot(title = &amp;quot;loss by time&amp;quot;)&lt;br /&gt;
        def interrupt(): Unit = isShuttingDown = true&lt;br /&gt;
        def startTrain(): Unit = {&lt;br /&gt;
            @monadic[Future]&lt;br /&gt;
            def trainTask: Future[Unit] = {&lt;br /&gt;
                isShuttingDown = false&lt;br /&gt;
                var epoch = 0&lt;br /&gt;
            &lt;br /&gt;
                while (epoch &amp;lt; numberOfEpoches &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                    val cifar10 = Cifar10.load().blockingAwait&lt;br /&gt;
                    val iterator = cifar10.epoch(batchSize).zipWithIndex&lt;br /&gt;
                    while (iterator.hasNext &amp;amp;&amp;amp; !isShuttingDown) {&lt;br /&gt;
                        val (Cifar10.Batch(labels, batch), i) = iterator.next()&lt;br /&gt;
                        val loss = lossFunction(batch, labels).train.each&lt;br /&gt;
                        lossBuffer += loss&lt;br /&gt;
                        hyperparameters.logger.info(s&amp;quot;epoch=epoch iteration=i batchSize=batchSize loss=loss&amp;quot;)&lt;br /&gt;
                    }&lt;br /&gt;
                    epoch += 1&lt;br /&gt;
                }&lt;br /&gt;
                hyperparameters.logger.info(&amp;quot;Done&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            trainTask.onComplete { tryUnit: scala.util.Try[Unit] =&amp;gt; tryUnit.get }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]&lt;br /&gt;
*[[:Рекуррентные нейронные сети|Рекуррентные нейронные сети]]&lt;br /&gt;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25 Understanding 2D Dilated Convolution Operation with Examples in Numpy and Tensorflow with Interactive Code, Towards Data Science]&lt;br /&gt;
* [https://arxiv.org/pdf/1806.03589v2.pdf Free-Form Image Inpainting with Gated Convolution, Jiahui Yu, Zhe Lin, Jimei Yang, Xiaohui Shen, Xin Lu, Thomas Huang]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79191</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79191"/>
				<updated>2021-01-20T15:59:20Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Garch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент, применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенности, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая {{---}} это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1.] Кросс-валидация временного ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2.] Набор данных описывающий график производства электрооборудования]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3.] Сезонные колебания]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4.] Наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5.] Cезонно-наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности $T$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE-модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие $T$ шагов совпадают с предыдущими $T$ шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6.] Методы разложения ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона.&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7.] Сезонные индексы ряда]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона;&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции;&lt;br /&gt;
* избежать лишнего сглаживания;&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8.] Декомпозиция и наивная модель]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает расчёты для 2007 года с использованием декомпозиции и наивной модели (рис. 8) для сезонно-изменяемого временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9.] Данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
где''''' $0&amp;lt;⍺&amp;lt;1$ '''''. Если $⍺ = 0$, то текущие наблюдения игнорируются, если же $⍺ = 1$, то полностью игнорируются предыдущие наблюдения.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10.] Данные полученные для 2007 года, с использованием модели экспоненциального сглаживания и декомпозиции]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны [https://otexts.com/fpp2/taxonomy.html здесь].&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года, с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] SARIMA]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ {{---}} свободный член (константа).&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ {{---}} параметры авторегрессии.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ {{---}} константа.&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ {{---}} параметры скользящего среднего.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12.] SARIMA декомпозированная]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Более подробную информацию про ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года, с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13.] ARMA]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (англ. Generalized AutoRegressive Conditional Heteroscedasticity, GARCH) предполагается, что слагаемое ошибки следует авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется (рис. 13).&lt;br /&gt;
&lt;br /&gt;
В 1982 году была предложена ARCH {{---}} модель, описываемая формулой: &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $\alpha$ {{---}} коэффициент задержки&amp;lt;br&amp;gt;&lt;br /&gt;
$\sigma^2(t)$ - волатильность&amp;lt;br&amp;gt;&lt;br /&gt;
$\sum_{i = 1}^{\alpha}b_ir^{2}_{t-1}$ - линенйная комбинация абсолютных значений нескольких последних изменений значений.&lt;br /&gt;
&lt;br /&gt;
Позднее была создана GARCH {{---}} обобщённая ARCH модель, которая также учитывает предыдущие оценки дисперсии. Формула может быть записана так:&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1} \sum_{i = 1}^{p}c_i\sigma^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где p {{---}} количество предшествующих оценок, влияющих на текущее значение.&amp;lt;br&amp;gt;&lt;br /&gt;
с {{---}} весовые коэффициенты предыдущих оценок.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh и различные варианты можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14.] DLM]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов (рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)$ ~ $N(0,W)$, $m(t)$ ~ $N(0,M)$, $r(t)$ ~ $N(0,R)$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15.] DLM]]&lt;br /&gt;
TBATS (англ. Trigonometric seasonality, Box-Cox transformation, ARMA errors, Trend and Seasonal components) {{---}} это модели, которые основаны на экспоненциальном сглаживании (рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на [[L 2-теория рядов Фурье|рядах Фурье]]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которое имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями (рис. 16). &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука ([https://facebook.github.io/prophet/ ссылка]).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16.] Prophet]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть разложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд,&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность,&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы, т.е аномальные данные,&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturing.png |left|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17.] NNETAR]]&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полносвязную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть]. &lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
Модель можно описать уравнением&lt;br /&gt;
$y_t = f(y_{t-1}) + \epsilon_t$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $y_{t-1} = (y_{t-1}, y_{t-2}, ...)'$ {{---}} вектор, содержащий запаздывающие значения, &amp;lt;br&amp;gt;&lt;br /&gt;
f {{---}} нейронная сеть, с 4 скрытыми узлами в каждом слое, &amp;lt;br&amp;gt;&lt;br /&gt;
$\epsilon_t$ {{---}} считаем, что ряд ошибок [https://ru.wikipedia.org/wiki/Гомоскедастичность гомокседастичен] (и возможно имеет нормальное распределение).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturingDecomposition.png |right|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18.] NNETAR c декомпозицией]]&lt;br /&gt;
&lt;br /&gt;
Мы можем моделировать будущие выборочные пути этой модели итеративно, случайным образом генерируя значение для $\epsilon_t$ либо из нормального распределения, либо путем повторной выборки из исторических значений.&amp;lt;br&amp;gt; Так что если&lt;br /&gt;
$\epsilon^*_{T+1}$&lt;br /&gt;
{{---}} случайная выборка из распределения ошибок в момент времени $T+1$,&amp;lt;br&amp;gt; тогда $y^*_{T+1} = f(y_T) + \epsilon^*_{T+1}$ {{---}} один из возможных вариантов распределения прогнозов для $y_{T+1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
Установив $y^*_{T+1} = (y^*_{T+1}, y_{T})'$, мы можем повторить процесс, чтобы получить $y^*_{T+2} = f(y_{T+1}) + \epsilon_{T+2}$. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы можем итеративно моделировать будущий путь выборки. Повторно моделируя выборочные пути, мы накапливаем знания о распределении всех будущих значений на основе подобранной нейронной сети.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов (как показано [https://arxiv.org/abs/1704.04110 здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 19.] MAE с перекрестной проверкой для каждой модели]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[Оценка качества в задачах классификации и регрессии|средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе (рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 20.] MAE, тестовый набор]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Методы увеличения производительности===&lt;br /&gt;
&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов,&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза),&lt;br /&gt;
*Агрегация начальных данных.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае необходимо обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Подробнее о глобальном подходе [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
*[http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
*[https://chaos.phys.msu.ru/loskutov/PDF/Lectures_time_series_analysis.pdf Лоскутов А.Ю. физ. фак. МГУ: Анализ Временных Рядов]&lt;br /&gt;
*[https://wiki.loginom.ru/articles/garch-model.html loginom: Garch-модель]&lt;br /&gt;
*[https://otexts.com/fpp2/nnetar.html Otexts: NNETAR]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79176</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79176"/>
				<updated>2021-01-20T15:39:53Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Источники Информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент, применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенности, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая {{---}} это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1.] Кросс-валидация временного ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2.] Набор данных описывающий график производства электрооборудования]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3.] Сезонные колебания]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4.] Наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5.] Cезонно-наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности $T$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE-модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие $T$ шагов совпадают с предыдущими $T$ шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6.] Методы разложения ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона.&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7.] Сезонные индексы ряда]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона;&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции;&lt;br /&gt;
* избежать лишнего сглаживания;&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8.] Декомпозиция и наивная модель]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает расчёты для 2007 года с использованием декомпозиции и наивной модели (рис. 8) для сезонно-изменяемого временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9.] Данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
где''''' $0&amp;lt;⍺&amp;lt;1$ '''''. Если $⍺ = 0$, то текущие наблюдения игнорируются, если же $⍺ = 1$, то полностью игнорируются предыдущие наблюдения.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10.] Данные полученные для 2007 года, с использованием модели экспоненциального сглаживания и декомпозиции]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны [https://otexts.com/fpp2/taxonomy.html здесь].&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года, с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] SARIMA]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ {{---}} свободный член (константа).&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ {{---}} параметры авторегрессии.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ {{---}} константа.&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ {{---}} параметры скользящего среднего.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12.] SARIMA декомпозированная]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Более подробную информацию про ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года, с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13.] ARMA]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (англ. Generalized AutoRegressive Conditional Heteroscedasticity, GARCH) предполагается, что слагаемое ошибки следует авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется (рис. 13).&lt;br /&gt;
&lt;br /&gt;
В 1982 году была предложена ARCH {{---}} модель, описываемая формулой: &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $\alpha$ {{---}} коэффициент задержки. ARCH модель моделирует волатильность в виде суммы базовой волатильности и линейной функции абсолютных значений нескольких последних изменений значений.&lt;br /&gt;
&lt;br /&gt;
Позднее была создана GARCH {{---}} обобщённая ARCH модель, которая также учитывает предыдущие оценки дисперсии. Формула может быть записана так:&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1} \sum_{i = 1}^{p}c_i\sigma^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где p {{---}} количество предшествующих оценок, влияющих на текущее значение.&amp;lt;br&amp;gt;&lt;br /&gt;
с {{---}} весовые коэффициенты предыдущих оценок.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh и различные варианты можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14.] DLM]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов (рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)$ ~ $N(0,W)$, $m(t)$ ~ $N(0,M)$, $r(t)$ ~ $N(0,R)$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15.] DLM]]&lt;br /&gt;
TBATS (англ. Trigonometric seasonality, Box-Cox transformation, ARMA errors, Trend and Seasonal components) {{---}} это модели, которые основаны на экспоненциальном сглаживании (рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на [[L 2-теория рядов Фурье|рядах Фурье]]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которое имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями (рис. 16). &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука ([https://facebook.github.io/prophet/ ссылка]).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16.] Prophet]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть разложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд,&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность,&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы, т.е аномальные данные,&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturing.png |left|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17.] NNETAR]]&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полносвязную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть]. &lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
Модель можно описать уравнением&lt;br /&gt;
$y_t = f(y_{t-1}) + \epsilon_t$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $y_{t-1} = (y_{t-1}, y_{t-2}, ...)'$ {{---}} вектор, содержащий запаздывающие значения, &amp;lt;br&amp;gt;&lt;br /&gt;
f {{---}} нейронная сеть, с 4 скрытыми узлами в каждом слое, &amp;lt;br&amp;gt;&lt;br /&gt;
$\epsilon_t$ {{---}} считаем, что ряд ошибок [https://ru.wikipedia.org/wiki/Гомоскедастичность гомокседастичен] (и возможно имеет нормальное распределение).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturingDecomposition.png |right|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18.] NNETAR c декомпозицией]]&lt;br /&gt;
&lt;br /&gt;
Мы можем моделировать будущие выборочные пути этой модели итеративно, случайным образом генерируя значение для $\epsilon_t$ либо из нормального распределения, либо путем повторной выборки из исторических значений.&amp;lt;br&amp;gt; Так что если&lt;br /&gt;
$\epsilon^*_{T+1}$&lt;br /&gt;
{{---}} случайная выборка из распределения ошибок в момент времени $T+1$,&amp;lt;br&amp;gt; тогда $y^*_{T+1} = f(y_T) + \epsilon^*_{T+1}$ {{---}} один из возможных вариантов распределения прогнозов для $y_{T+1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
Установив $y^*_{T+1} = (y^*_{T+1}, y_{T})'$, мы можем повторить процесс, чтобы получить $y^*_{T+2} = f(y_{T+1}) + \epsilon_{T+2}$. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы можем итеративно моделировать будущий путь выборки. Повторно моделируя выборочные пути, мы накапливаем знания о распределении всех будущих значений на основе подобранной нейронной сети.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов (как показано [https://arxiv.org/abs/1704.04110 здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 19.] MAE с перекрестной проверкой для каждой модели]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[Оценка качества в задачах классификации и регрессии|средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе (рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 20.] MAE, тестовый набор]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Методы увеличения производительности===&lt;br /&gt;
&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов,&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза),&lt;br /&gt;
*Агрегация начальных данных.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае необходимо обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Подробнее о глобальном подходе [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
*[http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
*[https://chaos.phys.msu.ru/loskutov/PDF/Lectures_time_series_analysis.pdf Лоскутов А.Ю. физ. фак. МГУ: Анализ Временных Рядов]&lt;br /&gt;
*[https://wiki.loginom.ru/articles/garch-model.html loginom: Garch-модель]&lt;br /&gt;
*[https://otexts.com/fpp2/nnetar.html Otexts: NNETAR]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79128</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79128"/>
				<updated>2021-01-20T14:39:33Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* NNETAR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент, применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенности, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая {{---}} это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1.] Кросс-валидация временного ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2.] Набор данных описывающий график производства электрооборудования]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3.] Сезонные колебания]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4.] Наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5.] Cезонно-наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности $T$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE-модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие $T$ шагов совпадают с предыдущими $T$ шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6.] Методы разложения ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона.&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7.] Сезонные индексы ряда]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона;&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции;&lt;br /&gt;
* избежать лишнего сглаживания;&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8.] Декомпозиция и наивная модель]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает расчёты для 2007 года с использованием декомпозиции и наивной модели (рис. 8) для сезонно-изменяемого временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9.] Данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
где''''' $0&amp;lt;⍺&amp;lt;1$ '''''. Если $⍺ = 0$, то текущие наблюдения игнорируются, если же $⍺ = 1$, то полностью игнорируются предыдущие наблюдения.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10.] Данные полученные для 2007 года, с использованием модели экспоненциального сглаживания и декомпозиции]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны [https://otexts.com/fpp2/taxonomy.html здесь].&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года, с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] SARIMA]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ {{---}} свободный член (константа).&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ {{---}} параметры авторегрессии.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ {{---}} константа.&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ {{---}} параметры скользящего среднего.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12.] SARIMA декомпозированная]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Более подробную информацию про ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года, с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13.] ARMA]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (англ. Generalized AutoRegressive Conditional Heteroscedasticity, GARCH) предполагается, что слагаемое ошибки следует авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется (рис. 13).&lt;br /&gt;
&lt;br /&gt;
В 1982 году была предложена ARCH {{---}} модель, описываемая формулой: &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $\alpha$ {{---}} коэффициент задержки. ARCH модель моделирует волатильность в виде суммы базовой волатильности и линейной функции абсолютных значений нескольких последних изменений значений.&lt;br /&gt;
&lt;br /&gt;
Позднее была создана GARCH {{---}} обобщённая ARCH модель, которая также учитывает предыдущие оценки дисперсии. Формула может быть записана так:&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1} \sum_{i = 1}^{p}c_i\sigma^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где p {{---}} количество предшествующих оценок, влияющих на текущее значение.&amp;lt;br&amp;gt;&lt;br /&gt;
с {{---}} весовые коэффициенты предыдущих оценок.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh и различные варианты можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14.] DLM]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов (рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)$ ~ $N(0,W)$, $m(t)$ ~ $N(0,M)$, $r(t)$ ~ $N(0,R)$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15.] DLM]]&lt;br /&gt;
TBATS (англ. Trigonometric seasonality, Box-Cox transformation, ARMA errors, Trend and Seasonal components) {{---}} это модели, которые основаны на экспоненциальном сглаживании (рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на [[L 2-теория рядов Фурье|рядах Фурье]]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которое имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями (рис. 16). &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука ([https://facebook.github.io/prophet/ ссылка]).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16.] Prophet]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть разложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд,&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность,&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы, т.е аномальные данные,&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturing.png |left|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17.] NNETAR]]&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полносвязную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть]. &lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
Модель можно описать уравнением&lt;br /&gt;
$y_t = f(y_{t-1}) + \epsilon_t$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $y_{t-1} = (y_{t-1}, y_{t-2}, ...)'$ {{---}} вектор, содержащий запаздывающие значения, &amp;lt;br&amp;gt;&lt;br /&gt;
f {{---}} нейронная сеть, с 4 скрытыми узлами в каждом слое, &amp;lt;br&amp;gt;&lt;br /&gt;
$\epsilon_t$ {{---}} считаем, что ряд ошибок [https://ru.wikipedia.org/wiki/Гомоскедастичность гомокседастичен] (и возможно имеет нормальное распределение).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturingDecomposition.png |right|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18.] NNETAR c декомпозицией]]&lt;br /&gt;
&lt;br /&gt;
Мы можем моделировать будущие выборочные пути этой модели итеративно, случайным образом генерируя значение для $\epsilon_t$ либо из нормального распределения, либо путем повторной выборки из исторических значений.&amp;lt;br&amp;gt; Так что если&lt;br /&gt;
$\epsilon^*_{T+1}$&lt;br /&gt;
{{---}} случайная выборка из распределения ошибок в момент времени $T+1$,&amp;lt;br&amp;gt; тогда $y^*_{T+1} = f(y_T) + \epsilon^*_{T+1}$ {{---}} один из возможных вариантов распределения прогнозов для $y_{T+1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
Установив $y^*_{T+1} = (y^*_{T+1}, y_{T})'$, мы можем повторить процесс, чтобы получить $y^*_{T+2} = f(y_{T+1}) + \epsilon_{T+2}$. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы можем итеративно моделировать будущий путь выборки. Повторно моделируя выборочные пути, мы накапливаем знания о распределении всех будущих значений на основе подобранной нейронной сети.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов (как показано [https://arxiv.org/abs/1704.04110 здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 19.] MAE с перекрестной проверкой для каждой модели]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[Оценка качества в задачах классификации и регрессии|средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе (рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 20.] MAE, тестовый набор]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Методы увеличения производительности===&lt;br /&gt;
&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов,&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза),&lt;br /&gt;
*Агрегация начальных данных.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае необходимо обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Подробнее о глобальном подходе [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
*[http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
*[https://chaos.phys.msu.ru/loskutov/PDF/Lectures_time_series_analysis.pdf Лоскутов А.Ю. физ. фак. МГУ: Анализ Временных Рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79033</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79033"/>
				<updated>2021-01-20T01:28:56Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Garch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент, применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенности, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая {{---}} это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1.] Кросс-валидация временного ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2.] Набор данных описывающий график производства электрооборудования]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3.] Сезонные колебания]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4.] Наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5.] Cезонно-наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности $T$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE-модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие $T$ шагов совпадают с предыдущими $T$ шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6.] Методы разложения ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона.&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7.] Сезонные индексы ряда]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона;&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции;&lt;br /&gt;
* избежать лишнего сглаживания;&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8.] Декомпозиция и наивная модель]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает расчёты для 2007 года с использованием декомпозиции и наивной модели (рис. 8) для сезонно-изменяемого временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9.] Данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
где''''' $0&amp;lt;⍺&amp;lt;1$ '''''. Если $⍺ = 0$, то текущие наблюдения игнорируются, если же $⍺ = 1$, то полностью игнорируются предыдущие наблюдения.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10.] Данные полученные для 2007 года, с использованием модели экспоненциального сглаживания и декомпозиции]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны [https://otexts.com/fpp2/taxonomy.html здесь].&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года, с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] SARIMA]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Авторегрессионная модель''' {{---}} модель временных рядов, в которой значения временного ряда в данный момент линейно зависят от предыдущих значений этого же ряда.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ {{---}} свободный член (константа).&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ {{---}} параметры авторегрессии.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ {{---}} константа.&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ {{---}} параметры скользящего среднего.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12.] SARIMA декомпозированная]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Более подробную информацию про ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года, с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13.] ARMA]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (англ. Generalized AutoRegressive Conditional Heteroscedasticity, GARCH) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется (рис. 13).&lt;br /&gt;
&lt;br /&gt;
В 1982 году была предложена ARCH - модель, описываемая формулой: &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $\alpha$ {---} коэффициент задержки. ARCH модель моделирует волатильность в виде суммы базовой волатильности и линейной функции абсолютных значений нескольких последних изменений значений.&lt;br /&gt;
&lt;br /&gt;
Позднее была создана GARCH {---} обощённая ARCH модель, которая также учитывает предыдущие оценки дисперсии. Формула может быть записана так:&lt;br /&gt;
$\sigma^2(t) = \alpha + \sum_{i = 1}^{\alpha}b_ir^{2}_{t-1} \sum_{i = 1}^{p}c_i\sigma^{2}_{t-1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
где p {---} количество предществующих оценок, влияющих на текущее значение&amp;lt;br&amp;gt;&lt;br /&gt;
с {---} весовые коэффициенты предыдущих оценок.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh и различные варианты можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14.] DLM]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов (рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)$ ~ $N(0,W)$, $m(t)$ ~ $N(0,M)$, $r(t)$ ~ $N(0,R)$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15.] DLM]]&lt;br /&gt;
TBATS (англ. Trigonometric seasonality, Box-Cox transformation, ARMA errors, Trend and Seasonal components) {{---}} это модели, которые основаны на экспоненциальном сглаживании (рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на [[L 2-теория рядов Фурье|рядах Фурье]]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями (рис. 16). &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука ([https://facebook.github.io/prophet/ ссылка]).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16.] Prophet]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть разложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд,&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность,&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы, т.е аномальные данные,&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturing.png |left|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17.] NNETAR]]&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полносвязную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть]. &lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.[[Файл:NNETARElectriacalequipmntManufacturingDecomposition.png |left|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18.] NNETAR c декомпозицией]]&lt;br /&gt;
&lt;br /&gt;
Модель можно описать уравнением&lt;br /&gt;
$y_t = f(y_{t-1}) + \epsilon_t$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $y_{t-1} = (y_{t-1}, y_{t-2}, ...)'$ - вектор, содержащий запаздывающие значения &amp;lt;br&amp;gt;&lt;br /&gt;
f - нейронная сеть, с 4 скрытыми узлами в каждом слое &amp;lt;br&amp;gt;&lt;br /&gt;
$\epsilon_t$ - считаем, что ряд ошибок --- гомокседастичен( и возможно имеет нормальное распределение)&lt;br /&gt;
&lt;br /&gt;
Мы можем моделировать будущие выборочные пути этой модели итеративно, случайным образом генерируя значение для $\epsilon_t$ либо из нормального распределения, либо путем повторной выборки из исторических значений. Так что если&lt;br /&gt;
$\epsilon_{T+1}*$&lt;br /&gt;
--- случайная выборка из распределения ошибок в момент времени $T+1$,&amp;lt;br&amp;gt; тогда $y_{T+1}* = f(y_T) + \epsilon_{T+1}*$ --- один из возможных вариантов распределения прогнозов для $y_{T+1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
Установив $y_{T+1}* = (y_{T+1}*, y_{T})'$, мы можем повторить процесс, чтобы получить $y_{T+2}* = f(y_{T+1}) + \epsilon_{T+2}$. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы можем итеративно моделировать будущий путь выборки. Повторно моделируя выборочные пути, мы накапливаем знания о распределении всех будущих значений на основе подобранной нейронной сети.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов (как показано [https://arxiv.org/abs/1704.04110 здесь]).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 19.] MAE с перекрестной проверкой для каждой модели]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[Оценка качества в задачах классификации и регрессии|sсредняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе (рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 20.] MAE, тестовый набор]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Методы увеличения производительности===&lt;br /&gt;
&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов,&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза),&lt;br /&gt;
*Агрегация начальных данных.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае необходимо обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Подробнее о глобальном подходе [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
*[https://chaos.phys.msu.ru/loskutov/PDF/Lectures_time_series_analysis.pdf Лоскутов А.Ю. физ. фак. МГУ: Анализ Временных Рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79030</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=79030"/>
				<updated>2021-01-19T23:08:12Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* NNETAR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент, применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенности, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая {{---}} это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1.] Кросс-валидация временного ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2.] Набор данных описывающий график производства электрооборудования]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3.] Сезонные колебания]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4.] Наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5.] Cезонно-наивная]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности $T$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE-модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие $T$ шагов совпадают с предыдущими $T$ шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6.] Методы разложения ряда]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона.&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7.] Сезонные индексы ряда]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона;&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции;&lt;br /&gt;
* избежать лишнего сглаживания;&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8.] Декомпозиция и наивная модель]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает расчёты для 2007 года с использованием декомпозиции и наивной модели (рис. 8) для сезонно-изменяемого временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9.] Данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
где''''' $0&amp;lt;⍺&amp;lt;1$ '''''. Если $⍺ = 0$, то текущие наблюдения игнорируются, если же $⍺ = 1$, то полностью игнорируются предыдущие наблюдения.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10.] Данные полученные для 2007 года, с использованием модели экспоненциального сглаживания и декомпозиции]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны [https://otexts.com/fpp2/taxonomy.html здесь].&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года, с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11.] SARIMA]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Авторегрессионная модель''' {{---}} модель временных рядов, в которой значения временного ряда в данный момент линейно зависят от предыдущих значений этого же ряда.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ {{---}} свободный член (константа).&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ {{---}} параметры авторегрессии.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ {{---}} константа.&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ {{---}} параметры скользящего среднего.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12.] SARIMA декомпозированная]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Более подробную информацию про ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года, с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13.] ARMA]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (англ. Generalized AutoRegressive Conditional Heteroscedasticity, GARCH) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется (рис. 13).&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14.] DLM]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов (рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)$ ~ $N(0,W)$, $m(t)$ ~ $N(0,M)$, $r(t)$ ~ $N(0,R)$.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15.] DLM]]&lt;br /&gt;
TBATS (англ. Trigonometric seasonality, Box-Cox transformation, ARMA errors, Trend and Seasonal components) {{---}} это модели, которые основаны на экспоненциальном сглаживании (рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на [[L 2-теория рядов Фурье|рядах Фурье]]. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями (рис. 16). &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука ([https://facebook.github.io/prophet/ ссылка]).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16.] Prophet]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть разложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$,&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд,&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность,&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы, т.е аномальные данные,&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:NNETARElectriacalequipmntManufacturing.png |left|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17.] NNETAR]]&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полносвязную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть]. &lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.[[Файл:NNETARElectriacalequipmntManufacturingDecomposition.png |left|300px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18.] NNETAR c декомпозицией]]&lt;br /&gt;
&lt;br /&gt;
Модель можно описать уравнением&lt;br /&gt;
$y_t = f(y_{t-1}) + \epsilon_t$ &amp;lt;br&amp;gt;&lt;br /&gt;
где $y_{t-1} = (y_{t-1}, y_{t-2}, ...)'$ - вектор, содержащий запаздывающие значения &amp;lt;br&amp;gt;&lt;br /&gt;
f - нейронная сеть, с 4 скрытыми узлами в каждом слое &amp;lt;br&amp;gt;&lt;br /&gt;
$\epsilon_t$ - считаем, что ряд ошибок --- гомокседастичен( и возможно имеет нормальное распределение)&lt;br /&gt;
&lt;br /&gt;
Мы можем моделировать будущие выборочные пути этой модели итеративно, случайным образом генерируя значение для $\epsilon_t$ либо из нормального распределения, либо путем повторной выборки из исторических значений. Так что если&lt;br /&gt;
$\epsilon_{T+1}*$&lt;br /&gt;
--- случайная выборка из распределения ошибок в момент времени $T+1$,&amp;lt;br&amp;gt; тогда $y_{T+1}* = f(y_T) + \epsilon_{T+1}*$ --- один из возможных вариантов распределения прогнозов для $y_{T+1}$ &amp;lt;br&amp;gt;&lt;br /&gt;
Установив $y_{T+1}* = (y_{T+1}*, y_{T})'$, мы можем повторить процесс, чтобы получить $y_{T+2}* = f(y_{T+1}) + \epsilon_{T+2}$. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы можем итеративно моделировать будущий путь выборки. Повторно моделируя выборочные пути, мы накапливаем знания о распределении всех будущих значений на основе подобранной нейронной сети.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов (как показано [https://arxiv.org/abs/1704.04110 здесь]).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 19.] MAE с перекрестной проверкой для каждой модели]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[Оценка качества в задачах классификации и регрессии|sсредняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе (рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 20.] MAE, тестовый набор]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Методы увеличения производительности===&lt;br /&gt;
&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов,&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза),&lt;br /&gt;
*Агрегация начальных данных.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае необходимо обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Подробнее о глобальном подходе [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
*[https://chaos.phys.msu.ru/loskutov/PDF/Lectures_time_series_analysis.pdf Лоскутов А.Ю. физ. фак. МГУ: Анализ Временных Рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78531</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78531"/>
				<updated>2021-01-15T03:47:43Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Источники Информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая - это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''где $0&amp;lt;⍺&amp;lt;1.$ ''''' Если ⍺ = 0, то текущие наблюдения игнорируются, если же ⍺ = 1, то полностью игнорируются предыдущие наблюдения&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Авторегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ - свободный член(константа)&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ - параметры авторегрессии&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ - константа&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ - параметры скользящего среднего&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
*[https://chaos.phys.msu.ru/loskutov/PDF/Lectures_time_series_analysis.pdf Лоскутов А.Ю. физ. фак. МГУ: Анализ Временных Рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78530</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78530"/>
				<updated>2021-01-15T03:35:37Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Экспоненциальное сглаживание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая - это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''где $0&amp;lt;⍺&amp;lt;1.$ ''''' Если ⍺ = 0, то текущие наблюдения игнорируются, если же ⍺ = 1, то полностью игнорируются предыдущие наблюдения&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Авторегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ - свободный член(константа)&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ - параметры авторегрессии&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ - константа&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ - параметры скользящего среднего&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78529</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78529"/>
				<updated>2021-01-15T03:32:03Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Экспоненциальное сглаживание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая - это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''где $0&amp;lt;⍺&amp;lt;1.$'''''&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Авторегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ - свободный член(константа)&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ - параметры авторегрессии&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ - константа&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ - параметры скользящего среднего&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78528</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78528"/>
				<updated>2021-01-15T03:29:24Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* ARIMA, SARIMA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая - это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''with $0&amp;lt;⍺&amp;lt;1.$'''''&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Авторегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ - свободный член(константа)&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ - параметры авторегрессии&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &amp;lt;br&amp;gt;&lt;br /&gt;
Где $\mu$ - константа&amp;lt;br&amp;gt;&lt;br /&gt;
$\theta_1, \theta_2, \theta_3, ...$ - параметры скользящего среднего&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78527</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78527"/>
				<updated>2021-01-15T03:27:02Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* ARIMA, SARIMA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая - это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''with $0&amp;lt;⍺&amp;lt;1.$'''''&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Авторегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = &lt;br /&gt;
'''Процесс авторегрессии''' {{---}} последовательная зависимость элементов временного ряда, выразается следующим уравнением:&lt;br /&gt;
$x(t) = \psi + \phi_1 * x_(t-1) + \phi_2 * x_(t-2) + \phi_3 * x_(t-3) + ... + \epsilon$&amp;lt;br&amp;gt;&lt;br /&gt;
Где $\psi$ - свободный член(константа)&amp;lt;br&amp;gt;&lt;br /&gt;
$\phi_1, \phi_2, \phi_3, ...$ - параметры авторегрессии&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Процесс скользящего среднего''' {{---}} в процессе скользящего среднего каждый элемент ряда подвержен суммарному воздействию предыдущих ошибок. В общем виде это можно записать следующим образом:&lt;br /&gt;
$x_t = \mu + \epsilon_t - \theta_1 * \epsilon_{t-1} - \theta_2 * \epsilon_{t-2} - ...$ &lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд.&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78526</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78526"/>
				<updated>2021-01-15T03:12:11Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Временной ряд */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Как и большинство других видов анализа, анализ временных рядов предполагает, что данные содержат систематическую составляющую (обычно включающую несколько компонент) и случайный шум (ошибку), который затрудняет обнаружение регулярных компонент. Большинство методов исследования временных рядов включает различные способы фильтрации шума, позволяющие увидеть регулярную составляющую более отчетливо. Большинство регулярных составляющих временных рядов принадлежит к двум классам: они являются либо трендом, либо сезонной составляющей. Тренд представляет собой общую систематическую линейную или нелинейную компоненту, которая может изменяться во времени. Сезонная составляющая - это периодически повторяющаяся компонента. Оба эти вида регулярных компонент часто присутствуют в ряде одновременно.&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''with $0&amp;lt;⍺&amp;lt;1.$'''''&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Саморегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78525</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78525"/>
				<updated>2021-01-15T03:10:27Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Источники Информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''with $0&amp;lt;⍺&amp;lt;1.$'''''&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Саморегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html StatSoft: Анализ временных рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78524</id>
		<title>Анализ временных рядов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%80%D1%8F%D0%B4%D0%BE%D0%B2&amp;diff=78524"/>
				<updated>2021-01-15T03:09:57Z</updated>
		
		<summary type="html">&lt;p&gt;Cga: /* Источники Информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Временные ряды {{---}}  это актуальный инструмент применимый во множестве решений, от предсказания цен на акции, прогнозов погоды, планирования бизнеса, до распределения ресурсов. Несмотря на то, что прогнозирование может быть сведено к построению контролируемой [[Вариации регрессии|регрессии]], существуют особенноссти, связанные с временным характером наблюдений, которые необходимо учитывать, используя специальные инструменты.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Временной ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Временно́й ряд (или ряд динамики)''' {{---}} собранный в разные моменты времени статистический материал о значении каких-либо параметров (в простейшем случае одного) исследуемого процесса. Каждая единица статистического материала называется измерением или отсчётом. Во временном ряде для каждого отсчёта должно быть указано время измерения или номер измерения по порядку.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Валидирование и тестирование модели временного ряда==&lt;br /&gt;
Данные упорядочены относительно неслучайных моментов времени, и, значит, в отличие от случайных выборок, могут содержать в себе дополнительную информацию, поэтому нельзя пользоваться обычными способами валидации. Чтобы избежать смещения оценки необходимо удостовериться, что обучающие наборы данных содержат только наблюдения, которые произошли до событий из валидирующиx наборов.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TimeSeriesCross-validation.png |thumb|left|400px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 1. кросс-валидация временного ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможным способом преодоления данной проблемы будет использование скользящего окна, как описано [https://robjhyndman.com/hyndsight/tscv/ здесь]. Эта процедура называется [[Кросс-валидация|кросс-валидацией]] временного ряда и может быть вкратце описана следующей картинкой (рис. 1), в которой синие точки обозначают тренировочный набор данных, а красные соответствующие валидационные наборы данных.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если необходимо предсказать следующие $n$ шагов, то можно заранее кросс-валидировать $1,2,...,n$.&amp;lt;br&amp;gt; Таким образом можно также сравнить качество предсказаний для разных временных горизонтов.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определив лучшую модель, можно применить её ко всему обучающему набору и оценить его работу на следующем во времени наборе данных. Оценка работы может быть дана с использованием метода скользящего окна&amp;lt;ref&amp;gt;[https://wiki.loginom.ru/articles/windowing-method.html loginom: Метод скользящего окна]&amp;lt;/ref&amp;gt;, который используем при кросс-валидации, но без переподсчёта параметра модели.&lt;br /&gt;
&lt;br /&gt;
==Краткое исследование данных==&lt;br /&gt;
[[Файл:ManufactureOfElectricalEquipment.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 2. Набор данных описывающий график производства электрооборудования]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной части используется несколько разных моделей для предсказания изменений в промышленном производстве,&amp;lt;br&amp;gt; которые для примера будем оценивать численно, как количество электрооборудования, произведённого в зоне Евро (рис. 2, 3).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalPlotMonthluSeasonalPattern.png|thumb|right|300px|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 3. Сезонные колебания]]]&lt;br /&gt;
Набор данных описывает ежемесячное производство электрооборудования (компьютеры электрические и оптические приборы) в зоне евро (17 стран) в период с января 1996 по март 2012 года (см. график ниже). Последние два года будем использовать при тестировании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Модели прогнозирования временных рядов==&lt;br /&gt;
&lt;br /&gt;
Существует 10 моделей прогнозирования, у каждой имеются свои достоинства и недостатки. Ниже, используя каждую модель, предскажем 12 месяцев, соответственно, значение $t+1, t+2, …, t + 12$.&lt;br /&gt;
Имеет смысл использовать среднюю абсолютную ошибку для работы оценки модели.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Наивное предсказание===&lt;br /&gt;
[[Файл:NaiveElectricalEquipmentManufacturing.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 4. Наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предсказания для каждого горизонта соотвествуют последнему наблюдаемому значению&lt;br /&gt;
$Y(t + h|t) = Y(t)$.&lt;br /&gt;
&lt;br /&gt;
Такие предскания предполагают, что стохастическая&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Стохастичность Википедия: Стохастичность]&amp;lt;/ref&amp;gt; модель генерирует [[Участник:Mk17.ru|случайное блуждание]].&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonalNaiveElectricalEquipmentManufacturing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 5. Cезонно-наивная]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение наивной модели сезонно-наивная модель (англ. Season Naive, SNAIVE) {{---}} сезонно-наивная модель предполагает, что временной ряд имеет сезонную компоненту, и что период сезонности T.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Прогнозы SNAIVE {{---}} модели описываются формулой $\dot{Y}(t+h|t) = Y(t+h-T)$.&lt;br /&gt;
&lt;br /&gt;
Получаемые прогнозы следующие T шагов совпадают с предыдущими T шагами. &lt;br /&gt;
Эти модели часто используются как ориентировочные модели. Следующий графики показывают предсказания двух моделей для 2007 года (рис. 4, 5).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Разделение по сезонам + любая модель===&lt;br /&gt;
[[Файл:STL_docompositionOnIndustrialProductionIndexData.png|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 6. Методы разложения ряда]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Если данные показывают, что они восприимчивы к периодическим (сезонным) изменениям (ежедневно, еженедельно, ежеквартально, ежегодно), то будет полезным разложить исходный временной ряд на сумму трёх компонентов.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$Y(t) = S(t) + T(t) + R(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$S(t)$ {{---}} сезонный компонент.&amp;lt;br&amp;gt;&lt;br /&gt;
$T(t)$ {{---}} компонент трендового цикла.&amp;lt;br&amp;gt;&lt;br /&gt;
$R(t)$ {{---}} остаток.&amp;lt;br&amp;gt;&lt;br /&gt;
Существуют несколько способов для такого разложения, но наиболее простой называется классическим разложением и заключается в том, чтобы оценить тренд $T(t)$ через скользящее среднее, посчитать $S(t)$, как среднее без тренда $Y(t) - T(t)$ для каждого сезона&amp;lt;br&amp;gt;&lt;br /&gt;
Посчитать остаток, как $R(t) = Y(t) - T(t)-S(t)$.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedIndustrial.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 7. Сезонные индексы ряда]]]&lt;br /&gt;
Классическое разложение можно расширить несколькими способами.&amp;lt;br&amp;gt;&lt;br /&gt;
Расширение позволяет использовать данный метод при:&lt;br /&gt;
* непостоянной величине сезона&lt;br /&gt;
* посчитать начальные и конечные значения декомпозиции&lt;br /&gt;
* избежать лишнего сглаживания&lt;br /&gt;
&lt;br /&gt;
Обзор методов разложений ряда можно увидеть по [https://otexts.com/fpp2/decomposition.html ссылке]. Используется реализация из стандартной библиотеки (рис. 6).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одним из способов использования декомпозиции для прогнозирования будет:&amp;lt;br&amp;gt;&lt;br /&gt;
1) Разложить обучающий набор алгоритмом из STL.&amp;lt;br&amp;gt;&lt;br /&gt;
2) Посчитать сезонное отклонение ряда $Y(t) - S(t)$, используя любую модель для прогнозирования сезонно-чувствительного временного ряда.&amp;lt;br&amp;gt;&lt;br /&gt;
3) Добавить прогнозам сезонность последнего временного периода во временном ряду (в нашем случае $S(t)$ для прошлого года).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SeasonallyAdjustedTimeSeries.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 8. Декомпозиция и наивная модель]]]&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем графике показаны сезонные индексы ряда с учётом сезонности (рис. 7):&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следующий график показывает предсказания полученные для 2007 года с использованием STL декомпозиции и наивной модели(рис. 8) для сезонно-изменяемого временного ряда:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Декомпозиция была исплементирована с помощью встроенной в стандартную библиотеку функции.&lt;br /&gt;
&lt;br /&gt;
===Экспоненциальное сглаживание ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing.png|thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 9. данные полученные для 2007 года с использованием модели экспоненциального сглаживания]]]&lt;br /&gt;
Экспоненциальное сглаживание&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание Википедия: Экспоненциальное сглаживание]&amp;lt;/ref&amp;gt; {{---}} один из наиболее успешных классических методов предсказаний. В своей базовой форме он называется простым экспоненциальный сглаживанием и его прогнозы описываются формулами:&lt;br /&gt;
$Ŷ(t+h|t) = ⍺y(t) + ⍺(1-⍺)y(t-1) + ⍺(1-⍺)²y(t-2) + …$&amp;lt;br&amp;gt;&lt;br /&gt;
'''''with $0&amp;lt;⍺&amp;lt;1.$'''''&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:ExpSmoothing+Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 10. данные полученные для 2007 года с использованием модели экспоненциального сглаживания и декомпозиции]]]&lt;br /&gt;
&lt;br /&gt;
Заметно, что прогнозы равны взвешенному среднему от старых наблюдений, и что соответствующие веса убывают экспоненциально по мере хода времени.&lt;br /&gt;
&lt;br /&gt;
Некоторые методы для расширения алгоритма позволяют добавить тренд, его затухание и сезонность.&lt;br /&gt;
Экспоненциальное сглаживание состоит из 9 моделей, которые подробно описаны здесь([https://otexts.com/fpp2/taxonomy.html ссылка]).&lt;br /&gt;
&lt;br /&gt;
Следующие графики (рис. 9, 10) описывают прогнозы данных полученные для 2007 года с использованием модели экспоненциального сглаживания (выбраны автоматически), которые подходили исходному и сезонно-чувствительному временному ряду.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ARIMA, SARIMA===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:SARIMA.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 11. SARIMA]]]&lt;br /&gt;
Также как и экспоненциальное сглаживание, интегрированная модель авторегрессии скользящего среднего  (англ. autoregressive integrated moving average, ARIMA) также часто используются для прогноза временных рядов.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Саморегрессивность''' {{---}} линейная комбинация старых значений.&lt;br /&gt;
}} &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Скользящее среднее''' {{---}} общее название для семейства функций, значения которых в каждой точке определения равны некоторому среднему значению исходной функции за предыдущий период.&lt;br /&gt;
}} &lt;br /&gt;
[[Файл:SARIMA_Decomposition.png|thumb|right|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 12. SARIMA декомпозированная]]]&lt;br /&gt;
ARIMA {{---}} комбинация этих двух подходов. Так как эти подходы требуются стационарности временного ряда, может понадобится продифференциировать/проинтегрировать ряд&lt;br /&gt;
То есть рассматировать ряд разностей, а не исходный ряд.&lt;br /&gt;
&lt;br /&gt;
Сезонная интегрированная модель авторегрессии скользящего среднего (англ. season autoregressive integrated moving average, SARIMA) учитывает сезонность, добавляя линейную комбинацию прошлых сезонных значений и/или прошлых ошибок прогноза.&lt;br /&gt;
Для полного ввода в ARIMA, SARIMA читайте по [https://otexts.com/fpp2/arima.html ссылке].&lt;br /&gt;
&lt;br /&gt;
Данные графики показывают предсказания полученные для 2007 года с использованием модели SARIMA (рис. 11,12).&lt;br /&gt;
&lt;br /&gt;
===Garch===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:GARCH.png |thumb|left|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 13. ARMA]]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущих моделях считалось, что слагаемое ошибки в стохастическом процессе генерации временного ряда имело одинаковую дисперсию.&lt;br /&gt;
&lt;br /&gt;
В GARСH-модели (рис. 13) предполагается, что слагаемое ошибки следуют авторегрессионному скользящему среднему (англ. AutoRegressive Moving Average, ARMA), соответственно слагаемое меняется по ходу времени. Это особенно полезно при моделировании финансовых временных рядов, так как диапазон изменений тоже постоянно меняется.&lt;br /&gt;
&lt;br /&gt;
Обычно ARMA используется и для учёта среднего, более подробное введение в Garsh можно найти [https://cran.r-project.org/web/packages/rugarch/vignettes/Introduction_to_the_rugarch_package.pdf здесь]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Динамические линейные модели===&lt;br /&gt;
[[Файл:DLM+Decomposition.png|right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 14. DLM]]]&amp;lt;br&amp;gt;&lt;br /&gt;
Динамические линейные модели представляют другой класс моделей предсказания временных рядов(рис. 14).&lt;br /&gt;
Идея заключается в том, что в каждый момент времени $t$ эти модели соответствуют линейной модели, но коэффициент регрессии постоянно меняется. &amp;lt;br&amp;gt;Пример динамической линейной модели ниже:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = ⍺(t) + tβ(t) + w(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$⍺(t) = ⍺(t-1) + m(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$β(t) = β(t-1) + r(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$w(t)~N(0,W) , m(t)~N(0,M) , r(t)~N(0,R)$&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В предыдущей модели коэффициенты $a(t)$ и $b(t)$ следуют случайному блужданию.&lt;br /&gt;
&lt;br /&gt;
Динамические линейные модели могут быть построены в рамках Байесовской системы. Тем не менее и этот метод можно улучшить, подробности [https://cran.r-project.org/web/packages/dlm/vignettes/dlm.pdf здесь].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===TBATS===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:TBATS_Electrical.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 15. DLM]]]&lt;br /&gt;
TBATS {{---}} это модели, которые основаны на экспоненциальном сглаживании(рис. 15).&amp;lt;br&amp;gt; Главной особенностью TBATS является возможность взаимодействия с несколькими сезонностями. Моделируя каждую функцию сезонности отдельным тригонометрическим отображением построенным на рядах Фурье. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Классическим примером комплексной сезонности будет отображение ежедневных объемов продаж, которые имеет, как еженедельные колебания, так и ежегодные.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Больше информации можно прочиать [https://robjhyndman.com/papers/ComplexSeasonality.pdf тут].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Prophet===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ещё одна модель, способная взаимодействовать с несколькими сезонностями. &lt;br /&gt;
Это ПО с открытым исходным кодом от Фейсбука (рис. 16).&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Prophet.png |right|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 16. Prophet]]]&lt;br /&gt;
&lt;br /&gt;
Prophet считает, что временной ряд может быть расложен следующим образом:&amp;lt;br&amp;gt;&lt;br /&gt;
$y(t) = g(t) + s(t) + h(t) + ε(t)$&amp;lt;br&amp;gt;&lt;br /&gt;
$g(t)$ {{---}} тренд.&amp;lt;br&amp;gt;&lt;br /&gt;
$s(t)$ {{---}} сезонность.&amp;lt;br&amp;gt;&lt;br /&gt;
$h(t)$ {{---}} каникулы.&amp;lt;br&amp;gt;&lt;br /&gt;
$ε(t)$ {{---}} ошибки.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подгонка модели представляет собой упражнение по подгонке кривой, поэтому она явно не учитывает структуру временной зависимости в данных. Это также позволяет проводить наблюдения с нерегулярным интервалом.&amp;lt;br&amp;gt;&lt;br /&gt;
Есть два варианта временных рядов тренда: модель насыщающего роста и кусочно-линейная модель. Модель многопериодной сезонности основана на рядах Фурье&amp;lt;ref&amp;gt;[[Определение ряда Фурье]]&amp;lt;/ref&amp;gt;. Эффект известных и заказных выходных дней может быть легко включен в модель.&amp;lt;br&amp;gt;&lt;br /&gt;
Модель Prophet вставлена в байесовскую структуру и позволяет сделать полный апостериорный вывод, чтобы включить неопределенность параметров модели в неопределенность прогноза.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NNETAR===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модель авторегрессии нейронной сети (англ. Neural NETwork AutoRegression, NNETAR) представляет собой полностью связанную [https://neerc.ifmo.ru/wiki/index.php?title=Нейронные_сети,_перцептрон нейронную сеть].&lt;br /&gt;
&lt;br /&gt;
Модель NNETAR принимает на вход последние элементы последовательности до момента времени $t$ и выводит прогнозируемое значение в момент времени $t + 1$. Для выполнения многоэтапных прогнозов сеть применяется итеративно.&lt;br /&gt;
&lt;br /&gt;
===LSTM===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Модели [[:Долгая_краткосрочная_память|cети долго-краткосрочной памяти]] (англ. Long short-term memory, LSTM) могут использоваться для прогнозирования временных рядов (а также других рекуррентных нейронных сетей). &amp;lt;br&amp;gt;&lt;br /&gt;
Состояние сети LSTM представлено через вектор пространства состояний. Этот метод позволяет отслеживать зависимости новых наблюдений от прошлых (даже очень далеких).&amp;lt;br&amp;gt;&lt;br /&gt;
Вообще говоря, LSTM представляют собой сложные модели, и они редко используются для прогнозирования одного временного ряда, поскольку для их оценки требуется большой объем данных.&amp;lt;br&amp;gt;Однако они обычно используются, когда необходимы прогнозы для большого количества временных рядов ([https://arxiv.org/abs/1704.04110 как показано здесь]).&lt;br /&gt;
&lt;br /&gt;
==Оценка==&lt;br /&gt;
[[Файл:Evaluation.png |right|600px|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 17. MAE с перекрестной проверкой для каждой модели]]]&lt;br /&gt;
Выполнен выбор модели с помощью процедуры перекрестной проверки, описанной ранее. Не рассчитывая его для динамических линейных моделей и моделей LSTM из-за их высокой вычислительной стоимости и низкой производительности.&amp;lt;br&amp;gt;&lt;br /&gt;
На следующем рисунке показана [[средняя абсолютная ошибка]] (англ. Mean Absolute Error, MAE) с перекрестной проверкой для каждой модели и для каждого временного горизонта (рис. 17): &lt;br /&gt;
&lt;br /&gt;
Модель NNETAR по сезонно скорректированным данным была лучшей моделью для данной задачи, поскольку она соответствовала самому низкому значению MAE, прошедшему перекрестную проверку.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы получить объективную оценку наилучшей производительности модели, вычислим MAE на тестовом наборе(рис. 18), получив оценку, равную 5,24. На следующем рисунке можно увидеть MAE, оцененную на тестовой выборке для каждого временного горизонта.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Cross-validated MAE.png |left|thumb|[https://towardsdatascience.com/an-overview-of-time-series-forecasting-models-a2fa7a358fcb Рисунок 18. MAE, тестовый набор]]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
===Как еще больше повысить производительность===&lt;br /&gt;
Другие методы повышения производительности моделей:&lt;br /&gt;
*Использование разных моделей для разных временных горизонтов&lt;br /&gt;
*Объединение нескольких прогнозов (например, с учетом среднего прогноза)&lt;br /&gt;
*'''Агрегация начальных данных'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Последний метод можно резюмировать следующим образом:&lt;br /&gt;
*Разложите исходный временной ряд (например, используя STL)&lt;br /&gt;
*Создайте набор похожих временных рядов путем случайного перемешивания фрагментов оставшейся компоненты.&lt;br /&gt;
*Подбирайте модель для каждого временного ряда&lt;br /&gt;
*Средние прогнозы каждой модели&lt;br /&gt;
&lt;br /&gt;
==Заключительные замечания==&lt;br /&gt;
Большинство ранее описанных моделей позволяют легко включать изменяющиеся во времени предикторы. Они могут быть извлечены из одного и того же временного ряда или могут соответствовать внешним предикторам (например, временному ряду другого индекса). В последнем случае мы должны обратить внимание на то, чтобы не использовать информацию из будущего, которая могла бы быть удовлетворена путем прогнозирования предикторов или использования версий c ошибками.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данном конспекте рассматривается случай, когда у нас есть один временной ряд для прогнозирования. Когда у нас много временных рядов, может быть предпочтительнее глобальный подход, поскольку он позволяет нам оценивать более сложную и потенциально более точную модель. Чтобы ознакомиться с глобальным подходом, щелкните [https://arxiv.org/abs/1704.04110 здесь].&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
* [[Кластеризация]]&lt;br /&gt;
* [[Уменьшение размерности]]&lt;br /&gt;
* [[Рекомендательные системы]]&lt;br /&gt;
* [[Анализ социальных сетей]]&lt;br /&gt;
* [[Графовые нейронные сети]]&lt;br /&gt;
* [[Компьютерное зрение]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники Информации==&lt;br /&gt;
* Филатов, А. В. Заметки профайлера / А. В. Филатов. -Москва: Издательские решения, 2019. -522.&lt;br /&gt;
* [http://www.machinelearning.ru/wiki/index.php?title=Временной_ряд machinelearning.ru]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Временной_ряд Википедия: Временной ряд]&lt;br /&gt;
*[http://statsoft.ru/home/textbook/modules/sttimser.html Анализ временных рядов]&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Анализ временных рядов]]&lt;/div&gt;</summary>
		<author><name>Cga</name></author>	</entry>

	</feed>