\chapter*{Выбор архитектуры нейронной сети} \addcontentsline{toc}{chapter}{Выбор архитектуры нейронной сети} % Добавляем введение в оглавление \section{Super Resolution Convolutional Neural Network (SRCNN)} Использование сверточных нейронных сетей для данной работы является стандартом, поэтому и начать стоит с нее. Super Resolution Convolutional Neural Network\cite{DongLHT15} является одним из популярных решений для данной задачи. Архитектура сверточной нейронной сети (рис. \ref{fig:screenshot001})представлена в виде 3 слоев, входного слоя с 3 входами для каждого цвета и 64 фичами, после которых идет один скрытый сверточный слой и один выходной слой. В данном случае, первый слой извлекает набор фич из изображения, в то время, как второй слой нелинейно размечает данные фичи на патчи с высоким разрешением, а последний слой комбинирует предсказания с оценкой окружающих патчей и отдает на выход изображение с повышенным разрешением. \begin{figure}[h!] \centering \includegraphics[width=0.8\linewidth]{screenshot001} \caption{Архитектура нейронной сети SRCNN \cite{DongLHT15}} \label{fig:screenshot001} \end{figure} Стоит отметить, что в данной архитектуре входное изображение уже должно быть нужного разрешения, увеличивая вычислительную сложность нейронной сети. Что является потенциальным решающим фактором в пользу более продвинутых реализаций методов повышения разрешения. \begin{lstlisting}[ style=compactpython, caption=Протестированная реализация SRCNN, label={lst:SRCNN} ] class SimpleSuperResolutionNet(nn.Module): def __init__(self, kernel_size=3, n_feats=64, colors=3): super(SimpleSuperResolutionNet, self).__init__() self.conv = nn.Conv2d( colors, n_feats, kernel_size=kernel_size, padding=kernel_size//2) half_feats = n_feats//2 self.conv2 = nn.Conv2d( n_feats, half_feats, kernel_size=kernel_size, padding=kernel_size//2) self.conv3 = nn.Conv2d( half_feats, colors, kernel_size=kernel_size, padding=kernel_size//2) def forward(self, x): x = torch.relu(self.conv(x)) x = torch.relu(self.conv2(x)) x = self.conv3(x) return x \end{lstlisting} Можно увидеть в листинге \ref{lst:SRCNN}, что размер ядра был выбран отличным от представленных в работе, связано это с тем, что при обучении на наших тестовых данных, одинаковое ядро показало лучшие результаты, в сравнении с оригинальными. \section{Fast Super Resolution Convolutional Neural Network (FSRCNN)} sdada \section{Enhanced Deep Super Resolution (EDSR)} Некоторым продвижением в задаче повышения разрешения можно считать применение в сверточных нейронных сетях остаточных блоков.\cite{he2016deep} В ключевой реализации \cite{LimSKNL17} была предложена архитектура состоящая из большого количества скрытых остаточных блоков (рис. \ref{fig:resblockedsr}), после начального входного слоя. % TODO: \usepackage{graphicx} required \begin{figure}[h!] \centering \includegraphics[width=0.2\linewidth]{res_block_edsr} \caption[Структура остаточного блока в сети EDSR]{} \label{fig:resblockedsr} \end{figure} В отличии от стандартных остаточных блоков, использованных в ResNet \cite{HeZRS15}, в EDSR из остаточного блока удален блок пакетной нормализации, так как данный блок может быть нежелательным в данной задаче % TODO: \usepackage{graphicx} required \begin{figure}[h!] \centering \includegraphics[width=0.6\linewidth]{edsr_arch} \caption[Архитектура нейронной сети EDSR \cite{LimSKNL17}]{} \label{fig:edsrarch} \end{figure} Были проверены две реализации: "state-of-the-art", предоставленная авторами статьи, уже предобученная модель, а также своя реализация по образу и подобию предоставленной авторами. Сеть состояла из 8 остаточных блоков, в каждом из которых было по 64 фичи, с ядром размера 3х3, и значением множителя 0.1 \begin{lstlisting}[ style=compactpython, caption=Структура остаточного блока, label={lst:ResBlock} ] class ResidualBlock(nn.Module): def __init__(self, n_feats, kernel_size, bias=True, bn=False, act=nn.ReLU(True), res_scale=1.0): super(ResidualBlock, self).__init__() m = [] for i in range(2): m.append(nn.Conv2d(n_feats, n_feats, kernel_size, padding=(kernel_size//2), bias=bias)) if bn: m.append(nn.BatchNorm2d(n_feats)) if i == 0: m.append(act) self.body = nn.Sequential(*m) self.res_scale = res_scale def forward(self, x): res = self.body(x).mul(self.res_scale) res += x return res \end{lstlisting}