# Classifieur logistique

## Concepts

Le classifieur logistique est une classifieur linéaire, $X$ est l'entrée (par exemple les pixels d'une image) et il applique un transformation linéaire pour effectuer ses prédictions $y$.

\begin{align}
WX+b = y
\end{align}

- $W \in \mathbb{R}^{n \times m}$ est une matrice contenant la matrice des poids,
- $X \in \mathbb{R}^{m}$ est un vecteur d'entrée,
- $b \in \mathbb{R}^{n}$ est le biais,
- $y \in \mathbb{R}^{n}$ est la sortie prédite.

L'objectif est de trouver les matrices $W$ et $b$ permettant de réaliser les meilleurs prédictions. 

Le problème est que $y$ n'est évidemment pas une probabilité d'appartenance à une classe. $\sum_{i=1}^{n} y_i \ne 1$. Nous allons utiliser la fonction $softmax$ sur les éléments de sortie, pour d'une part normaliser les valeurs de sortie, mais aussi "exagérer" les écarts de probabiblité:

\begin{align}
S(y_i) =  \frac{e^{y_i}}{\sum_j e^{y_j}}
\end{align}

Les valeurs obtenues sont appelées **logits**.

Nous avons donc maintenant des probabilités d'appartenance à une classe (ou plutôt une estimation, d'où le ^ sur le vecteur $p$:


\begin{align}
S(WX+b) = \hat{p}
\end{align}

Lors de l'apprentissage, la probabilité de la sortie désirée est donc encodée de la manière triviale suivante: nous utilisons un vecteur ayant une probabilité de $1$ pour la classe désirée, et $0$ pour les autres classes. Cet encodage est appelé **one hot encoding**. Notons $p$ ce vecteur de probabilité désiré.

L'objectif est maintenant de mesurer une "distance" entre le vecteur de probabilité de la sortie désirée, et celle de la sortie effective. La mesure couremment utilisée à ces fins est la **cross entropie**.

\begin{align}
D(\hat{p},p) = - \sum_i p_i log (\hat{p}_i)
\end{align}

**Important** Notez que $\hat{p}$ est placé dans le $log$, ce point est inportant car $p$ contient $n-1$ valeurs $0$... et $log(0)= -\infty$.

## Apprentissage

La première méthode est de minimiser l'erreur moyenne sur tous les exemples:

\begin{align}
\mathcal{L}(X,b) = \frac{1}{n} \sum_i D(S(WX_i+b),P_i) 
\end{align}
    
Ce que nous recherchons, c'est: $argmin_{W,b} \mathcal{L}(W,b)$.

Cf: [Exercice n°1: 1_notmnist.ipynb](1_notmnist.ipynb)

# Mesure de la performance

**Ensemble d'apprentissage**: un ensemble d'exemples utilisés pour l'apprentissage: pour s'adapter aux paramètres du classificateur. Dans le cas des NN, nous utiliserions l'ensemble d'apprentissage pour trouver les poids synaptiques «optimaux».

**Ensemble de validation**: un ensemble d'exemples utilisés pour ajuster les hyper-paramètres paramètres d'un classificateur. Dans le cas des NN, nous utiliserions l'ensemble de validation pour trouver le nombre «optimal» de couches cachées ou déterminer un point d'arrêt pour l'algorithme de rétropropagation.

**Ensemble de tests**: un ensemble d'exemples utilisés uniquement pour évaluer la performance d'un classificateur entièrement formé. Dans le cas des NN, nous utiliserions le test pour estimer le taux d'erreur après avoir choisi le modèle final (taille du NN et poids synaptiques). 

Pourquoi séparer les ensembles de test et de validation? Pour éviter un sur-apprentissage par over-fitting des hyper-paramètres du modèle.

En vrac:
- Pour annoncer une amélioration, il doit y avoir 30 données correctement classées dans l'ensemble de validation pour conclure que le modèle s'est amélioré. Soit 0.1% d'amélioration sur 30000 données dans l'ensemble de validation.

# Descente de gradient vs Descente de gradient stochastique

## Description

\begin{align}
\mathcal{L}(X,b) = \frac{1}{n} \sum_i D(S(WX_i+b),P_i) 
\end{align}

Il faut calculer $\Delta \mathcal{L}(W,b)$ pour tous les exemples... et de nombreuses fois. Ce processus est top couteux, au lieu de calculer $\mathcal{L}$, nous allons calculer à chaque itération une estimation des cette valeur : $\hat{\mathcal{L}}$ sur un sous ensemble des données d'apprentissage (entre 1 et 1000 données choisies aléatoirement à chaque itération). Cette méthode est appelée descente de gradient stochastique ou **SGD**.

## Contraintes pour la SGD

Pour que la **SGD** fonctionne, il faut:

- Des entrées:
    - de moyenne nulle
    - de variance faible
- Des poids initialisés:
    - de manière aléatoire
    - de moyenne nulle
    - de variance faible  

## Astuce pour la SGD

### Momentum

Utiliser l'inertie (mumentum) plutôt que de mettre à jour les poids simplement avec $\delta_t = - \alpha \Delta \mathcal{L}(W)$, de la manière suivante : $\delta_t = (1-\beta) \Delta \mathcal{L}(W) + \beta \delta_{t-1}$ avec $\beta \in [0,1]$. Une valeur de $\beta = 0.9$ est généralement un bon choix.

### Learning rate decay

L'objectif est de diminuer la taille des pas au fil des itérations. De nombreuses méthodes existent:

- Exponential decay : Il a la forme mathématique $lr = lr_0  e^{- kt}$, où lr, k sont des hyperparamètres et t est le nombre d'itération.
- Step Decay : consiste par exemple à réduire le taux d'apprentissage de moitié toutes les 10 epoch.
- ...

Dans tous les cas si l'apprentissage se passe mal... commencez par diminuer la vitesse d'apprentissage.

**ADAGRAD** est un algorithme d'optimisation des descente de gradient, cet algorithme évite d'avoir à gérer un certain nombre d'hyper paramètres tels que *la vitesse d'apprentissage initiale*, le *momentum*, le *decay*. 
Il existe beaucoup [d'autres algorithmes](http://ruder.io/optimizing-gradient-descent/index.html#adagrad) de ce type.


## Eviter le sur-apprentissage

L'objectif des techniques suivantes est de minimiser le sur-apprentissage.

### Early termination

Cette technique consiste à stopper l'apprentissage dès que la précision sur l'ensemble d'apprentissage diminue.

### Techniques de regularisation 

Techniques ajoutant explicitement des contraintes sur les poids, par exemple :

- **L2 régularisation**: On ajoute un nouveau terme à la fonction de cout pénalisant des poids trop élevés: 

\begin{align}
\mathcal{L}_{reg} = \mathcal{L} + \beta \frac{1}{2} \| W \|_2^2
\end{align}

$\beta$ est donc un autre hyper paramètre. 

La dérivée de l'expression de régularisation ajouté est simple à calculer et vaut simplement: $\beta W$.

- **Dropout**: Le réseau neuronal se voit aléatoirement amputé d'une partie de ses neurones pendant la phase d'entrainement (leur valeur de sortie estimée à 0). Ce processus est répété à chaque itération. Une probabilité de $0.5$ est couramment utilisée pour le dropout. Si la technique de dropout ne fonctionne pas sur un modèle, c'est qu'il ne comporte pas suffisamment de poids.




```python

```

5b7eb913a66486142f2cd5f3825bc9939e7dabb1
ipynb
Jupyter Notebook
src/udatcity/Memo.ipynb
manueldeval/nn-course
f7f2de767224f69103ae3efae6f8485f1c50e8b9
MIT
src/udatcity/Memo.ipynb
manueldeval/nn-course
f7f2de767224f69103ae3efae6f8485f1c50e8b9
MIT
src/udatcity/Memo.ipynb
manueldeval/nn-course
f7f2de767224f69103ae3efae6f8485f1c50e8b9
MIT
Qwen/Qwen-72B
1. YES
2. YES