Fonction d’activation, comment ça marche ? – Une explication simple

Dans cet article nous allons voir en détails ce qu’est une fonction d’activation et son utilité dans un modèle de Deep Learning !

Vous vous souvenez ? Dans cet article nous avons vu que tous les neurones d’un modèle de Deep Learning appliquent une transformation aux données qu’ils reçoivent en entrée… Eh bien cette transformation consiste à appliquer les poids des neurones puis la fonction d’activation.

L’utilisateur choisit la fonction d’activation qui sera appliqué dans les neurones d’une couche. Par exemple avec ce code on créé une couche Dense avec la fonction sigmoid comme fonction d’activation :

model.add(layers.Dense(1, activation='sigmoid'))
Photo by Arne Smith on Unsplash

Qu’est-ce qu’une fonction d’activation ?

La fonction d’activation sert avant tout à modifier de manière non-linéaire les données. Cette non-linéarité permet de modifier spatialement leur représentation.

Dit simplement, la fonction d’activation permet de changer notre manière de voir une donnée.

Par exemple si on a comme donnée : chaque semaine 50% des clients d’un magasin achètent des barres de chocolat; la fonction d’activation permettrait de changer la donnée en 50% des clients aiment le chocolat ou encore, 50% des clients prévoient d’acheter du chocolat chaque semaine.

Le changement de représentation peut, dans notre exemple, nous permettre d’ajuster la stratégie commercial, ou bien les stocks possédés, de notre magasin.

Un modèle étant composé de multiples couches, et donc de multiples fonctions d’activation, des changements successifs et complexes de représentation s’opèrent. Cela permet d’avoir un nouveau point de vue sur nos données que l’homme serait incapable d’avoir en peu de temps.

Il ne faut pas confondre fonction d’activation et loss function. La loss function est appliqué sur tous le modèle et.. est donc unique, elle permet de calculer la performance du modèle.

Au contraire la fonction d’activation est spécifique à chaque couche, elle permet de transformer les données.

La particularité de cette fonction d’activation est qu’elle est non-linéaire. Cette non-linéarité permet de changer la représentation des données, d’avoir un nouvelle approche sur ces données. Ce changement de représentation ne serait pas possible avec une transformation linéaire.

Chaque neurone d’une couche va appliquer la fonction d’activation de la couche sur les données. Cette transformation sera différente selon chaque neurone car chacun possède un poids différent.

À retenir: la loss function s’appliquant sur tous le modèle, elle comprend, elle contient la fonction d’activation. Donc lorsqu’on calcul le gradient (la dérivé de la loss function) on calcul aussi les dérivées des loss functions.

Les différentes fonctions d’activation

En Python, les fonctions d’activation s’utilisent avec Activation(activations.fonction_d_activation), un exemple avec la fonction relu :

from tensorflow.keras import layers
from tensorflow.keras import activations

model.add(layers.Dense(64))
model.add(layers.Activation(activations.relu))

La fonction d’activation peut aussi s’utiliser directement quand on appelle la couche de neurones (layers):

model.add(layers.Dense(64, activation='relu'))

Selon le problème à résoudre (classification, régression, …) on utilise des fonction d’activations différentes.

Pour choisir la bonne fonction d’activation il faut à la fois considérer la transformation direct qu’elle applique aux données mais aussi sa dérivé qui sera utilisé pour ajuster les poids lors de la backpropagation.

ReLU

La fonction Rectified Linear Unit (ReLU) est la fonction d’activation la plus simple et la plus utilisée.

Elle donne x si x est supérieur à 0, 0 sinon. Autrement dit, c’est le maximum entre x et 0 :

fonction_ReLU(x) = max(x, 0)

Fonction ReLU – Rectified Linear Unit

Cette fonction permet d’effectuer un filtre sur nos données. Elle laisse passer les valeurs positives (x > 0) dans les couches suivantes du réseau de neurones. Elle est utilisée presque partout mais surtout pas dans la couche final, elle est utilisée dans les couches intermédiaires.

tf.keras.activations.relu(x, alpha=0.0, max_value=None, threshold=0) 
  • x : donnée d’entrée, tenseur
  • alpha : Un nombre réel qui régit la pente pour les valeurs inférieures au seuil.
  • max_value : Un nombre réel qui définit le seuil de saturation (la plus grande valeur que la fonction retournera).
  • threshold : Un nombre réel qui donne la valeur seuil de la fonction d’activation en dessous de laquelle les valeurs seront amorties ou mises à zéro

Sigmoid

La fonction Sigmoïde donne une valeur entre 0 et 1, une probabilité. Elle est donc très utilisée pour les classification binaire, lorsqu’un modèle doit déterminer seulement deux labels.

Ainsi, pour la classification des critiques de cinéma, plus la valeur retourné par Sigmoïde est proche de 1 plus le modèle considère que la critique est positive.

Au contraire, plus elle est proche de 0, plus elle est considérée comme négative.

fonction_Sigmoid(x) = 1 / (1 + exp(-x))

Fonction Sigmoïde

La fonction Sigmoïde est très simple a appliqué en Python car il n’y a pas de paramètre autre que la variable d’entrée :

tf.keras.activations.sigmoid(x)

Softmax

La fonction Softmax permet elle de transformer un vecteur réel en vecteur de probabilité.

On l’utilise souvent dans la couche finale d’un modèle de classification, notamment pour les problèmes multiclasse.

Dans la fonction Softmax, chaque vecteur est traité indépendamment. L’argument axis définit l’axe d’entrée sur lequel la fonction est appliquée.

fonction_Softmax(x) = exp(x) / tf.reduce_sum(exp(x))

fonction_Softmax(x) = exp(x) / sum(exp(xi))

Fonction Softmax
tf.keras.activations.softmax(x, axis=-1)
  • axis : Nombre entier, axe le long duquel la normalisation softmax est appliquée.

Softplus

La fonction Softplus est une approximation ‘lisse’ de la fonction ReLU. Cet aspect ‘lisse‘ (ou soft) implique que la fonction est différentiable.

En fait, cette fonction est intéressante par sa dérivée. Quand on dérive Softplus, on obtient la fonction logistique f(x) = 1/(1+exp(-x)). On rappelle que la dérivée est utilisée lors de la Backpropagation pour mettre à jour les poids.

Elle était utilisée pour contraindre le résultat d’une couche à être toujours positif mais a été remplacé par ReLU qui est linéaire et donc beaucoup plus rapide à calculer.

fonction_Softplus(x) = log(exp(x) + 1)


CRÉER TON APPLICATION IA !

Reçois tes 5 JOURS De Formation GRATUITE Pour Apprendre À Créer Ton APPLICATION d’INTELLIGENCE ARTIFICIELLE !

Tous les fondamentaux de la création d’Application IA : les approches, les outils et techniques, les librairies et framework, et bien d'autres ! Découvres étape par étape la création d’application de Deep Learning (tu apprendras même à trouver des idées d’appli !). En bonus, tu recevras notre Guide Ultime du Deep Learning !


Fonction Softplus
tf.keras.activations.softplus(x)

Softsign

La fonction Softsign est utile pour normaliser nos données car elle permet d’avoir un résultat entre -1 et 1 et garde en mémoire le signe des données (positif ou négatif). Autrement dit, les données sont recentrées sur zéro et bornées par -1 et 1.

En fait, c’est la fonction signe lissé (Softsign) et donc différentiable (Backpropagation oblige).

fonction_Softsign(x) = x / (abs(x) + 1)

Fonction Softsign
tf.keras.activations.softsign(x) 

tanh

La fonction tanh est simplement la fonction de la tangente hyperbolique.

Il s’agit en fait d’une version mathématiquement décalée de la fonction sigmoïde :

  • sigmoïde donne un résultat entre 0 et 1
  • tanh donne un résultat entre -1 et 1

L’avantage de tanh est que les entrées négatives seront bien répertoriées comme négatives là où, avec sigmoïde, les entrées négatives peuvent être confondus avec les valeurs proche de nulles.

Cette fonction est, comme Sigmoïde, utilisé dans la classification binaire. Par exemple pour notre classification des critiques de cinéma plus la valeur retourné par tanh est proche de 1 plus le modèle considère que la critique est positive, plus elle est proche de -1, plus elle est considérée comme négative.

Tanh fonctionne mieux que la fonction sigmoïde dans la plupart des cas.

fonction_tanh(x) = sinh(x)/cosh(x)

fonction_tanh(x) = ((exp(x) – exp(-x))/(exp(x) + exp(-x)))

Fonction tanh
tf.keras.activations.tanh(x)

ELU

La fonction Exponential Linear Unit (ELU) est une amélioration de ReLU car elle permet d’avoir des valeurs lisses lorsque x < 0.

Lorsque x < 0, ELU a des valeurs négatives différents de 0 (ce qui n’est pas le cas de ReLU). Cela permet de rapprocher la moyenne de la fonction de zéro.

Une moyenne plus proches de zéro permet un apprentissage plus rapide car cela rapprochent le gradient calculé du gradient naturel (un concept qui mérite un article entier).

Effectivement, plus x diminue, plus ELU saturent à une valeur négative. Cette saturation implique qu’ELU a une petite dérivée ce qui diminue la variation du résultat et donc l’information qui est propagée vers la couche suivante.

fonction_ELU(x) =

  • if x > 0: x
  • if x < 0: alpha * (exp(x) – 1)

avec :

  • alpha > 0
Fonction ELU – Exponential Linear Unit
tf.keras.activations.elu(x, alpha=1.0)
  • alpha: un scalaire, une variable, qui permet de contrôler la pente de ELU lorsque x < 0. Plus alpha est grand, plus la courbe est pentue. Ce scalaire doit est supérieur à 0 (alpha > 0)

SELU

La fonction Scaled Exponential Linear Unit (SELU) est une optimisation de ELU.

Le principe est le même qu’avec ELU. On multiplie seulement le résultat de ELU par un scalaire. On pourrait l’écrire comme cela : fonction_SELU(x) = scale * fonction_ELU(x).

Plus précisément:

fonction_SELU(x) =

  • if x > 0: return scale * x
  • if x < 0: return scale * alpha * (exp(x) - 1)

avec comme constante :

  • alpha = 1.67326324
  • scale = 1.05070098

alpha et scale sont prédéfinit, on ne peut donc pas les changer mais l’important a comprendre ici est que scale est supérieur à 1. Cela permet à la pente de SELU sur x > 0 d’être supérieur à 1 et évite certains problèmes lors du calcul de gradient.

Fonction SELU – Scaled Exponential Linear Unit
tf.keras.activations.tanh(x)

Cette fonction a d’ailleurs une spécificité : lors de son utilisation, il faut initialiser les poids avec ‘lecun_normal’ comme suit:

model.add(tf.keras.layers.Dense(64, kernel_initializer='lecun_normal', activation='selu'))

Fonctions d’activation personnalisées

Dans un travail de recherche ou d’expérimentation, il est possible que les fonctions d’activation prédéfini ne vous suffisent pas.

On peut notamment vouloir créer des fonctions d’activation si celles utilisées ne produisent pas le résultat attendu ou bien si l’on veut enclencher des transformations bien spécifiques sur nos données.

Pour créer une fonction d’activation il faut se rappeler deux choses :

  • une fonction d’activation doit être non-linéaire, c’est-à-dire différente de la forme f(x) = ax+b, qui ne peut pas être représentée par une ligne droite (les fonctions sigmoïde et exponentielle sont non-linéaire)
  • une fonction d’activation prend en entrée un tenseur ainsi, si on veut utiliser la fonction exponentielle sur Python, il ne faut pas utiliser math.exp(x) (car ici x est un nombre réel) mais tensorflow.math.exp(x) (où x est un tenseur)

Première exemple avec Tensorflow et la fonction exponentielle :

On créé la fonction

import tensorflow as tf

def ma_fonction(x, beta=1.0):
    return x * (beta * x)/tf.math.exp(-x)

Puis, on l’ajoute dans la couche souhaitée

from keras.layers.core import Activation

model.add(layers.Dense(16))
model.add(Activation(ma_fonction))

Deuxième exemple avec Keras en customisant la fonction sigmoïde :

On créé la fonction

from keras import backend as K

def ma_fonction(x, beta=1.0):
    return x * K.sigmoid(beta * x)

Puis, on l’ajoute dans la couche souhaitée

from keras.layers.core import Activation

model.add(layers.Dense(16))
model.add(Activation(ma_fonction))

Gardez à l’esprit que, si vous sauvegarder un modèle avec une fonction d’activation personnalisées, pour le réutiliser dans un autre programme il faudra que vous importiez la fonction d’activation que vous avez créé pour que le modèle fonctionne !

Quelle fonction pour quel cas ?

Comme on l’a vu précédemment, plusieurs fonctions d’activation peuvent être utilisé dans un modèle selon le choix de l’utilisateur.

Néanmoins, la dernière fonction d’activation est essentielle car c’est elle qui permet de produire le résultat.

Ainsi, il faudra choisir la bonne fonction d’activation en fonction du type de problème auquel on a à faire.

On ne va pas prendre une fonction retournant une probabilité si notre problème de base est de trouver la valeur futur d’une action en Bourse.

C’est pourquoi nous avons mis à votre disposition ce tableau pour savoir quelle fonction d’activation utiliser dans la dernière couche de son modèle selon le type de problème.

Type de problèmeFonction d’activation de la dernière couche
Classification Binairesigmoid
Classification multiclasse, à label uniquesoftmax
Classification multiclasse, multilabelsigmoid
Régression vers des valeurs arbitrairesaucune (ehh oui !)
Régression vers des valeurs comprises entre 0 et 1 (probabilités)sigmoid
Quelle activation pour quel problème ?

Bien sûr ce tableau n’est pas une règle absolue mais il permet de se repérer pour la plupart des cas.

Des fonctions d’activation plus complexes sont disponibles. Elle sont appellées « couches d’activation avancées« . Les plus connus sont les fonction PReLU et LeakyReLU et peuvent être trouvées dans le module : tf.keras.layers.advanced_activations.

Si vous souhaitez en savoir plus sur les classification multiclasse, multilabel mais surtout connaître la différence entre un label et une classe…

… ça se passe sur cet article ! 😉

sources photos :


CRÉER TON APPLICATION IA !

Reçois tes 5 JOURS De Formation GRATUITE Pour Apprendre À Créer Ton APPLICATION d’INTELLIGENCE ARTIFICIELLE !

Tous les fondamentaux de la création d’Application IA : les approches, les outils et techniques, les librairies et framework, et bien d'autres ! Découvres étape par étape la création d’application de Deep Learning (tu apprendras même à trouver des idées d’appli !). En bonus, tu recevras notre Guide Ultime du Deep Learning !


Tom Keldenich
Tom Keldenich

Data Engineer & passionné d'Intelligence Artificielle !

Fondateur du site Inside Machine Learning

8 commentaires

  1. Merci pour ce cours. C’est très édifiant. Pourquoi est-ce si compliqué d’avoir une fonction d’activation pour la régression vers des valeurs arbitraires?
    Ne peut-on pas utiliser la fonction sigmoïde
    pour cette régression ?

    A quoi ça sert une régression vers des valeurs aléatoires ?

    • Bonjour Samuel,

      Dans la dernière couche d’un réseau de neurones, la fonction d’activation est liée à l’objectif du problème.

      Admettons que tu veuille classifier l’image d’un animal. Le problème : Est-ce un cheval ?
      Ici on est dans un cas de classification Binaire (soit c’est un cheval, soit c’est autre chose).
      La fonction d’activation sigmoïde est parfaite pour nous car elle limite le résultat à une valeur entre 0 et 1 (c’est à dire une probabilité, 0 correspondant à 0% et 1 correspondant à 100%). Le résultat sera donc une probabilité que l’animal sur l’image soit un cheval.

      Par contre, admettons qu’on veuille prédire le prix d’un appartement dans un quartier de Paris. Dans ce cas, on ne veut pas une probabilité. En fait, on ne veut pas non plus que notre résultat soit limité entre 0 et 1 ou même 0 et 10.
      Ce qu’on veut c’est un résultat qui est potentiellement très élevé, illimité. On est donc dans un problème de Régression.

      Pour la régression, on ne veut donc pas limiter le résultat, l’output. Alors on ajoute notre couche de neurones sans indiquer de fonction d’activation, pour ne pas fixer de seuil à notre résultat.

      Par exemple, avec Keras on peut prendre comme dernière couche :
      model.add(tf.keras.layers.Dense(1))

      Bonne journée,
      Tom

  2. Bonjour ,
    Merci pour votre cours
    j’ai une question un peu technique, je suis entrain de tester différents processus de data augmentation, particulièrement un GAN. lors de la phase d’apprentissage de l’agent Generateur, je désire lui fournir un tensor avec des valeurs entières appartenant à un certain interval. Le Generateur est formé de 2 couches cachées avec la fonction d’activation ReLU.
    lorsque j’utilise torch.randn, cela fonctionne très bien mais le résultat (fake data) est composé par des float. Avec torch.randint, python m’indique une erreur au niveau du tensor fournit à la phase d’apprentissage. Avez vous une idée sur la cause de ce problème? Merci pour votre réponse.
    voici le lien drive où vous pouvez trouver le code et erreur générée par python
    https://drive.google.com/drive/folders/1rXwpags8v0uE7BQmsdKOkz_N3-h7SXRX?usp=sharing:

    • Bonjour Hajer,

      Si je comprends bien ton erreur est « Expected object of scalar type Float but got scalar type Long »

      Il attend de toi des float et tu lui donnes des Long (des entier).

      torch.randn fonctionne

      torch.randint ne fonctionne pas

      As-tu essayé de transformer tes int en float ?

      Tu peux le faire avec la fonction `.float()`

      Par exemple : torch.randint(20,100,(batch_size, 7)).float()

      De cette manière tu garderas la valeur de tes int tout en les transformant en float

      Essaye et tiens moi au courant,
      Tom

  3. Bonjour Tom,
    Je vous remercie pour cet article d’une grande qualité. J’ai à présent une vision plus claire de toutes les fonctions d’activation.
    Pouvez vous m’expliquer la différence entre : La Classification multiclasse à label unique et la Classification multiclasse, multilabel svp ?
    Bonne journée
    Dalila

    • Hello Dalila,

      Prenons des exemples concrets :
      – Si tu veux prédire la météo à Paris et que tu as 3 choix : beau temps, pluie, neige; c’est ici une classification multiclasse à label unique. Effectivement tu as plusieurs classes (beau temps, pluie, neige) et un label ‘météo à Paris’
      – Maintenant si tu veux prédire la météo dans plusieurs villes : Paris, Bordeaux, Lille. On est sur une classification multiclasse et multilabel. Tes labels étant ‘météo à Paris’, ‘météo à Bordeaux’, ‘météo à Lille’

      Du coup, on comprend facilement qu’une classification binaire est une classification à deux classes et un label.

      Tu peux en apprendre plus sur le sujet dans cet article !

      Et si tu veux en savoir davantage n’hésite pas à t’abonner à notre newsletter 😉

      Bonne journée,
      Tom

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.