jsplus quoi

This commit is contained in:
Laureηt 2023-08-22 14:05:23 +02:00
parent a5e617b177
commit 99d7012a4e
Signed by: Laurent
SSH key fingerprint: SHA256:kZEpW8cMJ54PDeCvOhzreNr4FSh6R13CMGH/POoO8DI
2 changed files with 135 additions and 86 deletions

BIN
assets/pvd-architecture.png (Stored with Git LFS)

Binary file not shown.

View file

@ -27,6 +27,7 @@
\usepackage{nomencl} \usepackage{nomencl}
\usepackage{caption} \usepackage{caption}
\usepackage{placeins} \usepackage{placeins}
\usepackage{calligra}
\usepackage{tikz} \usepackage{tikz}
\usepackage{pgf-pie} \usepackage{pgf-pie}
@ -90,6 +91,9 @@
\newacronym{n7}{ENSEEIHT}{École nationale supérieure d'électrotechnique, d'électronique, d'informatique, d'hydraulique et des télécommunications} \newacronym{n7}{ENSEEIHT}{École nationale supérieure d'électrotechnique, d'électronique, d'informatique, d'hydraulique et des télécommunications}
\newacronym{pfe}{PFE}{Projet de Fin d'Études} \newacronym{pfe}{PFE}{Projet de Fin d'Études}
\newacronym{mads}{MADS}{Mathematics Applied to Design and Simulation}
\newacronym{flex}{FLEX}{physics inFormed machine Learning and numerical EXploration}
\newacronym{dst}{DST}{Digital Sciences and Technologies}
\newacronym{ml}{ML}{Machine Learning} \newacronym{ml}{ML}{Machine Learning}
\newacronym{dl}{DL}{Deep Learning} \newacronym{dl}{DL}{Deep Learning}
@ -263,16 +267,14 @@ Safran Tech représente le centre de Recherche et Technologie de l'Innovation au
Les équipes de recherche au sein de Safran Tech ne sont pas directement soumises aux contraintes imposées par d'importants projets industriels. Par conséquent, elles ont la liberté de mener des projets de recherche tout en collaborant avec des laboratoires externes tels que l'ONERA, le Centre des Matériaux des Mines, ainsi que les équipes d'autres entreprises. Cette structure permet à Safran Tech de rester agile dans ses activités de recherche et de développement, en explorant des solutions novatrices sans les contraintes de projets industriels spécifiques. Les équipes de recherche au sein de Safran Tech ne sont pas directement soumises aux contraintes imposées par d'importants projets industriels. Par conséquent, elles ont la liberté de mener des projets de recherche tout en collaborant avec des laboratoires externes tels que l'ONERA, le Centre des Matériaux des Mines, ainsi que les équipes d'autres entreprises. Cette structure permet à Safran Tech de rester agile dans ses activités de recherche et de développement, en explorant des solutions novatrices sans les contraintes de projets industriels spécifiques.
% Ce stage a été réalisé au sein de l'équipe « Computational Applied Mathematics » du pôle « Modélisation \& Simulations ». L'équipe compte une quinzaine de personnes. Une moitié sont titulaires et l'autre se compose des doctorants et stagiaires. Le pôle compte une soixantaine de collaborateurs. Les membres permanents sont tous au moins docteurs et viennent pour beaucoup directement de la recherche (ONERA, Centre des Matériaux, Cachan, etc.).
\section{Contexte du stage} \section{Contexte du stage}
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=16cm]{aube.jpg} \includegraphics[width=16cm]{aube.jpg}
\caption{Aubes du moteur Leap-1A} \caption{Aubes du moteur Leap-1A.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Copyright \href{https://medialibrary.safran-group.com/Photos/media/179440}{Cyril Abad / CAPA Pictures / Safran}} \caption*{Copyright \href{https://medialibrary.safran-group.com/Photos/media/179440}{Cyril Abad / CAPA Pictures / Safran}.}
\end{figure} \end{figure}
Dans le domaine industriel, les codes de simulation numérique sont désormais un outil indispensable pour la conception de systèmes complexes, en particulier pour les modules de réacteurs d'avions ou d'hélicoptères. Dans le domaine industriel, les codes de simulation numérique sont désormais un outil indispensable pour la conception de systèmes complexes, en particulier pour les modules de réacteurs d'avions ou d'hélicoptères.
@ -325,9 +327,9 @@ Les graphes offrent une représentation intuitive de diverses structures telles
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{example-graphs.jpg} \includegraphics[width=0.8\textwidth]{example-graphs.jpg}
\caption{Exemple de graphes} \caption{Exemple de graphes.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://blogs.nvidia.com/blog/2022/10/24/what-are-graph-neural-networks/}{NVIDIA, 2022}} \caption*{Source: \href{https://blogs.nvidia.com/blog/2022/10/24/what-are-graph-neural-networks/}{NVIDIA, 2022}.}
\label{fig:graph_example} \label{fig:graph_example}
\end{figure} \end{figure}
@ -349,14 +351,14 @@ Les modèles génératifs sont une famille de modèles qui permettent de génér
Il existe plusieurs sous familles de modèles génératifs, chacune basées sur des principes différents, possédant ainsi des avantages et des inconvénients. Il est donc important de bien comprendre les différences entre ces modèles pour pouvoir choisir le modèle le plus adapté à la problématique. Plusieurs études ont déjà été réalisées pour comparer ces modèles, nous nous baserons donc partiellement sur ces études~\cite{faez_deep_2020,guo_systematic_2022,zhu_survey_2022} pour présenter les modèles les plus pertinents pour notre problématique. Il existe plusieurs sous familles de modèles génératifs, chacune basées sur des principes différents, possédant ainsi des avantages et des inconvénients. Il est donc important de bien comprendre les différences entre ces modèles pour pouvoir choisir le modèle le plus adapté à la problématique. Plusieurs études ont déjà été réalisées pour comparer ces modèles, nous nous baserons donc partiellement sur ces études~\cite{faez_deep_2020,guo_systematic_2022,zhu_survey_2022} pour présenter les modèles les plus pertinents pour notre problématique.
\begin{figure}[h!] % \begin{figure}[h!]
\centering % \centering
\includegraphics[width=0.8\textwidth]{generative-overview.png} % \includegraphics[width=0.8\textwidth]{generative-overview.png}
\caption{Principales familles de modèles génératifs} % \caption{Principales familles de modèles génératifs}
\vspace*{-11pt} % \vspace*{-11pt}
\caption*{Source: \href{https://lilianweng.github.io/posts/2021-07-11-diffusion-models/}{Lilian Weng, 2021}} % \caption*{Source: \href{https://lilianweng.github.io/posts/2021-07-11-diffusion-models/}{Lilian Weng, 2021}}
\label{fig:generative_models} % \label{fig:generative_models}
\end{figure} % \end{figure}
\FloatBarrier \FloatBarrier
\glsunset{gan} \glsunset{gan}
@ -365,9 +367,9 @@ Il existe plusieurs sous familles de modèles génératifs, chacune basées sur
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{gan-architecture.png} \includegraphics[width=0.8\textwidth]{gan-architecture.png}
\caption{Architecture d'un \gls{gan}} \caption{Architecture d'un \gls{gan}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://lilianweng.github.io/posts/2017-08-20-gan/}{Lilian Weng, 2017}} \caption*{Source: \href{https://lilianweng.github.io/posts/2017-08-20-gan/}{Lilian Weng, 2017}.}
\label{fig:gan-architecture} \label{fig:gan-architecture}
\end{figure} \end{figure}
@ -390,9 +392,9 @@ Face à ces inconvénients, et puisque nous ne possédons pas de grandes quantit
\begin{figure}[h] \begin{figure}[h]
\centering \centering
\includegraphics[width=0.8\textwidth]{vae-architecture.png} \includegraphics[width=0.8\textwidth]{vae-architecture.png}
\caption{Architecture d'un \gls{vae}} \caption{Architecture d'un \gls{vae}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://lilianweng.github.io/posts/2018-08-12-vae/}{Lilian Weng, 2018}} \caption*{Source: \href{https://lilianweng.github.io/posts/2018-08-12-vae/}{Lilian Weng, 2018}.}
\label{fig:vae-architecture} \label{fig:vae-architecture}
\end{figure} \end{figure}
@ -431,9 +433,9 @@ Tout comme les \glspl{gan}, de nombreuses améliorations (β-VAE~\cite{burgess_u
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{nf-architecture.png} \includegraphics[width=0.8\textwidth]{nf-architecture.png}
\caption{Architecture d'un \gls{nf}} \caption{Architecture d'un \gls{nf}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://lilianweng.github.io/posts/2018-10-13-flow-models/}{Lilian Weng, 2018}} \caption*{Source: \href{https://lilianweng.github.io/posts/2018-10-13-flow-models/}{Lilian Weng, 2018}.}
\label{fig:nf-architecture} \label{fig:nf-architecture}
\end{figure} \end{figure}
@ -529,9 +531,9 @@ En supposant que $S_g$ et $S_r$ soient échantillonnés à partir de la même di
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{vdm-architecture.png} \includegraphics[width=0.8\textwidth]{vdm-architecture.png}
\caption{Architecture d'un \gls{vdm}} \caption{Architecture d'un \gls{vdm}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: Calvin Luo~\cite{luo_understanding_2022}} \caption*{Source: Calvin Luo~\cite{luo_understanding_2022}.}
\label{fig:vdm-architecture} \label{fig:vdm-architecture}
\end{figure} \end{figure}
@ -546,7 +548,7 @@ Dans leur architecture, les \glspl{vdm} peuvent être vus comme une chaine de Ma
\item Les paramètres de l'encodeur varient au cours du temps de sorte que la distribution latente à l'étape finale $T$ soit une gaussienne standard. \item Les paramètres de l'encodeur varient au cours du temps de sorte que la distribution latente à l'étape finale $T$ soit une gaussienne standard.
\end{itemize} \end{itemize}
On note $q$ les "encodeurs" et $p$ les "décodeurs" des \glspl{vae} de la chaine de Markov, $x_0 \sim \boldsymbol{x}_0$ un échantillon de notre distribution de données, $x_T \sim \boldsymbol{x}_T$ un échantillon d'une normale isotropique, et $x_t \sim \boldsymbol{x}_t$ tout échantillon intermédiaire, avec $t$ le temps de diffusion, $T$ le temps final de diffusion. On note $q$ les ``encodeurs" et $p$ les ``décodeurs" des \glspl{vae} de la chaine de Markov, $x_0 \sim \boldsymbol{x}_0$ un échantillon de notre distribution de données, $x_T \sim \boldsymbol{x}_T$ un échantillon d'une normale isotropique, et $x_t \sim \boldsymbol{x}_t$ tout échantillon intermédiaire, avec $t$ le temps de diffusion, $T$ le temps final de diffusion. On désigne également les transitions de $x_t$ à $x_{t+1}$ comme le``forward process", et les transition de $x_t$ à $x_{t-1}$ comme le ``reverse process".
D'après les contraintes précédentes, on peut écrire pour le forward process: D'après les contraintes précédentes, on peut écrire pour le forward process:
\begin{equation} \begin{equation}
@ -571,11 +573,16 @@ On peut finalement simplifier cette expression via une reparamétrisation:
\begin{equation} \begin{equation}
\boldsymbol{x}_0 = \frac{ \boldsymbol{x}_T - \sqrt{1 - \overline{\alpha}_t} \epsilon_0 } { \sqrt{\overline{\alpha}_t} } \implies \mu_q (\boldsymbol{x}_t, \boldsymbol{x}_0) = \frac{ 1 } { \sqrt{\alpha} } \boldsymbol{x}_t - \frac{ 1 - \alpha_t } { \sqrt{ 1 - \overline{\alpha}_t } \sqrt{\alpha_t} } \epsilon_0 \boldsymbol{x}_0 = \frac{ \boldsymbol{x}_T - \sqrt{1 - \overline{\alpha}_t} \epsilon_0 } { \sqrt{\overline{\alpha}_t} } \implies \mu_q (\boldsymbol{x}_t, \boldsymbol{x}_0) = \frac{ 1 } { \sqrt{\alpha} } \boldsymbol{x}_t - \frac{ 1 - \alpha_t } { \sqrt{ 1 - \overline{\alpha}_t } \sqrt{\alpha_t} } \epsilon_0
\end{equation} \end{equation}
Si l'on réeffectue une dérivation de l'\gls{elbo} avec ces nouvelles expressions, on en conclut qu'il suffit de trouver une approximation $\epsilon_\theta (\boldsymbol{x}_t, t) \approx \epsilon_0$. En pratique on utilise un réseau de neurones que l'on entraine à minimiser $|\| \epsilon_0 - \epsilon_\theta (\boldsymbol{x}_t, t) \|_2^2$. Une fois cette approximation trouvée, on peut facilement remonter à $p_\theta (\boldsymbol{x}_{t-1} | \boldsymbol{x}_t)$. Si l'on réeffectue une dérivation de l'\gls{elbo} avec ces nouvelles expressions, on en conclut qu'il suffit de trouver une approximation $\epsilon_\theta (\boldsymbol{x}_t, t) \approx \epsilon_0$. En pratique on utilise un réseau de neurones que l'on entraine à minimiser $|\| \epsilon_0 - \epsilon_\theta (\boldsymbol{x}_t, t) \|_2^2$. Une fois cette approximation trouvée, on peut facilement remonter à $p_\theta (\boldsymbol{x}_{t-1} | \boldsymbol{x}_t)$. Formellement, l'entrainement de ce réseau de neurones est décrit dans l'algorithme \ref{alg:ddpm_training}.
\begin{algorithm} \begin{algorithm}
\caption{DDPM training} \caption{DDPM training}
\label{alg:ddpm_training}
\begin{algorithmic}[1] \begin{algorithmic}[1]
\Require $T \in \mathbb{N}^\star$: number of diffusion steps
\Require $\boldsymbol{x}_0$: data distribution to be learned
\Require $\alpha_t$: variance schedule
\Require $\epsilon_\theta$: neural network
\Repeat \Repeat
\State $x_0 \sim \boldsymbol{x_0}$ \State $x_0 \sim \boldsymbol{x_0}$
\State $t \sim \text{Uniform}( \lbrack\!\lbrack 1, T \rbrack\!\rbrack )$ \State $t \sim \text{Uniform}( \lbrack\!\lbrack 1, T \rbrack\!\rbrack )$
@ -585,20 +592,26 @@ Si l'on réeffectue une dérivation de l'\gls{elbo} avec ces nouvelles expressio
\end{algorithmic} \end{algorithmic}
\end{algorithm} \end{algorithm}
Après avoir achevé l'entraînement adéquat de notre modèle, on peut désormais appliquer $p_\theta (\boldsymbol{x}_{t-1} | \boldsymbol{x}_t)$ itérativement pour passer d'un échantillon $x_T$ à sa prédiction $\hat{x}_0$. Dans les faits, le réseau commence à halluciner des reconstructions qui présentent une forte ressemblance avec nos données d'entraînement, il génère donc de nouvelles données. Formellement, l'échantillonnage est décrit dans l'algorithme \ref{alg:ddpm_sampling}.
\begin{algorithm} \begin{algorithm}
\caption{DDPM sampling} \caption{DDPM sampling}
\label{alg:ddpm_sampling}
\begin{algorithmic}[1] \begin{algorithmic}[1]
\Require $T \in \mathbb{N}^\star$: number of diffusion steps
\Require $\alpha_t$: variance schedule
\Require $\epsilon_\theta$: trained neural network
\State $x_T \sim \mathcal{N}(0, \mathbf{I})$ \State $x_T \sim \mathcal{N}(0, \mathbf{I})$
\For{$t=T, ..., 1$} \For{$t=T, ..., 1$}
\State $z \sim \mathcal{N}(0, \mathbf{I})\ \text{if}\ t > 1, \text{else}\ z = 0$ \State $\displaystyle \mu_t = \frac{ 1 } { \sqrt{\alpha} } \boldsymbol{x}_t - \frac{ 1 - \alpha_t } { \sqrt{ 1 - \overline{\alpha}_t } \sqrt{\alpha_t} } \epsilon_\theta(x_t, t)$
\State $\displaystyle x_{t-1} = \frac{1}{\sqrt{\overline{\alpha}_t}} \left( x_t - \frac{\sqrt{1 - \alpha_t}}{\sqrt{\overline{\alpha}_t}} \epsilon_\theta (x_t, t) \right) + \sigma_t z$ \State $\displaystyle \sigma_t = \sqrt{ \frac{ (1 - \alpha_t)(1 - \overline{\alpha}_{t-1}) } { 1 - \overline{\alpha}_t } }$
\State $\epsilon \sim \mathcal{N}(0, \mathbf{I})\ \text{if}\ t > 1, \text{else}\ \epsilon = 0$
\State $x_{t-1} = \mu_t + \sigma_t \epsilon$
\EndFor \EndFor
\State \Return $x_0$ \State \Return $x_0$
\end{algorithmic} \end{algorithmic}
\end{algorithm} \end{algorithm}
Après avoir achevé l'entraînement adéquat de notre modèle, on peut désormais appliquer $p_\theta (\boldsymbol{x}_{t-1} | \boldsymbol{x}_t)$ itérativement pour passer d'un échantillon $x_T$ à sa prédiction $\hat{x}_0$. Dans les faits, le réseau commence à halluciner des reconstructions qui présentent une forte ressemblance avec nos données d'entraînement, il génère donc de nouvelles données.
Il est possible de démontrer théoriquement~\cite{luo_understanding_2022} l'équivalence entre les \glspl{vdm} et les méthodes de score matching~\cite{song_generative_2020} lorsque $T$ tend vers l'infini. Les méthodes de score matching, constituent une famille de techniques permettant l'estimation de la densité de probabilité associée à un ensemble de données. Elles se basent exclusivement sur le calcul du gradient de cette densité de probabilité, éliminant ainsi la nécessité du calcul laborieux d'une constante de normalisation. Une fois le gradient estimé (e.g. via un réseau de neurones), la densité de probabilité peut être retrouvée au moyen de méthodes d'échantillonnage telles que la méthode de recuit de Langevin~\cite{song_generative_2020}. Il est possible de démontrer théoriquement~\cite{luo_understanding_2022} l'équivalence entre les \glspl{vdm} et les méthodes de score matching~\cite{song_generative_2020} lorsque $T$ tend vers l'infini. Les méthodes de score matching, constituent une famille de techniques permettant l'estimation de la densité de probabilité associée à un ensemble de données. Elles se basent exclusivement sur le calcul du gradient de cette densité de probabilité, éliminant ainsi la nécessité du calcul laborieux d'une constante de normalisation. Une fois le gradient estimé (e.g. via un réseau de neurones), la densité de probabilité peut être retrouvée au moyen de méthodes d'échantillonnage telles que la méthode de recuit de Langevin~\cite{song_generative_2020}.
\FloatBarrier \FloatBarrier
@ -608,9 +621,9 @@ Il est possible de démontrer théoriquement~\cite{luo_understanding_2022} l'éq
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=6cm]{ldm-compression.jpg}\hspace*{5mm}\includegraphics[width=10cm]{ldm-architecture.png} \includegraphics[width=6cm]{ldm-compression.jpg}\hspace*{5mm}\includegraphics[width=10cm]{ldm-architecture.png}
\caption{Architecture d'un \gls{ldm}} \caption{Architecture d'un \gls{ldm}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: Rombach \& Blattmann, et al.~\cite{rombach_high-resolution_2022}} \caption*{Source: Rombach \& Blattmann, et al.~\cite{rombach_high-resolution_2022}.}
\label{fig:ldm-architecture} \label{fig:ldm-architecture}
\end{figure} \end{figure}
@ -632,7 +645,7 @@ La première méthode est appelée Classifier Guidance~\cite{dhariwal_diffusion_
\nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t | y) & = \nabla_{\boldsymbol{x}_t} \log p \left( \frac{ p(\boldsymbol{x}_t) p(y | \boldsymbol{x}_t) }{ p(y) } \right) \\ \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t | y) & = \nabla_{\boldsymbol{x}_t} \log p \left( \frac{ p(\boldsymbol{x}_t) p(y | \boldsymbol{x}_t) }{ p(y) } \right) \\
& = \underbrace{ \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t) }_{\text{unconditional score}} + \underbrace{ \nabla_{\boldsymbol{x}_t} \log q (y | \boldsymbol{x}_t) }_{\text{adversarial gradient}} \label{eq:165} & = \underbrace{ \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t) }_{\text{unconditional score}} + \underbrace{ \nabla_{\boldsymbol{x}_t} \log q (y | \boldsymbol{x}_t) }_{\text{adversarial gradient}} \label{eq:165}
\end{align} \end{align}
Si l'on remplace $q( y | \boldsymbol{x}_t )$ par $f_\phi ( y | \boldsymbol{x}_t )$ on obtient, et que l'on introduit un facteur de guidage $\gamma$, on obtient: Si l'on remplace $q( y | \boldsymbol{x}_t )$ par $f_\phi ( y | \boldsymbol{x}_t )$ et que l'on introduit un facteur de guidage $\gamma \in \mathbb{R}$, on obtient:
\begin{align} \begin{align}
\nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t | y) & \approx \nabla_{\boldsymbol{x}_t} \log q (\boldsymbol{x}_t) + \gamma \nabla_{\boldsymbol{x}_t} \log f_\phi (y | \boldsymbol{x}_t) \label{eq:166} \\ \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t | y) & \approx \nabla_{\boldsymbol{x}_t} \log q (\boldsymbol{x}_t) + \gamma \nabla_{\boldsymbol{x}_t} \log f_\phi (y | \boldsymbol{x}_t) \label{eq:166} \\
& = - \frac{1}{ \sqrt{1 - \overline{\alpha}_t} }\epsilon_\theta(\boldsymbol{x}_t, t) + \gamma \nabla_{\boldsymbol{x}_t} \log f_\phi (y | \boldsymbol{x}_t) & = - \frac{1}{ \sqrt{1 - \overline{\alpha}_t} }\epsilon_\theta(\boldsymbol{x}_t, t) + \gamma \nabla_{\boldsymbol{x}_t} \log f_\phi (y | \boldsymbol{x}_t)
@ -641,9 +654,9 @@ Si l'on remplace $q( y | \boldsymbol{x}_t )$ par $f_\phi ( y | \boldsymbol{x}_t
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{classifier-guidance.png} \includegraphics[width=0.8\textwidth]{classifier-guidance.png}
\caption{Conditionnement par Classifier Guidance} \caption{Conditionnement par Classifier Guidance.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://perceptron.blog/defusing-diffusion/}{Perceptron.blog, 2023}} \caption*{Source: \href{https://perceptron.blog/defusing-diffusion/}{Perceptron.blog, 2023}.}
\label{fig:classifier_guidance} \label{fig:classifier_guidance}
\end{figure} \end{figure}
@ -651,9 +664,9 @@ Si l'on remplace $q( y | \boldsymbol{x}_t )$ par $f_\phi ( y | \boldsymbol{x}_t
La seconde méthode est appelée Classifer-Free Guidance~\cite{ho_classifier-free_2022, nichol_glide_2022} et repose sur l'entraînement d'un unique réseau de neurones ayant pour objectif d'apprend à la fois la distribution conditionnelle et non conditionnelle. En réarrangeant l'équation \ref{eq:165}, on obtient: La seconde méthode est appelée Classifer-Free Guidance~\cite{ho_classifier-free_2022, nichol_glide_2022} et repose sur l'entraînement d'un unique réseau de neurones ayant pour objectif d'apprend à la fois la distribution conditionnelle et non conditionnelle. En réarrangeant l'équation \ref{eq:165}, on obtient:
\begin{equation} \begin{equation}
\nabla_{\boldsymbol{x}_t} \log p (y | \boldsymbol{x}_t) = \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t, y) - \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t) \nabla_{\boldsymbol{x}_t} \log p (y | \boldsymbol{x}_t) = \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t, y) - \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t) \label{eq:rearange}
\end{equation} \end{equation}
En subsituant l'équation \ref{eq:166} dans l'équation ci-dessus, on obtient: En subsituant l'équation \ref{eq:166} dans l'équation \ref{eq:rearange}, on obtient:
\begin{align} \begin{align}
\nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t | y) & = \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t) + \gamma ( \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t | y) - \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t) ) \\ \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t | y) & = \nabla_{\boldsymbol{x}_t} \log p (\boldsymbol{x}_t) + \gamma ( \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t | y) - \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t) ) \\
& = \underbrace{ \gamma \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t | y) }_{\text{conditional score}} + \underbrace{ (1 - \gamma) \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t) }_{\text{unconditional score}} & = \underbrace{ \gamma \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t | y) }_{\text{conditional score}} + \underbrace{ (1 - \gamma) \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t) }_{\text{unconditional score}}
@ -662,17 +675,23 @@ En subsituant l'équation \ref{eq:166} dans l'équation ci-dessus, on obtient:
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{classifier-free-guidance.png} \includegraphics[width=0.8\textwidth]{classifier-free-guidance.png}
\caption{Conditionnement par Classifier-free Guidance} \caption{Conditionnement par Classifier-free Guidance.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://perceptron.blog/defusing-diffusion/}{Perceptron.blog, 2023}} \caption*{Source: \href{https://perceptron.blog/defusing-diffusion/}{Perceptron.blog, 2023}.}
\label{fig:classifier_free_guidance} \label{fig:classifier_free_guidance}
\end{figure} \end{figure}
Cette approche présente divers avantages. Premièrement, elle s'appuie sur un unique réseau de neurones, contrairement à la méthode guidée par classificateur qui en utilise deux. Deuxièmement, l'entraînement ne devient pas significativement plus complexe ; nous procédons de la même manière qu'auparavant, en ajoutant simplement les embeddings de classe et en parfois excluant aléatoirement ces embeddings (selon une loi uniforme) pour apprendre en conditionnement non contraint. Troisièmement, les données telles que le texte se prêtent difficilement à une classification en classes, et cette approche permet l'utilisation de vecteurs scalaires pour le conditionnement. Cette approche présente divers avantages. Premièrement, elle s'appuie sur un unique réseau de neurones, contrairement à la méthode guidée par classificateur qui en utilise deux. Deuxièmement, l'entraînement ne devient pas significativement plus complexe; on procède de la même manière qu'auparavant, en ajoutant simplement les embeddings de classe et en parfois excluant aléatoirement ces embeddings (selon une loi uniforme) pour apprendre en conditionnement non contraint. Troisièmement, les données telles que le texte se prêtent difficilement à une classification en classes, et cette approche permet l'utilisation de vecteurs scalaires pour le conditionnement. Formellement, l'algorithme d'entraînement par \gls{cfg} est décrit dans l'algorithme \ref{alg:classifier-free-guidance}.
\begin{algorithm} \begin{algorithm}
\caption{DDPM training with classifier-free guidance} \caption{DDPM training with classifier-free guidance}
\label{alg:classifier-free-guidance}
\begin{algorithmic}[1] \begin{algorithmic}[1]
\Require $T \in \mathbb{N}^\star$: number of diffusion steps
\Require $\boldsymbol{x}_0$: data distribution to be learned
\Require $\boldsymbol{c}$: embeddings distribution to be learned
\Require $\alpha_t$: variance schedule
\Require $\epsilon_\theta$: neural network
\Require $p_\text{uncond}$: probability of unconditional training \Require $p_\text{uncond}$: probability of unconditional training
\Repeat \Repeat
\State $(x_0, c) \sim (\boldsymbol{x_0}, \boldsymbol{c})$ \State $(x_0, c) \sim (\boldsymbol{x_0}, \boldsymbol{c})$
@ -699,9 +718,9 @@ Dans notre cas d'application, nous pouvons conditionner sur les scalaires repré
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{arm-architecture.png} \includegraphics[width=0.8\textwidth]{arm-architecture.png}
\caption{Architecture d'un \gls{arm}} \caption{Architecture d'un \gls{arm}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://colah.github.io/posts/2015-08-Understanding-LSTMs/}{Christopher Olah, 2015}} \caption*{Source: \href{https://colah.github.io/posts/2015-08-Understanding-LSTMs/}{Christopher Olah, 2015}.}
\label{fig:arm-architecture} \label{fig:arm-architecture}
\end{figure} \end{figure}
@ -716,9 +735,9 @@ Les modèles auto-régressifs sont des méthodes de génération de séquences q
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{nerf-architecture.png} \includegraphics[width=0.8\textwidth]{nerf-architecture.png}
\caption{Architecture d'un \gls{nerf}} \caption{Architecture d'un \gls{nerf}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: \href{https://theaisummer.com/nerf/}{AI Summer, 2022}} \caption*{Source: \href{https://theaisummer.com/nerf/}{AI Summer, 2022}.}
\label{fig:nerf-architecture} \label{fig:nerf-architecture}
\end{figure} \end{figure}
@ -735,7 +754,9 @@ Dans notre cas, étant donné que notre jeu de données n'est pas adapté à l'a
\FloatBarrier \FloatBarrier
\chapter{Déroulement du stage} \chapter{Déroulement du stage}
Ce chapitre présente un aperçu détaillé du déroulement de mon stage de 6 mois (Du 21 Mars 2023 au 21 Septembre 2023) au sein de Safran. Tout au long de cette période, j'ai travaillé en tant que Stagiaire Ingénieur en Machine Learning au sein du département Safran Tech, dans l'équipe flex (chercher acronyme bidule), dont le but est de développer des outils de simulation et de modélisation pour les besoins de Safran. J'ai été encadré par Xavier Roynard, Michel Alessandro Bucci et Brian Staber. Ce chapitre présente un aperçu détaillé du déroulement de mon stage de 6 mois (Du 21 Mars 2023 au 21 Septembre 2023) au sein de Safran.
Tout au long de cette période, j'ai travaillé en tant que Stagiaire Ingénieur de Recherche en Machine Learning au sein du département Safran Tech, dans la sous-équipe \gls{flex} de l'équipe \gls{mads} dans le département \gls{dst}, dont le but est de développer des outils de simulation et de modélisation pour les besoins de Safran.
J'ai été encadré par Xavier Roynard, Michel Alessandro Bucci et Brian Staber.
Je décrirai dans les prochaines sections les différentes étapes de mon stage, les tâches qui m'ont été confiées ainsi que les projets auxquels j'ai contribué. Je décrirai dans les prochaines sections les différentes étapes de mon stage, les tâches qui m'ont été confiées ainsi que les projets auxquels j'ai contribué.
@ -760,14 +781,14 @@ Le principal ensemble de données sur lequel j'ai travaillé pendant mon stage s
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{online_adaptative_sampling_DOE} \includegraphics[width=0.8\textwidth]{online_adaptative_sampling_DOE}
\caption{Processus d'optimisation ayant permis de générer l'ensemble de données Rotor37\_1200} \caption{Processus d'optimisation ayant permis de générer l'ensemble de données Rotor37\_1200.}
\label{fig:process-rotor37-1200} \label{fig:process-rotor37-1200}
\end{figure} \end{figure}
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=4.5cm]{rotor37_1.png}\includegraphics[width=4.5cm]{rotor37_2.png}\includegraphics[width=4.5cm]{rotor37_3.png} \includegraphics[width=4.5cm]{rotor37_1.png}\includegraphics[width=4.5cm]{rotor37_2.png}\includegraphics[width=4.5cm]{rotor37_3.png}
\caption{Échantillon de l'ensemble de données Rotor37\_1200 sous plusieurs angles} \caption{Échantillon de l'ensemble de données Rotor37\_1200 sous plusieurs angles.}
\label{fig:example-rotor37-1200} \label{fig:example-rotor37-1200}
\end{figure} \end{figure}
@ -784,7 +805,12 @@ Afin de simplifier le chargement des données, j'ai choisi d'utiliser la bibliot
En complément de Rotor37\_1200, j'ai également travaillé sur un ensemble de données plus grand appelé Rotor37\_11000, qui contient 11000 échantillons. Cet ensemble de données a été créé via le même processus d'optimisation que Rotor37\_1200, cepandant les déformations qu'il contient sont d'un ordre de grandeur plus élevé. En complément de Rotor37\_1200, j'ai également travaillé sur un ensemble de données plus grand appelé Rotor37\_11000, qui contient 11000 échantillons. Cet ensemble de données a été créé via le même processus d'optimisation que Rotor37\_1200, cepandant les déformations qu'il contient sont d'un ordre de grandeur plus élevé.
% TODO: insérer viz rotor37_11000 \begin{figure}[h!]
\centering
{\Huge \calligra Fuck Rosetta}
\caption{Échantillon de l'ensemble de données Rotor37\_11000 sous plusieurs angles.}
\label{fig:example-rotor37-11000}
\end{figure}
% parler de la simulation full, qui comporte plusieurs millions de points, ainsi que la nacelle ? % parler de la simulation full, qui comporte plusieurs millions de points, ainsi que la nacelle ?
@ -813,27 +839,32 @@ La stack technique utilisée par l'équipe est basée sur Python, avec des bibli
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{graphvae-architecture.png} \includegraphics[width=0.8\textwidth]{graphvae-architecture.png}
\caption{Architecture de GraphVAE} \caption{Architecture de GraphVAE.}
\label{fig:graphvae_archi} \label{fig:graphvae_archi}
\end{figure} \end{figure}
L'une de nos premières initiatives a été de tester des réseaux basés sur les \glspl{vae}. Après avoir lu des articles de recherche sur les \glspl{vae}, j'ai réalisé plusieurs implémentations sur des images pour me refamiliariser avec ces concepts. L'une de nos premières initiatives a été de tester des réseaux basés sur les \glspl{vae}. Après avoir lu des articles de recherche sur les \glspl{vae}, j'ai réalisé plusieurs implémentations sur des images pour me refamiliariser avec ces concepts.
Nous avons ensuite étendu ces expérimentations à des architectures spécifiques aux graphes via GraphVae~\cite{simonovsky_graphvae_2018}. Les résultats obtenus étaient encourageants: le réseau était capable de générer des structures, mais la qualité des générations n'était pas exceptionnelle. De plus, nous avons constaté que le réseau était beaucoup trop volumineux par rapport à sa fonctionnalité. Nous avons ensuite étendu ces expérimentations à des architectures spécifiques aux graphes via GraphVae~\cite{simonovsky_graphvae_2018}. Les résultats obtenus étaient encourageants: le réseau était capable de générer des structures, mais la qualité des générations n'était pas exceptionnelle. De plus, nous avons constaté que le réseau était beaucoup trop volumineux par rapport à sa fonctionnalité.
% TODO: insérer ici screen des résultats de graphvae \begin{figure}[h!]
\centering
{\Huge \calligra Fuck Rosetta}
\caption{Résultats d'un \gls{ldm} \gls{pca} sur rotor37\_1200.}
\label{fig:pca_ldm_results}
\end{figure}
En effet, dans le contexte des graphes, les opérations de "upsampling" n'existent pas de manière directe. Par conséquent, nous avons rencontré des difficultés lors du passage du vecteur latent (représentant une distribution gaussienne) à une représentation sous forme de graphe (noeuds + connectivité) dans le décodeur du \gls{vae}. En effet, dans le contexte des graphes, les opérations de "upsampling" n'existent pas de manière directe. Par conséquent, nous avons rencontré des difficultés lors du passage du vecteur latent (représentant une distribution gaussienne) à une représentation sous forme de graphe (noeuds + connectivité) dans le décodeur du \gls{vae}.
Une première solution simple consistait en l'utilisation de une ou plusieurs couches denses (\glspl{mlp}) pour convertir le vecteur latent en un couple de matrices décrivant les positions et la connectivité des noeuds. Cependant, cette approche posait problème en raison de la taille des graphes que nous manipulions. En effet, avec des graphes de $n=3.10^4$ nœuds, cela impliquait une matrice de connectivité de taille $n^2 = 9.10^8$, ce qui faisait aisaiment exploser la complexité lorsque nous utilisions des couches denses. Une première solution simple consistait en l'utilisation de une ou plusieurs couches denses (\glspl{mlp}) pour convertir le vecteur latent en un couple de matrices décrivant les positions et la connectivité des noeuds. Cependant, cette approche posait problème en raison de la taille des graphes que nous manipulions. En effet, avec des graphes de $n=3.10^4$ nœuds, cela impliquait une matrice de connectivité de taille $n^2 = 9.10^8$, ce qui faisait aisaiment exploser la complexité lorsque nous utilisions des couches denses.
Pour donner un ordre de grandeur, si l'on utilisai un espace latent de taille $8$, rien que pour prédire les positions 3D des points dans notre maillage (sans prendre en compte la connectivité), l'utilisation d'une seule couche dense impliquait déjà $8 \times 3.10^4 \times 3 = 7,2.10^6$ paramètres. Prédire la connectivité était tout simplement impossible, car il aurait fallu une couche dense avec plus de $8 \times 9.10^8 = 7,2.10^9$ paramètres, ce qui dépassait largement les capacités de calcul de nos ressources GPU. Pour donner un ordre de grandeur, si l'on utilisai un espace latent de taille $8$, rien que pour prédire les positions 3D des points dans notre maillage (sans prendre en compte la connectivité), l'utilisation d'une seule couche dense impliquait déjà $8 \times 3.10^4 \times 3 = 7,2.10^6$ paramètres. Prédire la connectivité était tout simplement impossible, car il aurait fallu une couche dense avec plus de $8 \times (3.10^4)^2 = 7,2.10^9$ paramètres, ce qui dépassait largement les capacités de calcul de nos ressources GPU.
Une seconde solution consitait à utiliser une architecture plus intelligente, telle que Graph U-Net~\cite{gao_graph_2019}. Cette approche permettait d'éviter l'utilisation de couches denses dans le décodeur grâce à des connexions résiduelles (skip connections). Cependant, ce faisant l'information ne passait pas entièrement par l'espace latent entre le décodeur et l'encodeur. Par conséquent, il était impossible de créer un modèle génératif complet avec cette architecture, puisqu'une partie de l'information pour générer des échantillons était compris dans les skip connections. Une seconde solution consitait à utiliser une architecture plus intelligente, telle que Graph U-Net~\cite{gao_graph_2019}. Cette approche permettait d'éviter l'utilisation de couches denses dans le décodeur grâce à des connexions résiduelles (skip connections). Cependant, ce faisant l'information ne passait pas entièrement par l'espace latent entre le décodeur et l'encodeur. Par conséquent, il était impossible de créer un modèle génératif complet avec cette architecture, puisqu'une partie de l'information pour générer des échantillons était compris dans les skip connections.
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{graphunet-architecture.png} \includegraphics[width=0.8\textwidth]{graphunet-architecture.png}
\caption{Architecture de Graph U-Net} \caption{Architecture de Graph U-Net.}
\label{fig:graphunet_archi} \label{fig:graphunet_archi}
\end{figure} \end{figure}
@ -844,7 +875,12 @@ Face aux difficultés rencontrées avec les réseaux basés sur les VAE et les l
L'approche la plus connue pour utilise des \glspl{nf} sur des nuages de points est PointFlow~\cite{yang_pointflow_2019}. Adapter l'implémentation originale afin d'y intégrer l'utilisation de Rotor37\_1200 s'est avéré être une tâche aisée, entraînant des résultats supérieurs à ceux obtenus par GraphVAE, bien que sans être exceptionnels. La structure du code s'est cependant révélée relativement difficile à manipuler pour toute autre tâche plus complexe (comme souvent avec du code académique). L'approche la plus connue pour utilise des \glspl{nf} sur des nuages de points est PointFlow~\cite{yang_pointflow_2019}. Adapter l'implémentation originale afin d'y intégrer l'utilisation de Rotor37\_1200 s'est avéré être une tâche aisée, entraînant des résultats supérieurs à ceux obtenus par GraphVAE, bien que sans être exceptionnels. La structure du code s'est cependant révélée relativement difficile à manipuler pour toute autre tâche plus complexe (comme souvent avec du code académique).
% TODO: insérer ici résultats \begin{figure}[h!]
\centering
{\Huge \calligra Fuck Rosetta}
\caption{Résultats de PointFlow sur rotor37\_1200.}
\label{fig:pointflow_results}
\end{figure}
PointFlow a néanmoins apporté une contribution significative à la création d'un dataset de référence pour la génération de nuages de points, qui est actuellement exploité par de multiples articles de recherche. Ce jeu de données repose sur ShapeNet~\cite{shapenet2015}, un ensemble de données dédiée à une variété d'objets en trois dimensions (tels que des avions, des chaises, des voitures, etc.), modifié par Furthest Point Sampling pour contenir uniquement 2048 points par nuages. PointFlow a néanmoins apporté une contribution significative à la création d'un dataset de référence pour la génération de nuages de points, qui est actuellement exploité par de multiples articles de recherche. Ce jeu de données repose sur ShapeNet~\cite{shapenet2015}, un ensemble de données dédiée à une variété d'objets en trois dimensions (tels que des avions, des chaises, des voitures, etc.), modifié par Furthest Point Sampling pour contenir uniquement 2048 points par nuages.
De plus, PointFlow a joué un rôle essentiel dans l'implémentation de différentes métriques et distances en CUDA, telles que la \gls{cd}, l'\gls{emd}, et bien d'autres. De plus, PointFlow a joué un rôle essentiel dans l'implémentation de différentes métriques et distances en CUDA, telles que la \gls{cd}, l'\gls{emd}, et bien d'autres.
@ -852,7 +888,7 @@ De plus, PointFlow a joué un rôle essentiel dans l'implémentation de différe
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.9\textwidth]{shapenet.png} \includegraphics[width=0.9\textwidth]{shapenet.png}
\caption{Exemple de datasets d'objets 3D} \caption{Exemple de datasets d'objets 3D.}
\label{fig:shapenet} \label{fig:shapenet}
\end{figure} \end{figure}
@ -870,7 +906,7 @@ Par la suite, une avancée significative du modèle PointNet a conduit à l'éme
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{pointnet-architecture.jpg} \includegraphics[width=0.8\textwidth]{pointnet-architecture.jpg}
\caption{Architecture de PointNet et PointNet++} \caption{Architecture de PointNet et PointNet++.}
\label{fig:pointnet_archi} \label{fig:pointnet_archi}
\end{figure} \end{figure}
@ -880,7 +916,7 @@ Par la suite, une avancée significative du modèle PointNet a conduit à l'éme
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{kpconv-architecture.png} \includegraphics[width=0.8\textwidth]{kpconv-architecture.png}
\caption{Architecture de KP-FCNN et KP-CNN, construit avec des \glspl{kpconv}} \caption{Architecture de KP-FCNN et KP-CNN, construit avec des \glspl{kpconv}.}
\label{fig:kpconv_archi} \label{fig:kpconv_archi}
\end{figure} \end{figure}
@ -901,20 +937,22 @@ Dans notre situation, nous avons la possibilité d'opter pour le réseau KP-FCNN
Comme on l'observe dans la figure~\ref{fig:kpfcnn_results}, cette architecture permet de générer des nuages de points en forme d'aube. Cependant, on remarque que les générations sont d'assez mauvaise qualité puisque les nuages de points semblent comporter une part de bruit résiduel importante. Certaines générations ne ressemblent de même pas du tout à des aubes, mais plutôt à des nuages de points aléatoires. Comme on l'observe dans la figure~\ref{fig:kpfcnn_results}, cette architecture permet de générer des nuages de points en forme d'aube. Cependant, on remarque que les générations sont d'assez mauvaise qualité puisque les nuages de points semblent comporter une part de bruit résiduel importante. Certaines générations ne ressemblent de même pas du tout à des aubes, mais plutôt à des nuages de points aléatoires.
Autre point négatif, le decodeur de KP-FCNN étant composé de \glspl{mlp}, il n'est pas scalable. En effet le réseau actuel comporte environ 4 millions de paramètres, dont une large majorité se situent dans le décodeur. Autre point négatif, le decodeur de KP-FCNN étant composé de \glspl{mlp}, il n'est pas scalable. En effet le réseau actuel comporte environ 4 millions de paramètres, dont une large majorité se situent dans le décodeur.
% TODO verif le nb de params
\FloatBarrier \FloatBarrier
\subsection{Présentation des \glspl{pvconv}} \subsection{Présentation des \glspl{pvconv}}
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{pvconv.png} \includegraphics[width=0.8\textwidth]{pvconv.png}
\caption{Architecture d'une \gls{pvconv}} \caption{Architecture d'une \gls{pvconv}.}
\label{fig:pvconv_archi} \label{fig:pvconv_archi}
\end{figure} \end{figure}
Une seconde alternative aux opérations de convolutions et d'aggregation de PointNet++ sont les \glspl{pvconv}~\cite{liu_point-voxel_2019}. Les \glspl{pvconv} proposent d'utiliser des voxels afin de retomber sur des structures régulières, permettant ainsi d'effectuer efficacement des convolutions classiques en 3D. Par conséquent, une \gls{pvconv} est composée de deux branches distinctes. La première branche, appelée "coarse-grained", transforme les points en voxels, applique des convolutions, puis reconvertit les voxels en points à l'aide d'une interpolation trilinéaire. La seconde branche, nommée "fine-grained", est constituée de shared \glspl{mlp}. Ces deux branches sont ensuite combinées par sommation. Une seconde alternative aux opérations de convolutions et d'aggregation de PointNet++ sont les \glspl{pvconv}~\cite{liu_point-voxel_2019}. Les \glspl{pvconv} proposent d'utiliser des voxels afin de retomber sur des structures régulières, permettant ainsi d'effectuer efficacement des convolutions classiques en 3D. Par conséquent, une \gls{pvconv} est composée de deux branches distinctes. La première branche, appelée "coarse-grained", transforme les points en voxels, applique des convolutions, puis reconvertit les voxels en points à l'aide d'une interpolation trilinéaire. La seconde branche, nommée "fine-grained", est constituée de shared \glspl{mlp}. Ces deux branches sont ensuite combinées par sommation.
Par conséquent, PVCNN peut être considéré comme l'équivalent de PointNet, tandis que PVCNN++ correspond à PointNet++. Cpendant, ces deux réseau basés sur de \glspl{pvconv} se distinguent par le maintien d'un nombre constant de points dans chaque couche du réseau. Les benchmarks démontrent que PVCNN++ est au moins autant performant que PointNet++, tout en surpassant nettement ce dernier en termes d'efficacité globale. Cependant, il est important de noter que l'implémentation de PVCNN++ est assez complexe et nécessite l'utilisation de plusieurs modules CUDA (les opérations de voxelization et de dévoxelization étant impossible à écrire en PyTorch classique). Par conséquent, PVCNN peut être considéré comme l'équivalent de PointNet, tandis que PVCNN++ correspond à PointNet++. Cpendant, ces deux réseau basés sur de \glspl{pvconv} se distinguent par le maintien d'un nombre constant de points dans chaque couche du réseau. Les benchmarks démontrent que PVCNN++ est au moins autant performant que PointNet++, tout en surpassant nettement ce dernier en termes d'efficacité globale. Cependant, il est important de noter que l'implémentation de PVCNN++ est assez complexe et nécessite l'utilisation de plusieurs modules CUDA (les opérations de voxelization et de dévoxelization étant impossible à écrire en PyTorch classique).
Une version légèrement améliorée de gls{pvconv}, appelée gls{spvconv}, a également été développée en utilisant des opérations de convolution éparses. En effet, il a été empiriquement observé que les grilles de voxels sont fréquemment remplies en moyenne à hauteur de 60\%. Cependant, ces améliorations nécessitent l'utilisation de code CUDA très ésotérique. Une version légèrement améliorée de gls{pvconv}, appelée gls{spvconv}, a également été développée en utilisant des opérations de convolution éparses. En effet, on observe empiriquement que les grilles de voxels sont fréquemment remplies en moyenne à hauteur de 60\%. Cependant, ces améliorations nécessitent l'utilisation de code CUDA très ésotérique.
\FloatBarrier \FloatBarrier
\subsection{Test de PVD} \subsection{Test de PVD}
@ -926,7 +964,7 @@ Une version légèrement améliorée de gls{pvconv}, appelée gls{spvconv}, a é
\label{fig:pvd_archi} \label{fig:pvd_archi}
\end{figure} \end{figure}
Le premier papier ayant utilisé une architecture du type PVCNN++ pour la générations de nuages de point est PVD~\cite{zhou_3d_2021}. Ce réseau utilise \gls{ddpm} et travaille directement sur le nuage de points. Si l'on récupère l'implémentation des auteurs et que l'on la modifie pour utiliser rotor37\_37\_mmd2048 on obtient de très bon résultat. Cependant, une bonne partie de la codebase étant basé sur celle de PVCNN++ et de PointFlow, celle-ci est tout aussi difficile à modifier. Le premier papier ayant utilisé une architecture du type PVCNN++ pour la générations de nuages de point est PVD~\cite{zhou_3d_2021}. Ce réseau utilise \gls{ddpm} et travaille directement sur le nuage de points. Si l'on récupère l'implémentation des auteurs et que l'on la modifie pour utiliser rotor37\_1200 on obtient de très bon résultat. Cependant, une bonne partie de la codebase étant basé sur celle de PVCNN++ et de PointFlow, celle-ci est tout aussi difficile à modifier.
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
@ -937,8 +975,6 @@ Le premier papier ayant utilisé une architecture du type PVCNN++ pour la géné
Comme on l'observe sur la figure~\ref{fig:pvd_results}, les générations que produisent PVD sont de très bonne qualité. Contrairement à KP-FCNN, les générations ne présentent pas de bruits résiduels. Cependant PVD est un réseau assez lourd, (27,6 millions de paramètres) et nécéssite un entrainement plutot long d'environ 10 heures pour produire de bon résultats. Comme on l'observe sur la figure~\ref{fig:pvd_results}, les générations que produisent PVD sont de très bonne qualité. Contrairement à KP-FCNN, les générations ne présentent pas de bruits résiduels. Cependant PVD est un réseau assez lourd, (27,6 millions de paramètres) et nécéssite un entrainement plutot long d'environ 10 heures pour produire de bon résultats.
% TODO: vérif le 10h et le nb de params.
\FloatBarrier \FloatBarrier
\glsunset{ldm} \glsunset{ldm}
\subsection{Test de LION} \subsection{Test de LION}
@ -946,7 +982,7 @@ Comme on l'observe sur la figure~\ref{fig:pvd_results}, les générations que pr
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{LION.jpg} \includegraphics[width=0.8\textwidth]{LION.jpg}
\caption{Architecture de LION~\cite{zeng_lion_2022}} \caption{Architecture de LION~\cite{zeng_lion_2022}.}
\label{fig:lion_archi} \label{fig:lion_archi}
\end{figure} \end{figure}
@ -956,14 +992,19 @@ Un deuxième encodeur transforme le nuage de points original, en utilisant le ve
Ce nuage de points latent est ensuite décodé pour obtenir une reconstruction du nuage de point original. Ce nuage de points latent est ensuite décodé pour obtenir une reconstruction du nuage de point original.
Le processus de diffusion a lieu à la fois sur le vecteur latent et sur le nuage de points latent. Le processus de diffusion a lieu à la fois sur le vecteur latent et sur le nuage de points latent.
% TODO: insérer résultat ? \begin{figure}[h!]
\centering
{\Huge \calligra Fuck Rosetta}
\caption{Résultats de LION sur rotor37\_1200.}
\label{fig:lion_results}
\end{figure}
\FloatBarrier \FloatBarrier
\subsection{Synthèse des méthodes} \subsection{Synthèse des méthodes}
Les résultats précédents montrent que la résolution de notre problème est possible. Cependant une majorité des approche précedente traitent de la génération non conditonnée, ou alors conditionnent sur des classes d'objets via des onehot vectors. Puisque nous souhaitons conditionner via des vecteurs scalaires, et car les implémentations présentée prédemment sont difficile à manipiler, nous avons décidé de développer notre propre implémentation. De plus, de manière générale les modèles présentés précedemment comporte souvent trop de paramètre pour notre problème, qui reste tout de même plus simple en comparaison. Les résultats antérieurs démontrent la faisabilité de la résolution de notre problématique. Cependant, la plupart des approches précédentes se concentrent sur la génération non conditionnée ou utilisent des one-hot vectors pour le conditionnement sur des classes discrètes. Étant donné notre objectif est conditionner à l'aide de vecteurs scalaires, et étant donné que les implémentations précédemment présentées s'avèrent complexes à manipuler, nous avons pris la décision de développer notre propre mise en œuvre. En outre, il convient de noter que les modèles précédemment proposés sont souvent caractérisés par un nombre élevé de paramètres, ce qui s'avère excessif pour notre problématique, laquelle demeure comparativement plus simple.
pour essayer d'améliorer les résultats que nous avions obtenus via KP-FCNN, nous avons opté pour une approche par \gls{ldm}. Pour cela il nous fallait choisir un modèle capable de transformer/réduire nos données d'entrée. Nous avons sélectionné dans un premier temps une \gls{pca}. En effet, après analyse, les données de rotor37\_1200 se porte très bien à une compression par \gls{pca}. De plus, il s'agit d'une méthode non paramétrique, ce qui est un avantage car pas besoin d'opti. Nous avons décidé d'adopter une approche reposant sur la réduction de dimension, via les \gls{ldm}. Pour ce faire, il était crucial de choisir un modèle capable de transformer ou de réduire nos données d'entrée. Dans cette optique, nous avons opté pour une première étape de réduction par \gls{pca}. Il convient d'ailleurs de souligner que cette approche présente l'avantage d'être non paramétrique, éliminant ainsi la nécessité d'un processus d'optimisation.
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
@ -972,49 +1013,55 @@ pour essayer d'améliorer les résultats que nous avions obtenus via KP-FCNN, no
\label{fig:pca_cumsum} \label{fig:pca_cumsum}
\end{figure} \end{figure}
Via cette figure nous en déduisons qu'environ 30 modes permettent de décrire 90\% de l'information contenue dans rotor37\_1200. On remarque cependant que cette compression est moins efficace pour rotor37\_11000, ce qui est normal car les données se ressemblent moins. À partir de la Figure \ref{fig:pca_cumsum}, nous pouvons déduire qu'environ 30 modes sont nécessaires pour représenter approximativement 90\% de l'information présente dans le jeu de données rotor37\_1200. Cependant, il est à noter que cette compression s'avère moins efficace pour le jeu de données rotor37\_11000, ce qui est attendu étant donné que les données présentent moins de similarités. Afin de résoudre les problèmes de compression associés au jeu de données rotor37\_11000, nous avons exploré la possibilité de remplacer la méthode \gls{pca} par une \gls{pod}. Malgré une meilleure capacité de compression obtenue par la \gls{pod}, cette approche s'est révélée plus coûteuse en termes de calcul et moins adaptée aux autres techniques que nous prévoyons d'utiliser. En conséquence, pour le moment, nous avons décidé de maintenir l'utilisation de la \gls{pca} pour l'encodeur et de la ``\gls{pca} inverse'' pour le decodeur de notre \gls{ldm}.
%Pour palier à ce problème nous avons essayé de remplacer la PCA par une POD, mais comme nous le verrons par la suite, même si cela permettait une meilleur compression, le calcul de la POD était bien plus couteux et se prétait moins bien aux autres techniques nous allons utiliser. Dans le cas de rotor37\_1200, cela signifie que nous passons de 30000 points, chacun comportant à la fois leurs coordonnées spatiales et leurs normales (soit un total de 30000x6 scalaires), à un vecteur de taille 30.
Ce vecteur étant petit, nous pouvons donc utiliser un simple \gls{mlp} pour prédire le bruit dans le processus de diffusion. De plus, pour conditionner ce réseau en fonction de l'étape temporelle de la diffusion, nous pouvons simplement additionner les embeddings de pas de temps à chaque couche du réseau.
Le réseau résultant contient à peine plus de 10000 paramètres, ce qui est considérablement inférieur aux autres modèles précédemment présentés.
Par conséquent, ce réseau est très facile à manipuler et à entraîner, mais il présente l'inconvénient d'être spécialisé sur le jeu de données utilisé pour construire la \gls{pca}.
Cependant, dans le contexte industriel, cet inconvénient est moins préoccupant car la nécessité de modèles génériques n'est pas primordiale.
% travaile sur 1200 dans un premier temps Après quelques entrainements, on obtient des résultats très satisfasant, comme le montre la figure \ref{fig:pca_ldm_results}.
Nous avons donc choisi de réduire nos données à 30 dimensions via une \gls{pca}. Dans le cas de rotor37\_1200 on passe donc de 30000 points contenant leur positions et leur normales à un vecteur de taille 30. Ce vecteur etant très petit et aussi structuré, nous pouvons nous permettre d'utiliser un simple \gls{mlp} pour prédire le bruit dans le \gls{ddpm}. Le réseau résultat dépasse à peine les 10 000 paramètres, ce qui est très peu comparé aux autres modèles présentés précedemment. Ainsi le réseau est très simple à manipuler et à entrainer. Pour le décodeur nous pouvons donc simplement effectuer l'opération inverse de la PCA pour transformer un vecteure de taille 30 en un nuage de points de taille 30000 (positions + normales).
Après quelques entrainements, on obtient des résultats très satisfasant, comme le montre la figure suivante: \begin{figure}[h!]
\centering
% décrire les résultat. {\Huge \calligra Fuck Rosetta}
\caption{Résultats d'un \gls{ldm} \gls{pca} sur rotor37\_1200.}
\label{fig:pca_ldm_results}
\end{figure}
\FloatBarrier \FloatBarrier
\glsunset{cfg} \glsunset{cfg}
\subsection{Condtionnement par \acrfull{cfg}} \subsection{Condtionnement par \acrfull{cfg}}
% TODO: rappeller le vecteure de perf, 5 bidules Pour conditionner notre processus de diffusion, nous avons opté pour l'utilisation de la \gls{cfg}, avec une probabilité de $p_\text{uncond}$ pour le dropout des embeddings. Pour intégrer les embeddings de conditionnement dans notre réseau, nous avons suivi une approche similaire à celle utilisée pour les embeddings de pas de temps. Les modifications apportées modifient très peu la surface de coût du réseau, et nous sommes désormais en mesure de générer des aubes tant non conditionnées que conditionnées, en fonction d'un vecteur scalaire de performances. Les résultats visuels des générations demeurent satisfaisants. Toutefois, il est difficile de déterminer visuellement si les aubes conditionnées générées respectent effectivement les critères de conditionnement qui leur sont assignés.
% TODO: parler de la concatenation des 2 inputs cfd avec les modes pca
Pour conditionner notre processus de diffusion, nous avons choisi d'utiliser la \gls{cfg}, avec une probabilité de 10\% pour le dropout des embeddings. Pour rajouter les embeddings de conditionnement dans notre réseau, nous procédons de la même manière que pour les embeddings de timesteps. La surface de coût du réseau change très peu, et nous somme désormais capable de génerer des aubes non conditionnées ou conditionnées selon un vecteur scalaire de performances. Visuellement les générations sont toujours satifisante, cependant il est impossible de déterminer à l'oeil nu si les aube conditonnées générées respectent bien le conditonnement qu'elles devraient avoir.
\FloatBarrier \FloatBarrier
\glsunset{gp} \glsunset{gp}
\subsection{Vérification par \acrfull{gp}} \subsection{Vérification par \acrfull{gp}}
À cet effet nous devons donc trouver un moyen de vérifier les propriétés physiques des aubes et les comparés aux conditionnement. De manière naive nous pourrions simplement passer nos générations dans un simulateur \gls{cfd}, mais cette approche n'est pas envisageable car trop lente. Dans cette optique, il devient impératif de mettre en place un moyen de vérification des propriétés physiques des aubes générées et de les comparer aux critères de conditionnement. Bien que l'approche la plus simple consisterait à soumettre nos générations à un simulateur \gls{cfd}, cette méthode s'avère inenvisageable en raison de sa lenteur.
Une solution est d'entrainer un modèle de regression pour trouver une relation entre nos nuages de points (ou leurs espaces latents) et critèrs de performances. Nous pouvons évidemment faire cela via réseau de neurones, mais nous pouvons aussi opter pour une approche moins paramétrique tel que les \glspl{gp}. Les \glspl{gp} sont ... Une solution viable consiste à entraîner un modèle de régression capable d'établir une relation entre nos nuages de points (ou leurs espaces latents) et leurs critères de performances. Cette tâche peut être réalisée en utilisant des réseaux de neurones, mais également en optant pour une approche moins paramétrique telle que les \glspl{gp}.
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=0.8\textwidth]{gp.png} \includegraphics[width=0.8\textwidth]{gp.png}
\caption{Régression par \gls{gp}} \caption{Régression par \gls{gp}.}
\vspace*{-11pt} \vspace*{-11pt}
\caption*{Source: doi:10.23915/distill.00017~\cite{görtler2019a}} \caption*{Source: distill.pub~\cite{görtler2019a}.}
\label{fig:gp_regression} \label{fig:gp_regression}
\end{figure} \end{figure}
Les \glspl{gp} sont des modèles probabilistes non paramétriques qui trouvent leur application dans des tâches de régression, de classification ou de prédiction. Ils sont particulièrement adaptés aux tâches de régression, car ils sont capables de fournir des estimations de l'incertitude associée à leurs prédictions. Cette mesure d'incertitude se révèle particulièrement précieuse pour la vérification de nos aubes générées, car elle permet d'évaluer la validité de nos générations en fournissant une estimation de la fiabilité de ces dernières.
Ainsi si l'on entrainer un \gls{gp} sur des couples (nuage de points, critère de performance), on peut ensuite utiliser ce \gls{gp} pour vérifier si nos nuages de points générés sont corrects. En effet, si l'on génère un nuage de points, et que l'on obtient un critère de performance très différent de celui attendu, alors on peut en déduire que notre génération est incorrecte. Ainsi si l'on entrainer un \gls{gp} sur des couples (nuage de points, critère de performance), on peut ensuite utiliser ce \gls{gp} pour vérifier si nos nuages de points générés sont corrects. En effet, si l'on génère un nuage de points, et que l'on obtient un critère de performance très différent de celui attendu, alors on peut en déduire que notre génération est incorrecte.
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=1\textwidth]{gp_train_30_pca.png} \includegraphics[width=1\textwidth]{gp_train_30_pca.png}
\caption{Entrainement d'un \gls{gp} sur 30 modes PCA de rotor37\_1200} \caption{Entrainement d'un \gls{gp} sur 30 modes PCA de rotor37\_1200.}
\label{fig:gp_train_30_pca}
\end{figure} \end{figure}
% \begin{figure}[h!] % \begin{figure}[h!]
@ -1026,25 +1073,27 @@ Ainsi si l'on entrainer un \gls{gp} sur des couples (nuage de points, critère d
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=1\textwidth]{gp_massflow_1_pca.png} \includegraphics[width=1\textwidth]{gp_massflow_1_pca.png}
\caption{Vérification du conditionnement (out\_massflow=1) par \gls{gp}} \caption{Vérification du conditionnement (out\_massflow=1) par \gls{gp}.}
\label{fig:gp_massflow_1_pca}
\end{figure} \end{figure}
\begin{figure}[h!] \begin{figure}[h!]
\centering \centering
\includegraphics[width=1\textwidth]{gp_efficiency_1_pca.png} \includegraphics[width=1\textwidth]{gp_efficiency_1_pca.png}
\caption{Vérification du conditionnement (isentropy\_efficiency=1) par \gls{gp}} \caption{Vérification du conditionnement (isentropy\_efficiency=1) par \gls{gp}.}
\label{fig:gp_efficiency_1_pca}
\end{figure} \end{figure}
Comme on l'observe sur les figures, on observe très clairement un changement de la densité de probabilité des modes \glspl{pca} lorsque l'on conditionne nos générations. on en déduit que notre modèle est capable de générer correctement des données conditionnées. On observer de même sa capacité à générer certaines données out of distribution, du moment que celle-ci ne sont pas trop éloignées de la distribution d'entrainement. Par example il est totalement impossible de demander la génération d'aubes ayant un in\_massflow et out\_massflow différents, car cela n'existe pas dans le jeu de données d'entrainement, et car cela est aussi impossible physiquement dans un système fermé. Comme illustré dans les figures \ref{fig:gp_massflow_1_pca} et \ref{fig:gp_efficiency_1_pca}, il est nettement observable qu'il y a un changement dans la densité de probabilité des modes \glspl{pca} lorsque nous conditionnons nos générations. Cette observation claire indique que notre modèle est compétent pour générer avec précision des données conditionnées. En outre, on peut également constater sa capacité à générer des données qui se situent en dehors de la distribution d'entraînement, à condition que ces données demeurent relativement proches de ladite distribution. Par exemple, il est totalement inenvisageable de demander la génération d'aubes ayant des valeurs différentes pour les attributs in\_massflow et out\_massflow. Cette impossibilité résulte du fait que de telles combinaisons ne se trouvent pas dans le jeu de données d'entraînement, et qu'elles sont également physiquement incohérentes dans un système clos.
\FloatBarrier \FloatBarrier
\chapter{Conclusion} \chapter{Conclusion}
% conclusion, présenter résultats, adéquation objectifs, enirchessiement personnel, connaissance techniques et rapport humain. % conclusion, présenter résultats, adéquation objectifs, enirchessiement personnel, connaissance techniques et rapport humain.
"Et éventuellement de proposer des améliorations spécifiques aux maillages utilisés en simulations numériques." en intro -> réduire la taille des maillages, ça serait bien. même si j'imagine que pas trop possible car les ingé des aubes veullent une très grande résolution dans leurs simu, même sur des surfaces plutôt planes, qui pourraient être représentées par moins de points. % "Et éventuellement de proposer des améliorations spécifiques aux maillages utilisés en simulations numériques." en intro -> réduire la taille des maillages, ça serait bien. même si j'imagine que pas trop possible car les ingé des aubes veullent une très grande résolution dans leurs simu, même sur des surfaces plutôt planes, qui pourraient être représentées par moins de points.
🎉 it works \texttrademark
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%