\begin{frame}{Čo je neurónová sieť?}
  \begin{itemize}
    \item Matematický model inšpirovaný ľudským mozgom
    \item Skladá sa z neurónov usporiadaných do vrstiev
    \item Vstupná vrstva $\rightarrow$ skryté vrstvy $\rightarrow$ výstupná vrstva
    \item Každé spojenie má váhu $w$ --- sieť sa učí úpravou týchto váh
  \end{itemize}
\end{frame}

\input{1.tex}

\begin{frame}{Ako sa sieť učí?}
  \begin{enumerate}
    \item \textbf{Forward pass} --- dáta prechádzajú sieťou, dostaneme predikciu
    \item \textbf{Loss} --- zmeriame, ako veľmi sa sieť mýli
    \item \textbf{Backpropagation} --- spočítame gradienty (derivácie chyby podľa váh)
    \item \textbf{SGD update} --- upravíme váhy v smere najväčšieho poklesu chyby:
  \end{enumerate}
  \vspace{0.5em}
  \begin{equation}
    w \leftarrow w - \eta \cdot \frac{\partial L}{\partial w}
  \end{equation}
  \begin{center}
    kde $\eta$ je \textit{learning rate}
  \end{center}
\end{frame}

\begin{frame}{Aktivačné funkcie}
  Bez aktivačných funkcií by bola celá sieť len lineárna transformácia.

  \vspace{0.5em}
  \textbf{ReLU} --- najpoužívanejšia funkcia:
  \begin{equation}
    \texttt{ReLU}(x) = \max(0, x)
  \end{equation}

  \textbf{Softmax} --- na výstupe pre klasifikáciu:
  \begin{equation}
    \texttt{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}
  \end{equation}
  Výstupom je pravdepodobnostné rozdelenie cez triedy.
\end{frame}

{
\usebackgroundtemplate{
  \vbox to \paperheight{
    \vfill
    \hbox to \paperwidth{
      \hfill
      \includegraphics[height=0.35\paperheight]{obrazky/burn_logo.png}
    }
    \vspace{1.8cm} 
  }
}

\begin{frame}{Burn framework}
  \begin{itemize}
    \item Deep learning framework napísaný v Ruste
    \item Cieľ: byť pre Rust tým, čím je PyTorch pre Python
    \item Kľúčové vlastnosti:
    \begin{itemize}
      \item Backend-agnostický dizajn
      \item Typová bezpečnosť v compile-time
      \item Automatická diferenciácia (autodiff)
      \item Podpora pre CPU, CUDA, WebGPU, \dots
    \end{itemize}
  \end{itemize}
\end{frame}
}

\begin{frame}{Burn --- Backend systém}
  Burn oddeľuje logiku modelu od hardvéru:

  \vspace{0.5em}
  \begin{center}
    \texttt{Tensor<B, 2>} --- \texttt{B} je generický backend
  \end{center}

  \vspace{0.5em}
  \begin{itemize}
    \item \texttt{NdArray} --- Rust, CPU, žiadne závislosti
    \item \texttt{Wgpu} --- GPU cez WebGPU (cross-platform)
    \item \texttt{LibTorch} --- wrapper nad C++ LibTorch (CUDA)
    \item \texttt{Candle} --- Hugging Face backend
  \end{itemize}

  \vspace{0.5em}
  Ten istý kód beží na CPU aj GPU --- stačí zmeniť typ.
\end{frame}

\begin{frame}[fragile]{Backend sa mení jedným riadkom}
\begin{lstlisting}[language=Rust, style=colouredRust]
// CPU, Rust, žiadne závislosti
type B = NdArray;

// GPU cez WebGPU, cross-platform
type B = Wgpu;

// NVIDIA GPU cez LibTorch
type B = LibTorch;
\end{lstlisting}
  \vspace{0.5em}
  Zvyšok kódu sa nemení --- model, tréning, inferencia,
  všetko zostáva rovnaké.
\end{frame}

\begin{frame}{Ako Burn pristupuje k tenzorom}
  Tenzor v Burn nesie informáciu o type počas kompilácie:
  \vspace{0.5em}
  \begin{itemize}
    \item \texttt{Tensor<B, 1>} --- vektor
    \item \texttt{Tensor<B, 2>} --- matica
    \item \texttt{Tensor<B, 3>} --- 3D tenzor (napr. batch obrázkov)
  \end{itemize}
  \vspace{0.5em}
  Ak sa pokúsite násobiť maticu s vektorom nesprávnych rozmerov,
  kompilátor to zastaví ešte pred spustením.
\end{frame}

\begin{frame}[fragile]{Ako vyzerá model v Burn}
\begin{lstlisting}[language=Rust, style=colouredRust]
#[derive(Module)]
pub struct MnistModel<B: Backend> {
    linear1: Linear<B>,
    linear2: Linear<B>,
    activation: Relu,
}
\end{lstlisting}]
  \vspace{0.5em}
  Derive makro \texttt{Module} automaticky vygeneruje:
  \begin{itemize}
    \item Zber všetkých parametrov na tréning
    \item Serializáciu a deserializáciu modelu
    \item Presun medzi zariadeniami (CPU $\leftrightarrow$ GPU)
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Forward pass}
\begin{lstlisting}[language=Rust, style=colouredRust]
fn forward(&self, x: Tensor<B, 2>) -> Tensor<B, 2> {
    let x = self.linear1.forward(x);
    let x = self.activation.forward(x);
    self.linear2.forward(x)
}
\end{lstlisting}

\end{frame}

\begin{frame}{Ako funguje autodiff v Burn}
  Burn zabalí ľubovoľný backend do autodiff vrstvy:
  \vspace{0.5em}
  \begin{enumerate}
    \item Počas forward passu sa buduje výpočtový graf
    \item Každá operácia si pamätá, odkiaľ prišli dáta
    \item \texttt{loss.backward()} prejde graf nazad.
    \item Výsledok: gradient pre každý parameter
  \end{enumerate}
  \vspace{0.5em}
  Typ rozlišuje fázy --- \texttt{Autodiff<Wgpu>} na tréning a \texttt{Wgpu} na inferenciu. 
\end{frame}

