190 lines
10 KiB
TeX
190 lines
10 KiB
TeX
\documentclass[]{article}
|
||
\usepackage[T1]{fontenc}
|
||
\usepackage{polski}
|
||
\usepackage[utf8]{inputenc}
|
||
\usepackage[margin=1.25in]{geometry}
|
||
\usepackage{alltt}
|
||
\usepackage{titling}
|
||
\usepackage{pdfpages}
|
||
\usepackage{float}
|
||
\usepackage{amsmath}
|
||
\usepackage{booktabs}
|
||
\usepackage{tabularx}
|
||
\usepackage{amstext}
|
||
\usepackage{pgfplots}
|
||
\usepackage{tikz}
|
||
\usepackage{xspace}
|
||
\usepackage{enumerate}
|
||
\usepackage{lmodern}
|
||
\usepackage{amsfonts}
|
||
\usepackage{mathtools}
|
||
\usepackage{graphicx}
|
||
\usepackage{algorithm}
|
||
\usepackage{algpseudocode}
|
||
\usepackage{wrapfig}
|
||
\usepackage[polish]{babel}
|
||
\usepackage{etoolbox}
|
||
\usepackage{subcaption}
|
||
\usepackage{multirow} % kurwa
|
||
|
||
\pgfplotsset{compat=1.15}
|
||
\usepgfplotslibrary{groupplots}
|
||
|
||
\DeclarePairedDelimiter\ceil{\lceil}{\rceil}
|
||
\DeclarePairedDelimiter\floor{\lfloor}{\rfloor}
|
||
|
||
\usetikzlibrary{decorations.pathmorphing, arrows.meta, positioning}
|
||
\usetikzlibrary{shapes.geometric, arrows, intersections}
|
||
\usetikzlibrary{external}
|
||
\tikzexternalize
|
||
|
||
\pgfdeclarelayer{background}
|
||
\pgfdeclarelayer{foreground}
|
||
\pgfsetlayers{background,main,foreground}%
|
||
|
||
% opening
|
||
\title{Retusz starych zdjęć \\ \small{Projekt ze Sztzucznej Inteligencji, WETI, PG 2018}}
|
||
\author{\protect\begin{tabular}{ll|l}
|
||
Szymon Szczyrbak & \textit{165760} & Informatyka 2016/2017 \\
|
||
Kacper Donat & \textit{165581} & Semestr IV, gr. 1
|
||
\protect\end{tabular}}
|
||
\floatname{algorithm}{Program}
|
||
|
||
\makeatletter
|
||
\newcommand{\imgresult}[1]{%
|
||
\gdef\tablerow{
|
||
\includegraphics[height=1.6cm]{out/#1_damaged.jpg} &%
|
||
\foreach \v in {damaged,1,2,4,8,16,32,64,128,200} {%
|
||
\includegraphics[height=1.6cm]{out/#1_\v.jpg} &%
|
||
}%
|
||
\includegraphics[height=1.6cm]{out/#1_ok.jpg} \\%
|
||
}%
|
||
}
|
||
\makeatother
|
||
|
||
\begin{document}
|
||
\maketitle
|
||
\section{Cel projektu}
|
||
Celem projektu było przygotowanie programu, który w sposób automatyczny umożliwiałby retuszowanie starych zdjęć z
|
||
wykorzystaniem technik sztucznej inteligencji.
|
||
|
||
\begin{figure}[H]
|
||
\centering
|
||
\includegraphics{./oczekiwane.jpg}
|
||
\caption{Oczekiwany rezultat działania aplikacji}
|
||
\end{figure}
|
||
|
||
Do realizacji celu zdecydowano się wykorzystać technikę GAN\footnote{https://arxiv.org/abs/1406.2661} zakładającą
|
||
stworzenie 2 sieci neuronowych, próbujących się wzajemnie oszukać. Jedna sieć - Generator - odpowiada za generowanie danych na
|
||
podstawie wektora wejściowego (w tym wypadku uszkodzonego zdjęcia) starając się przekonać drugą sieć -
|
||
Dyskryminatora - że jest to nieuszkodzone zdjęcie.
|
||
|
||
\subsection{Pozyskanie datasetu}
|
||
Jednym z problemów, na które natknęliśmy się podczas opracowywania rozwiązania był brak dostępnego wystarczająco
|
||
dużego datasetu, mogącego posłużyc do wyuczenia sieci. aby poradzić sobie z tym problemem została napisana aplikacja
|
||
umożliwająca generyczne niszczenie zdjęć.
|
||
|
||
\begin{figure}[H]
|
||
\centering
|
||
\begin{tikzpicture}[node distance=1.5cm]
|
||
\node (in) {\includegraphics[height=2cm]{steps/in.jpg}};
|
||
\node[right=of in] (sepia) {\includegraphics[height=2cm]{steps/sepia.jpg}};
|
||
\node[right=of sepia] (brightness) {\includegraphics[height=2cm]{steps/brightness.jpg}};
|
||
\node[below=of in] (noise) {\includegraphics[height=2cm]{steps/noise.jpg}};
|
||
\node[right=of noise] (decals) {\includegraphics[height=2cm]{steps/decals.jpg}};
|
||
\node[right=of decals] (blur) {\includegraphics[height=2cm]{steps/blur.jpg}};
|
||
|
||
\draw [->] (in) -- node [above] {sepia} (sepia);
|
||
\draw [->] (sepia) -- node [above] {jasność} (brightness);
|
||
\draw [->] (brightness) -- node [sloped, above] {szum} (noise);
|
||
\draw [->] (noise) -- node [above] {zniszczenia} (decals);
|
||
\draw [->] (decals) -- node [above] {rozmycie} (blur);
|
||
\end{tikzpicture}
|
||
\caption{Proces niszczenia zdjęć}
|
||
\end{figure}
|
||
|
||
Każdy z kroków jest parametryzowalny, oraz każde zdjęcie zawiera losową zmianę do parametru w celu zapobiegnięcia
|
||
zbyt szybkiemu overfittingowi sieci.
|
||
|
||
\subsection{Architektura modelu GAN}
|
||
Technika GAN zakłada jednoczesne uczenie dwóch modelów: generatora i dyskryminatora. W niniejszym projekcie dla generatora wejściem jest uszkodzone zdjęcie i wyjsciem jest zdjęcie po retuszu, a dla dyskryminatora wejściem jest zdjęcie po retuszu, a wyjściem jest mapa wartości od $0.0$ do $1.0$ oceniających prawdopodobieństwo przynależności wejściowego zdjęcia do datasetu zawierającego prawidłowo wyretuszowane zdjęcia.
|
||
|
||
Dyskryminator to sztuczna sieć neuronowa składająca się z czterech warstw konwolucyjnych (filtr 4x4x3, krok 1x1 i liczba map aktywacji dla pierwszej warstwy równa 32 i dla kolejnych dwukrotnie większa od liczby warstwy poprzedniej) i dodatkowej warstwy wyjściowej zwracającej jedną mapę o głębokości 1. W warstwach ukrytych po konwolucji wykonywana jest normalizacja. We wszystkich warstwach opróch warstwy wyjściowej stosowana jest funkcja aktywacyji LeakyReLU o $\alpha = 0.2$. W warstwie wyjściowej zastosowano funckję aktywacji Sigmoid.
|
||
|
||
Generator składa się identycznie tak jak dyskryminator z czterech warstw konwolucyjnych oraz dodatkowych lustrzanie zbudowanych warstw dekonwolucyjnych. W warstwie wyjściowej przed dekonwolucją stosowana się dodatkowa funkcja aktywacyji LeakyReLU, a po dekonwolucji zastosowano funkcję aktywacyji tanh.
|
||
|
||
Obie sieci neuronowe są uczone dostarczonym przez bibliotekę PyTorch algorytmem Adam o tempie uczenia $lr = 0.0002$.
|
||
Użyte funkcje straty generatora $G_{loss}$ i dyskryminatora $D_{loss}$ zdefiniowano poprzez funkcje straty L1 oraz Binary Cross-Entropy jako:
|
||
$$G_{loss} = BCE(D(G(x), real) + \lambda L1(G(x), y)$$
|
||
$$D_{loss} = BCE(D(y),real_{smooth}) + BCE(D(G(x)),fake_{smooth})$$
|
||
gdzie $x$ to zniszczone zdjęcie z datasetu, a $y$ to wyretuszowane zdjęcie z datasetu. $real$ to mapa wartości $1.0$ opisująca perfekcyjnie zretuszowanie zdjęcia, a $fake$ to analogiczna mapa samych $0.0$.
|
||
Dodanie do funkcji straty generatora sterowanej parametrem $\lambda = 100$ straty L1 zdaje się zapobiegać nauce oszukiwania dyskryminatora poprzez manipulacje kolorem palety barw zdjęcia.
|
||
Jako że dyskryminator uczy się oceniać jakość retuszu znacznie szybciej, niż generator uczy się dobrze retuszować, spowolniono szybkość jego nauki techniką znaną jako label smoothing dodając do $real$ i $fake$ losowy szum z zakresu kolejno od $-0.3$ do $0.2$ oraz od $0.0$ do $0.3$, w wyniku uzyskując $real_{smooth}$ i $fake_{smooth}$.
|
||
|
||
|
||
|
||
\section{Rezultaty}
|
||
\begin{center}\textit{\color{red} wstaw budowę sieci plox
|
||
- nope jest textowo opisana}\end{center}
|
||
|
||
\begin{figure}[H]
|
||
\centering
|
||
\begin{tikzpicture}
|
||
\begin{axis}[grid=both, width=\linewidth, height=8cm, no marks, xmin=0, xmax=200, xlabel={Epoka}, ylabel={Strata}]
|
||
\addplot[very thin, blue] table [x=epoch,y=g,col sep=comma] {iterations.csv};
|
||
\addplot[very thick] table [x=epoch,y=g,col sep=comma] {loss.csv};
|
||
\end{axis}
|
||
\end{tikzpicture}
|
||
\caption{Funkcja straty dla generatora}
|
||
\label{fig:results}
|
||
\end{figure}
|
||
|
||
\begin{figure}[H]
|
||
\centering
|
||
\begin{tikzpicture}
|
||
\begin{axis}[grid=both, width=\linewidth, height=8cm, no marks, xmin=0, xmax=200, xlabel={Epoka}, ylabel={Strata}]
|
||
\addplot[very thin, red] table [x=epoch,y=d,col sep=comma] {iterations.csv};
|
||
\addplot[very thick] table [x=epoch,y=d,col sep=comma] {loss.csv};
|
||
\end{axis}
|
||
\end{tikzpicture}
|
||
\caption{Funkcja straty dla dyskryminatora}
|
||
\end{figure}
|
||
|
||
\begin{table}[H]
|
||
\centering
|
||
\def\arraystretch{.6}
|
||
\setlength{\tabcolsep}{0pt} % for the horizontal padding
|
||
\begin{tabular}{cccccccccccc}
|
||
zniszczone & 1 & 2 & 4 & 8 & 16 & 32 & 64 & 128 & 200 & oczekiwane \tabularnewline \hline
|
||
\input{table.tex}
|
||
\end{tabular}
|
||
\caption{Zestawienie wyników dla kolejnych epok, zdjęcia z 3 oraz 4 rzędu pochodzą z internetu, pozostałe zostały zniszczone generycznie}
|
||
\end{table}
|
||
|
||
\subsection{Obserwacje}
|
||
Powyższe dane zostały pozyskane z uczenia sieci na datasecie zawierajacym 100 różnych elementów. W zestawieniu
|
||
\ref{fig:results} wyraźnie widać, że wraz z każdą generacją generator osiąga coraz lepsze wyniki jednak, od pewnego
|
||
momentu szybkość uczenia się zdecydowanie maleje.
|
||
|
||
\subsection{Problemy}
|
||
Głównym blokujący problemem podczas rozwijania projektu były niezwykle długie czasy uczenia się sieci na CPU, oraz
|
||
dość wysoka podatność na zmiany w parametrach sieci czy wygenerowanego datasetu, nie pozwoliło to na zrobienie zbyt
|
||
wielu iteracji programu, a tym samym na jego skuteczny rozwój.
|
||
|
||
Wyraźnie również widać przekolorowanie na obrazkach oraz zmianę jasności - prawdopodobnie oba te problemy wynikają z
|
||
zastosowania normalizacji zarówno wektora wejściowego jak i na poszczególnych etapach Generatora oraz przy konwersji
|
||
z tensorów, którymi posługuje się do obrazów.
|
||
|
||
Po sprawdzeniu kilku różnych zestawu danych do uczenia się, można zauważyć, że efekty na obrazach pochodzących z
|
||
realnego śiata są do siebie bardzo podobne, co wskazywałoby na relatywną stabilność rozwiązania i problem ze
|
||
sposobem generowania danych, który dostarcza zbyt mało różnorodne wejście. Problem ten można by rozwiązać
|
||
wykorzystując dataset zbudowany na podstawie kilku różnych metod generowania zniszczeń, bądź najlepiej wykorzystując
|
||
dane pochodzące z realnego świata.
|
||
|
||
Dodatkową trudnością jest fakt, że sieć nie tylko musi nauczyć się generować brakujące części obrazu ale też
|
||
decydować, które części są uszkodzeniem, a które detalem do zachowania. Problem ten widać w 3 wierszu prezentowanych
|
||
danych - wzór na koszuli został uznany za uszkodzenie i usunięty przez sieć.
|
||
\end{document}
|
||
|
||
|