Somme de fonctions

Soit les données non-linéairement séparables suivant.

Un modèle linéaire seule (ex: perceptron ou régression logistique) ne peut pas trouver une frontière entre ces données. Il faut trouver un moyen de créer une fonction non-linéaire qui pourra représenter une frontière.

Ceci est possible en combinant des fonctions ensemble.

\[combinaison = \alpha f_{\mathbf{w}0}(\mathbf{x}) + \beta f_{\mathbf{w}1}(\mathbf{x}) + \dots\]

Les fonctions \(f_{\mathbf{w}_j}\) ont la forme \(activation(\mathbf{w}_j \cdot \mathbf{x})\). \(\alpha\), \(\beta\), etc. sont des poids pour la combinaison de fonctions.

Chaque fonction reçoit le même \(\mathbf{x}\), mais utilise un \(\mathbf{w}\) différent pour \(\mathbf{w} \cdot \mathbf{x}\) et \(activation\) est une fonction non-linéaire. Ceci transforme les valeurs \(\mathbf{w}_j \cdot \mathbf{x}\) dans un espace non-linéaire. Il peut être prouvé qu’une combinaison linéaire de fonctions non-linéaires donne une fonction non-linéaire. En contraste, une combinaison de fonctions linéaires donne toujours une fonction linéaire.

Les trois premiers graphiques présentent \(f_{\mathbf{w}_j} = \sigma(\mathbf{w}_j \cdot \mathbf{x})\) avec des poids et biais différents. La frontière se trouve où \(\sigma(\mathbf{w}_j \cdot \mathbf{x}) = 0.5\), dont où la distance entre \(\mathbf{x}\) et la frontière \(\perp\) à \(\mathbf{w}_j\) est \(0\).

Le quatrième présente la somme combinaison des trois \(\sigma\) avec des poids \(\alpha\), \(\beta\), etc. \(=1\).

Imaginez que chaque fonction « vote » avec une certaine pondération \(\alpha, \beta, ...\) pour la probabilité que la classe soit \(1\). La moyenne pondérée des votes donne effectivement une frontière non linéaire.


Exemple d’un réseau de neurones qui combine 10 fonctions avec activation \(ReLU\).

https://colab.research.google.com/drive/1ZzOmYlInEgBcN7Dc1yiDxUg7W5ndjoss?usp=sharin

Construction d’un réseau de neurones

Nous voulons construire un modèle avec la capacité de combinaison

\[combinaison = \alpha f_{\mathbf{w}0}(\mathbf{x}) + \beta f_{\mathbf{w}1}(\mathbf{x}) + \dots\]

Si nous choissisons \(\sigma\) comme \(activation\) :

\[ \hat{y}_i = \alpha\sigma(\mathbf{w}_0 \cdot \mathbf{x}_i) + \beta\sigma(\mathbf{w}_1 \cdot \mathbf{x}_i)\space + \space... \]

Nous remarquons que la sortie est une somme de neurones de régression logisitique.

Supposons des données à 4 caractéristiques et 3 neurones :

** le biais \(b\) n’est souvent pas représenté visuellement. Nous tenons pour acquis qu’il est là. **

Suivant la représentation visuelle des connections vu pour le perceptron :

\[ z = g(\mathbf{w}|\mathbf{x}_i) = \mathbf{w} \cdot \mathbf{x}_i\\[10pt] z_0 = g(\mathbf{w}_0) = \mathbf{w}_0 \cdot \mathbf{x}_i\\ z_1 = g(\mathbf{w}_1) = \mathbf{w}_1 \cdot \mathbf{x}_i \]

Deux neurones de régressions logistiques sont connectées aux mêmes intrants – mais avec leurs propres paramètres \(\mathbf{w}_{neurone}\). La sortie de la régression logisitque est \(\sigma(z_{neurone}) = \sigma(\mathbf{w}_{neurone} \cdot \mathbf{x}_i)\)

Toutes les neuronnes entre la première et dernière couche sont dans une « couche cachée ». En d’autres mots, l’utilisateur du modèle a une « boite noire » où il sait quoi donner et recevoir au modèle, mais ne connaît pas la complexité interne du système.

Finalement, la sortie est également une neurone où ses intrants est le résultat de la couche précédente. Considérons cette neurone comme la neuronne #2 et changeons les noms des coefficients \(\alpha, \beta, \dots\) pour des \(\mathbf{w}_2\).

\[ \begin{align*} \hat{y}_i &= h_{\theta}(\mathbf{x}_i), \quad \theta = \{\mathbf{w}_0, \mathbf{w}_1, \mathbf{w}_2\}\\[5pt] &= w_{2,0}\sigma(g(\mathbf{w}_0)) + w_{2,1}\sigma(g(\mathbf{w}_1))\\[5pt] &= w_{2,0}\sigma(z_0) + w_{2,1}\sigma(z_1)\\[5pt] &= w_{2,0}\sigma(\mathbf{w}_0 \cdot \mathbf{x}_i) + w_{2,1}\sigma(\mathbf{w}_1 \cdot \mathbf{x}_i)\\[5pt] &= \begin{bmatrix} w_{2,0} \\ w_{2,1} \end{bmatrix} \begin{bmatrix} \sigma(\mathbf{w}_0 \cdot \mathbf{x}_i) \\ \sigma(\mathbf{w}_1 \cdot \mathbf{x}_i) \end{bmatrix}\\ &=\mathbf{w}_2 \begin{bmatrix} \sigma(\mathbf{w}_0 \cdot \mathbf{x}_i)\\ \sigma(\mathbf{w}_1 \cdot \mathbf{x}_i) \end{bmatrix} \end{align*} \]

Nous voyons bien que la sortie est en fonction de tous les paramètres internes \(\theta\) et qu’il la sortie d’une couche influence une autre par la composition de fonctions. \[ h(\mathbf{x}_i | \mathbf{w}_0,\mathbf{w}_1,\mathbf{w}_2) = \mathbf{w}_2 \begin{bmatrix} \sigma(\mathbf{w}_0 \cdot \mathbf{x}_i)\\ \sigma(\mathbf{w}_1 \cdot \mathbf{x}_i) \end{bmatrix} \]

Ceci est important pour calculer le gradient pendant l’apprentissage : une modification à un \(\mathbf{w}\) peut avoir une influence (gradient) importante sur la sortie et donc l’erreur !

Un réseau plus complexe

Pour simplifier l’écriture et les calculs, nous pouvons combiner les vecteurs \(\mathbf{w}\) de chaque neurones en « matrices de couches ».

La première couche cachée :

\[ \begin{align*} W_0 &= \begin{bmatrix} \mathbf{w}_0 & \mathbf{w}_1 & \mathbf{w}_2 & \mathbf{w}_3 & \mathbf{w}_4 \end{bmatrix}\\[5pt] &= \begin{bmatrix} w_{0,0} & w_{1,0} & w_{2,0} & w_{3,0} & w_{4,0} \\ w_{0,1} & w_{1,0} & w_{2,0} & w_{3,0} & w_{4,0} \\ w_{0,2} & w_{1,0} & w_{2,0} & w_{3,0} & w_{4,0} \\ w_{0,3} & w_{1,0} & w_{2,0} & w_{3,0} & w_{4,0} \\ b_0 & b_1 & b_2 & b_3 & b_4 \end{bmatrix} \end{align*} \]

Nous pouvons calculer tous les \(z\) de la première couche pour un \(\mathbf{x}_i\) d’un coup. Nommons le vecteur \(\mathbf{z}_{0,i}\)\(_0\) indique la couche pour le \(i\)-ème exemple.

\[ \begin{align*} \mathbf{z}_{0,i} &= W_{0}^T \mathbf{x}_i\\[5pt] \mathbf{z}_{0,i} &= \begin{bmatrix} w_{0,0} & w_{0,1} & w_{0,2} & w_{0,3} & b_0 \\ w_{1,0} & w_{1,1} & w_{1,2} & w_{1,3} & b_1 \\ w_{2,0} & w_{2,1} & w_{2,2} & w_{2,3} & b_2 \\ w_{3,0} & w_{3,1} & w_{3,2} & w_{3,3} & b_3 \\ w_{4,0} & w_{4,1} & w_{4,2} & w_{4,3} & b_4 \end{bmatrix} \begin{bmatrix} x_{i,0} \\ x_{i,1} \\ x_{i,2} \\ x_{i,3} \\ 1 \end{bmatrix}\\ &= \begin{bmatrix} \mathbf{w}_0 \cdot \mathbf{x}_i + b_0 \\ \mathbf{w}_1 \cdot \mathbf{x}_i + b_1 \\ \mathbf{w}_2 \cdot \mathbf{x}_i + b_2 \\ \mathbf{w}_3 \cdot \mathbf{x}_i + b_3\\ \mathbf{w}_4 \cdot \mathbf{x}_i + b_4 \end{bmatrix} = \begin{bmatrix} z_0 \\ z_1\\ z_2\\ z_3\\ z_4 \end{bmatrix}\\ \end{align*} \]

Nous pouvons même calculer les vecteurs \(\mathbf{z}_{0,i}\) pour tous les \(m\) exemples d’un coup !

\[ \begin{align*} {Z}_{0} &= W_{0}^T X^T\\[5pt] &= \begin{bmatrix} w_{0,0} & w_{0,1} & w_{0,2} & w_{0,3} & b_0 \\ w_{1,0} & w_{1,1} & w_{1,2} & w_{1,3} & b_1 \\ w_{2,0} & w_{2,1} & w_{2,2} & w_{2,3} & b_2 \\ w_{3,0} & w_{3,1} & w_{3,2} & w_{3,3} & b_3 \\ w_{4,0} & w_{4,1} & w_{4,2} & w_{4,3} & b_4 \end{bmatrix} \begin{bmatrix} x_{0,0} & x_{1,0} & \dots & x_{m-1,0} \\ x_{0,1} & x_{1,1} & \dots & x_{m-1,1} \\ x_{0,2} & x_{1,2} & \dots & x_{m-1,2} \\ x_{0,3} & x_{1,3} & \dots & x_{m-1,3} \\ 1 & 1 & \dots & 1 \end{bmatrix}\\ &= \begin{bmatrix} \mathbf{z}_{0,0} & \mathbf{z}_{0,1} & \dots & \mathbf{z}_{0,m-1} \end{bmatrix}\\ \end{align*} \]

Maintenant pour la deuxième couche, nous avons \(W_1\) et les intrants ne sont plus \(\mathbf{x}_i\) mais \(\sigma(\mathbf{z}_{0,i})\) ! :

\[ \begin{align*} {Z}_{1} &= W_{1}^T \sigma(Z_0))\\[5pt] &= \begin{bmatrix} w_{0,0} & w_{0,1} & w_{0,2} & w_{0,3} & w_{0,4} & b_0 \\ w_{1,0} & w_{1,1} & w_{1,2} & w_{1,3} & w_{1,4} & b_1 \\ \end{bmatrix} \begin{bmatrix} \sigma(\mathbf{z}_{0,0}) & \sigma(\mathbf{z}_{0,1}) & \dots & \sigma(\mathbf{z}_{0,m-1})\\ 1 & 1 & \dots & 1 \end{bmatrix}\\ \end{align*} \]

Finalement, \(\hat{y} = W_2^T\sigma(Z_1)\)

Intuition par transformation

Observez que \(\mathbf{z}_{0,i} = W_{0}^T \mathbf{x}_i\) prend un point \(\mathbf{x}_i\) de l’espace des caractéristiques et l’amène vers un nouvel espace. Dans l’exemple, la transformation d’un point par \(W_0^T\) est une fonction qui map de 4D à 5D.

Si vous avez IMN401, vous savez que les lignes de \(W\) donne les vecteurs de bases de la nouvelle espace (voir cours sur la matrice \(V\)).

\(Z_{0} = W_{0}^T X^T\) transforme tous les points ! \(Z_{1}\) est l’espace qui map de 5D à 2D. \(\hat{y}\) de 2D à 1D. L’ajout du \(\sigma\) permet des transformations non linéaires telles que nous avions vu avec la régression logisitique.

Chaque couche fait partie d’une pipeline de transformations des points vers un autre espace.

Nous avions vu avec les iris qu’en 2D ils n’étaient pas linéairement séparable, mais en 3/4D, ils l’étaient. L’intuition est semblable : nous espérons amener nos points vers d’autres espaces avec des transformations non linéaires en espérant d’arriver à un espace où les points sont séparables par une frontière. Nous voyons dans l’architecture que \(\hat{y}\) est une régression logistique (essentiellement une ligne frontière) mais sur des données dans un autre espace que celle des caractéristiques originales.

https://www.youtube.com/watch?v=pdNYw6qwuNc

https://www.youtube.com/watch?v=0QczhVg5HaI <>

Complexité d’un modèle

https://playground.tensorflow.org/

Souvenons-nous de biais versus variance : un modèle plus complexe peut mieux mémoriser le jeu d’entraînement. Plus de neurones par couches (largeur) et plus de couches (profondeur) augmente la complexité des modèle. Il faut trouver un équilibre.

DeepSeek v3 a 671 millards de paramètres. C’est beaucoup de neurones dans beaucoup de couches. Lorsque le nombre de couches devient considérable, nous parlons de réseaux de neurones profondes (deep neural networks). Plusieurs problèmes nécessitent une très grande complexité pour quand même bien généraliser.