<?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=Slavam2605</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=Slavam2605"/>
		<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/Slavam2605"/>
		<updated>2026-08-18T21:38:47Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69597</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69597"/>
				<updated>2019-01-28T16:00:15Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;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;
'''Порождающее моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;, определенном на датасете &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; из пространства (возможно многомерного) &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство &amp;lt;math&amp;gt;Z&amp;lt;/math&amp;gt; соответствующее случайной величине &amp;lt;math&amp;gt;(z, P(z))&amp;lt;/math&amp;gt; (распределенной как-нибудь фиксированно, здесь &amp;lt;math&amp;gt;\sim N(0, 1)&amp;lt;/math&amp;gt;). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to X &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; по &amp;lt;math&amp;gt;P(z)&amp;lt;/math&amp;gt; мы получили &amp;quot;что-то похожее&amp;quot; на элементы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Вообще, для любого &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; мы хотим считать &amp;lt;math&amp;gt;P(x) = \int P(x|z; \theta)P(z)dz&amp;lt;/math&amp;gt;, здесь мы заменили &amp;lt;math&amp;gt;f(z, \theta)&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt;, чтобы явно показать зависимость между &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; и после этого применить формулу полной вероятности. Обычно &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt; около нуля почти для всех пар &amp;lt;math&amp;gt;(x, z)&amp;lt;/math&amp;gt;. Основная идея в том, что мы хотим теперь генерировать &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, который бы давали что-то около &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и только их суммировать в &amp;lt;math&amp;gt;P(x)&amp;lt;/math&amp;gt;. Для этого нам требуется ввести еще одно распределение &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, которое будет получать &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и говорить распределение на &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; которое наиболее вероятно будет генерировать нам такой &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Теперь нам нужно как-то сделать похожими распределения &amp;lt;math&amp;gt;E_{z\sim Q}P(X|z)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим следующую дивергенцию Кульбака-Лейблера (''Kullback–Leibler divergence'', ''KLD'').&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z|X) − log P(z|X)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Распишем &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;P(X|z) * P(z) / P(X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z) − log P(X|z) - log P(z)] + log P(X)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что эквивалентно:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим эту штуку для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, тогда:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z|X)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z|X)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посмотрим, на это равенство. Правую часть мы можем оптимизировать градиентным спуском (пусть пока и не совсем понятно как).&lt;br /&gt;
В левой же части первое слагаемое {{---}} то, что мы хотим максимизировать. В то же время &amp;lt;math&amp;gt;D[Q(z|X)||P(z|X)]&amp;lt;/math&amp;gt; мы хотим минимизировать. Если у нас &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt; {{---}} достаточно сильная модель, то в какой-то момент она будет хорошо матчить &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, а значит их дивергенция Кульбака-Лейблера будет почти 0. Значит, при оптимизации можно исключить эту часть и стараться максимизировать только правую. В качестве бонуса мы еще получили более &amp;quot;податливую&amp;quot; &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, вместо нее можно смотреть на &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь разберемся как оптимизировать правую часть. Сначала нужно определиться с моделью для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;. Обычно ее берут равной &amp;lt;math&amp;gt;N(z|\mu(X, \theta), \sigma(X, \theta))&amp;lt;/math&amp;gt;. Где &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sigma&amp;lt;/math&amp;gt; какие-то детерминированные функции на X с обучаемыми параметрами &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, которые мы впредь будем опускать (обычно используются нейронные сети). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно проверить, что для дивергенция Кульбака-Лейблера двух нормальных распределений имеет следующий вид.&lt;br /&gt;
:&amp;lt;math&amp;gt;D_{K}[N(\mu_1, \Sigma_0)||N(\mu_1, \Sigma_0)]&amp;lt;/math&amp;gt;, KLD есть &amp;lt;math&amp;gt;\frac{1}{2} (tr(\Sigma_1^{-1}\Sigma_0) + (\mu_1 - \mu_0)^T\Sigma_1^{-1}(\mu_1 - \mu_0) - k + log(\frac{det\Sigma_1}{det\Sigma_0})) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это значит, что&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z|X)||P(z)] = D[N(\mu(X), \Sigma(X))||N(0, I)] = \frac12 (tr(\Sigma(X)) + \mu(X)^T\mu(X) - k - log(det\Sigma(X)))&amp;lt;/math&amp;gt;. &lt;br /&gt;
Теперь здесь &lt;br /&gt;
можно считать градиенты, для BackPropagation. С первым слагаемым в правой части все немного сложнее. &amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)]&amp;lt;/math&amp;gt; мы можем считать методом Монте-Карло(МК), но тогда такая штука (из-за того, что переменные спрятаны в распределении, из которого мы генерируем себе выборку, для МК) не является гладкой относительно них, а значит непонятно, как проталкивать через это градиент. Для того, чтобы все-таки можно было протолкнуть градиент, применяется так называемый ''трюк репараметризации'', который базируется на простой формуле &amp;lt;math&amp;gt;N(\Sigma(X), \mu(X)) = \mu(X) + \Sigma^{\frac12}(X) * N(0, I) &amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)] = E_{\epsilon \sim N(0, I)}[log P(X = f(\mu(X) + \Sigma^{\frac12}(X) * \epsilon), \theta)]&amp;lt;/math&amp;gt;. &lt;br /&gt;
В такой форме мы уже можем использовать BackPropagation для переменных из функций &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следующая картинка лучше поможет осознать структуру VAE и, в частности, зачем нужен (и как работает) трюк репараметризации.&lt;br /&gt;
&lt;br /&gt;
На левой части диаграмма без использования reparameterization trick. &lt;br /&gt;
На правой части диаграмма с использованием reparameterization trick. &lt;br /&gt;
&lt;br /&gt;
[[Файл:VAE.PNG]]&lt;br /&gt;
&lt;br /&gt;
взято из https://arxiv.org/pdf/1606.05908.pdf&lt;br /&gt;
&lt;br /&gt;
== Пример реализации ==&lt;br /&gt;
Ниже приведена реализация частного случая VAE на языке Python с использованием библиотеки Pytorch.&lt;br /&gt;
Эта реализация работает с датасетом MNIST.&lt;br /&gt;
Размерность скрытого слоя {{---}} 2. &lt;br /&gt;
Координаты в нем считаются независимыми (из-за этого, например, матрица &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; диагональная, и формула для расчета KLD немного другая).&lt;br /&gt;
&lt;br /&gt;
 class VariationalAutoencoder(nn.Module):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super().__init__()&lt;br /&gt;
        self.mu = nn.Linear(32, 2)&lt;br /&gt;
        self.gamma = nn.Linear(32, 2)&lt;br /&gt;
        self.encoder = nn.Sequential(nn.Linear(784, 32), nn.ReLU(True))&lt;br /&gt;
        self.decoder = nn.Sequential(nn.Linear(2, 32), nn.ReLU(True), nn.Linear(32, 784), nn.Sigmoid())&lt;br /&gt;
 &lt;br /&gt;
    def forward(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        x = self.decoder(encoding)&lt;br /&gt;
        return x, mu, gamma&lt;br /&gt;
 &lt;br /&gt;
    def reparameterize(self, mu, gamma):&lt;br /&gt;
        if self.training:&lt;br /&gt;
            sigma = torch.exp(0.5*gamma)&lt;br /&gt;
            std_z = Variable(torch.from_numpy(np.random.normal(0, 1, size=sigma.size())).float())&lt;br /&gt;
            encoding = std_z.mul(sigma).add(mu)&lt;br /&gt;
            return encoding&lt;br /&gt;
        else:&lt;br /&gt;
            return mu&lt;br /&gt;
 &lt;br /&gt;
    def encode(self, x):&lt;br /&gt;
        x = self.encoder(x)&lt;br /&gt;
        mu = self.mu(x)&lt;br /&gt;
        gamma = self.gamma(x)&lt;br /&gt;
        return mu, gamma&lt;br /&gt;
  &lt;br /&gt;
    def decode(self, x):&lt;br /&gt;
        return self.decoder(x)&lt;br /&gt;
 &lt;br /&gt;
    def latent(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        return encoding&lt;br /&gt;
 &lt;br /&gt;
 def loss_function(input, output, mu, gamma, batch_size=batch_size):&lt;br /&gt;
    BCE = F.binary_cross_entropy(output, input)&lt;br /&gt;
    KLD = -0.5*torch.sum(1 + gamma - mu.pow(2) - gamma.exp())&lt;br /&gt;
    KLD /= batch_size*784&lt;br /&gt;
    return BCE + KLD&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;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[:Автокодировщик|Автокодировщик]]&amp;lt;sup&amp;gt;[на 28.01.19 не создан]&amp;lt;/sup&amp;gt; &lt;br /&gt;
*[[:Generative Adversarial Nets (GAN)|Порождающие состязательные сети]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
*[https://habr.com/ru/post/429276/ Вариационные автокодировщики: теория и рабочий код]&lt;br /&gt;
*[https://jaan.io/what-is-variational-autoencoder-vae-tutorial/ Tutorial - What is a variational autoencoder?]&lt;br /&gt;
*[https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf Intuitively Understanding Variational Autoencoders]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[https://arxiv.org/abs/1606.05908 Tutorial on Variational Autoencoders]&lt;br /&gt;
*Datalore презентация Дениса Степанова&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Порождающие модели]]&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68718</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=68718"/>
				<updated>2019-01-21T13:20:40Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &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|Пример свертки двух матриц размера 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|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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|Пример операции пулинга с функцией максимума]]&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|Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|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|Устройство 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;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура 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|Архитектура 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;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Net-comparison.png&amp;diff=68717</id>
		<title>Файл:Net-comparison.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Net-comparison.png&amp;diff=68717"/>
				<updated>2019-01-21T13:15:14Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Сравнение нейронных сетей
Источник: https://arxiv.org/pdf/1605.07678.pdf&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Сравнение нейронных сетей&lt;br /&gt;
Источник: https://arxiv.org/pdf/1605.07678.pdf&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68716</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=68716"/>
				<updated>2019-01-21T13:13:37Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &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|Пример свертки двух матриц размера 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|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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|Пример операции пулинга с функцией максимума]]&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|Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|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|Устройство 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;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура 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|Архитектура 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;
===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;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68715</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=68715"/>
				<updated>2019-01-21T13:03:37Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &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|Пример свертки двух матриц размера 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|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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|Пример операции пулинга с функцией максимума]]&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|Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|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|Устройство 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;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура 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|Архитектура 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&lt;br /&gt;
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;
== Примеры кода ==&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;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68714</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=68714"/>
				<updated>2019-01-21T13:02:58Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &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|Пример свертки двух матриц размера 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|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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|Пример операции пулинга с функцией максимума]]&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|Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|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|Устройство 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;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура 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|Архитектура 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&lt;br /&gt;
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;
== Примеры кода ==&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;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Residual.png&amp;diff=68713</id>
		<title>Файл:Residual.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Residual.png&amp;diff=68713"/>
				<updated>2019-01-21T12:34:55Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Устройство residual block.
Источник: https://arxiv.org/pdf/1512.03385.pdf&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Устройство residual block.&lt;br /&gt;
Источник: https://arxiv.org/pdf/1512.03385.pdf&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68666</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=68666"/>
				<updated>2019-01-20T20:02:48Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &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|Пример свертки двух матриц размера 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|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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|Пример операции пулинга с функцией максимума]]&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|Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|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;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура 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|Архитектура 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&lt;br /&gt;
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;
== Примеры кода ==&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;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68597</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=68597"/>
				<updated>2019-01-20T15:57:39Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Добавлены ссылки на архитектуры известных нейронных сетей&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|Пример свертки двух матриц размера 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|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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|Пример операции пулинга с функцией максимума]]&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|Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref&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;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура 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|Архитектура 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&lt;br /&gt;
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;
== Примеры кода ==&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;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68593</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=68593"/>
				<updated>2019-01-20T14:56:50Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Описание inception module&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная Яном Лекуном&amp;lt;ref&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|Пример свертки двух матриц размера 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|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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|Пример операции пулинга с функцией максимума]]&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|Inception module]]&lt;br /&gt;
[[Файл:Inception_red.png|upright=1.0|thumb|Inception module с сокращением размерностей]]&lt;br /&gt;
''Inception module'' {{---}} это специальный слой нейронной сети, который был предложен в работе&amp;lt;ref&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;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&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;
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Inception_red.png&amp;diff=68592</id>
		<title>Файл:Inception red.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Inception_red.png&amp;diff=68592"/>
				<updated>2019-01-20T14:52:09Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Inception module с сокращением размерностей.
Источник: https://arxiv.org/pdf/1409.4842.pdf&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Inception module с сокращением размерностей.&lt;br /&gt;
Источник: https://arxiv.org/pdf/1409.4842.pdf&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Inception.png&amp;diff=68590</id>
		<title>Файл:Inception.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Inception.png&amp;diff=68590"/>
				<updated>2019-01-20T13:58:11Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Inception module.
Источник: https://arxiv.org/abs/1409.4842&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Inception module.&lt;br /&gt;
Источник: https://arxiv.org/abs/1409.4842&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68272</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=68272"/>
				<updated>2019-01-10T11:57:33Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная [https://ru.wikipedia.org/wiki/%D0%9B%D0%B5%D0%BA%D1%83%D0%BD,_%D0%AF%D0%BD Яном Лекуном], изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.0|thumb|Пример свертки двух матриц размера 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'') и [[:Нейронные сети, перцептрон|полносвязные слои]]&amp;lt;sup&amp;gt;[на 09.01.19 не создан]&amp;lt;/sup&amp;gt; (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
=== Сверточный слой ===&lt;br /&gt;
[[Файл:Padding.png|upright=1.0|thumb|Пример свертки двух матриц с дополнением нулями и сдвигом 2]]&lt;br /&gt;
[[Файл:Convolution-operation-on-volume5.png|upright=1.0|thumb|Пример свертки с трехмерным ядром]]&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''). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения (распространенной практикой является дополнять изображение нулями (англ. ''zero padding''), но возможны и другие подходы). Такие свертки называют ''одинаковыми'' (англ. ''same convolution''), а свертки без дополнения изображения называются ''правильными'' (англ. ''valid convolution'').&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|Пример операции пулинга с функцией максимума]]&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;
== Известные архитектуры сверточных нейронных сетей ==&lt;br /&gt;
=== LeNet-5 ===&lt;br /&gt;
[[Файл:Lenet5.png|upright=1.0|thumb|Архитектура LeNet-5]]&lt;br /&gt;
Нейронная сеть, предложенная Яном Лекуном, для распознавания рукописных цифр MNIST.&lt;br /&gt;
&lt;br /&gt;
=== AlexNet ===&lt;br /&gt;
[[Файл:Alexnet.png|upright=1.0|thumb|Архитектура AlexNet]]&lt;br /&gt;
Победитель соревнования ImageNet 2012-ого года, набравший точность 84.6%. Была реализована с использованием CUDA для повышения производительности. Состоит из двух отдельных частей, которые слабо взаимодействуют друг с другом, что позволяет исполнять их параллельно на разных GPU с минимальным обменом данными.&lt;br /&gt;
&lt;br /&gt;
=== VGG ===&lt;br /&gt;
Семейство архитектур нейронных сетей, которое включает в себя, в частности, VGG-11, VGG-13, VGG-16 и VGG-19. Победитель соревнования ImageNet 2013-ого года (VGG-16), набравший точность 92.7%. Одной из отличительных особенностей является использование ядер свертки небольшого размера (3x3, в отличие от больших ядер размера 7x7 или 11x11).&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Alexnet.png&amp;diff=68271</id>
		<title>Файл:Alexnet.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Alexnet.png&amp;diff=68271"/>
				<updated>2019-01-10T11:44:10Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Архитектура сверточной нейронной сети AlexNet.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Архитектура сверточной нейронной сети AlexNet.&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Lenet5.png&amp;diff=68270</id>
		<title>Файл:Lenet5.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Lenet5.png&amp;diff=68270"/>
				<updated>2019-01-10T11:38:18Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Архитектура сверточной нейронной сети LeNet-5.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Архитектура сверточной нейронной сети LeNet-5.&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Maxpool.jpeg&amp;diff=68269</id>
		<title>Файл:Maxpool.jpeg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Maxpool.jpeg&amp;diff=68269"/>
				<updated>2019-01-10T11:20:57Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Пример операции пулинга с функцией максимума.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Пример операции пулинга с функцией максимума.&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Convolution-operation-on-volume5.png&amp;diff=68267</id>
		<title>Файл:Convolution-operation-on-volume5.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Convolution-operation-on-volume5.png&amp;diff=68267"/>
				<updated>2019-01-10T11:11:13Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68218</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=68218"/>
				<updated>2019-01-09T12:30:22Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная [https://ru.wikipedia.org/wiki/%D0%9B%D0%B5%D0%BA%D1%83%D0%BD,_%D0%AF%D0%BD Яном Лекуном], изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.5|thumb|Пример свертки двух матриц размера 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'') и [[:Нейронные сети, перцептрон|полносвязные слои]]&amp;lt;sup&amp;gt;[на 09.01.19 не создан]&amp;lt;/sup&amp;gt; (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
== Сверточный слой ==&lt;br /&gt;
[[Файл:Padding.png|upright=1.5|thumb|Пример свертки двух матриц с дополнением нулями]]&lt;br /&gt;
[[Файл:Strides.png|upright=1.5|thumb|Пример свертки двух матриц со сдвигом 2]]&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). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения (распространенной практикой является дополнять изображение нулями (англ. zero padding), но возможны и другие подходы). Такие свертки называют ''одинаковыми'' (англ. same convolution), а свертки без дополнения изображения называются ''правильными'' (англ. valid convolution).&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;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция (например, максимум в случае max pooling или (взвешенное) среднее в случае (weighted) average pooling). Обучаемых параметров у этого слоя нет, его основная цель {{---}} уменьшить изображение, чтобы последующие свертки оперировали над большей областью исходного изображения. Также он призван увеличить инвариантность выхода сети по отношению к малому переносу входа.&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Strides.png&amp;diff=68217</id>
		<title>Файл:Strides.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Strides.png&amp;diff=68217"/>
				<updated>2019-01-09T12:29:35Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Свертка с использованием сдвига 2.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Свертка с использованием сдвига 2.&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68216</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=68216"/>
				<updated>2019-01-09T12:24:47Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная [https://ru.wikipedia.org/wiki/%D0%9B%D0%B5%D0%BA%D1%83%D0%BD,_%D0%AF%D0%BD Яном Лекуном], изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.5|thumb|Пример свертки двух матриц размера 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'') и [[:Нейронные сети, перцептрон|полносвязные слои]]&amp;lt;sup&amp;gt;[на 09.01.19 не создан]&amp;lt;/sup&amp;gt; (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
== Сверточный слой ==&lt;br /&gt;
[[Файл:Padding.png|upright=1.5|thumb|Пример свертки двух матриц с дополнением нулями]]&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). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения (распространенной практикой является дополнять изображение нулями (англ. zero padding), но возможны и другие подходы). Такие свертки называют ''одинаковыми'' (англ. same convolution), а свертки без дополнения изображения называются ''правильными'' (англ. valid convolution).&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;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция (например, максимум в случае max pooling или (взвешенное) среднее в случае (weighted) average pooling). Обучаемых параметров у этого слоя нет, его основная цель {{---}} уменьшить изображение, чтобы последующие свертки оперировали над большей областью исходного изображения. Также он призван увеличить инвариантность выхода сети по отношению к малому переносу входа.&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Padding.png&amp;diff=68215</id>
		<title>Файл:Padding.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Padding.png&amp;diff=68215"/>
				<updated>2019-01-09T12:20:49Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Пример свертки с дополненим изображения.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Пример свертки с дополненим изображения.&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68214</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=68214"/>
				<updated>2019-01-09T12:18:16Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная [https://ru.wikipedia.org/wiki/%D0%9B%D0%B5%D0%BA%D1%83%D0%BD,_%D0%AF%D0%BD Яном Лекуном], изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.5|thumb|Пример свертки двух матриц размера 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'') и [[:Нейронные сети, перцептрон|полносвязные слои]]&amp;lt;sup&amp;gt;[на 09.01.19 не создан]&amp;lt;/sup&amp;gt; (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
== Сверточный слой ==&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). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения (распространенной практикой является дополнять изображение нулями (англ. zero padding), но возможны и другие подходы). Такие свертки называют ''одинаковыми'' (англ. same convolution), а свертки без дополнения изображения называются ''правильными'' (англ. valid convolution).&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;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция (например, максимум в случае max pooling или (взвешенное) среднее в случае (weighted) average pooling). Обучаемых параметров у этого слоя нет, его основная цель {{---}} уменьшить изображение, чтобы последующие свертки оперировали над большей областью исходного изображения. Также призван увеличить инвариантность выхода сети по отношению к малому переносу входа.&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=68213</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=68213"/>
				<updated>2019-01-09T11:53:53Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная [https://ru.wikipedia.org/wiki/%D0%9B%D0%B5%D0%BA%D1%83%D0%BD,_%D0%AF%D0%BD Яном Лекуном], изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.5|thumb|Пример свертки двух матриц размера 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'') и [[:Нейронные сети, перцептрон|полносвязные слои]]&amp;lt;sup&amp;gt;[на 09.01.19 не создан]&amp;lt;/sup&amp;gt; (англ. ''fully-connected layer'').&lt;br /&gt;
&lt;br /&gt;
== Сверточный слой ==&lt;br /&gt;
Сверточный слой нейронной сети представляет из себя применение операции свертки к выходам с предыдущего слоя, где веса ядра свертки являются обучаемыми параметрами. Еще один обучаемый вес используется в качестве константного сдвига (англ. bias). При этом есть несколько важных деталей:&lt;br /&gt;
&lt;br /&gt;
Ядер свертки на каждом слое может быть несколько и они могут быть трехмерными. Например, если мы хотим как-то усреднить на первом слое информацию о трёх цветовых каналах изображения, то мы можем поместить на первый слой свертку с ядром размерности &amp;lt;math&amp;gt;3\times w \times h&amp;lt;/math&amp;gt;. На выходе такого слоя будет уже одно изображение (вместо трёх). Также можно иметь несколько сверток на одном слое нейронной сети, например, если на входе один слой изображения и 6 сверток, то на выходе будет 6 слоев изображения.&lt;br /&gt;
&lt;br /&gt;
Еще одна важная делать заключается в том, что применение операции свертки уменьшает изображение. Также пиксели, которые находятся на границе изображения учавствуют в меньшем количестве сверток, чем внутренние. В связи с этим в сверточных слоях используется дополнение изображения (англ. padding). Выходы с предыдущего слоя дополняются пикселями так, чтобы после свертки сохранился размер изображения (распространенной практикой является дополнять изображение нулями (англ. zero padding), но возможны и другие подходы). Такие свертки называют ''одинаковыми'' (англ. same convolution), а свертки без дополнения изображения называются ''правильными'' (англ. valid convolution).&lt;br /&gt;
&lt;br /&gt;
== Пулинговый слой ==&lt;br /&gt;
Пулинговый слой призван снижать размерность изображения. Исходное изображение делится на блоки размером &amp;lt;math&amp;gt;w\times h&amp;lt;/math&amp;gt; и для каждого блока вычисляется некоторая функция (например, максимум в случае max pooling или (взвешенное) среднее в случае (weighted) average pooling). Обучаемых параметров у этого слоя нет, его основная цель {{---}} уменьшить изображение, чтобы последующие свертки оперировали над большей областью исходного изображения.&lt;/div&gt;</summary>
		<author><name>Slavam2605</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=67996</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=67996"/>
				<updated>2018-12-21T10:21:35Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Зачаток страницы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сверточная нейронная сеть''' (англ. ''convolutional neural network'', ''CNN'') {{---}} специальная архитектура нейронных сетей, предложенная [https://ru.wikipedia.org/wiki/%D0%9B%D0%B5%D0%BA%D1%83%D0%BD,_%D0%AF%D0%BD Яном Лекуном], изначально нацеленная на эффективное распознавание изображений.&lt;br /&gt;
&lt;br /&gt;
== Свертка ==&lt;br /&gt;
[[Файл:Convolution_example.png|upright=1.5|thumb|Пример свертки двух матриц размера 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;&amp;lt;}}двигается{{&amp;gt;&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;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Convolution_example.png&amp;diff=67995</id>
		<title>Файл:Convolution example.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Convolution_example.png&amp;diff=67995"/>
				<updated>2018-12-21T09:31:07Z</updated>
		
		<summary type="html">&lt;p&gt;Slavam2605: Пример свертки двух матриц&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Пример свертки двух матриц&lt;/div&gt;</summary>
		<author><name>Slavam2605</name></author>	</entry>

	</feed>