Optimisation du régulateur PID Une approche de descente de gradient

Optimisation du régulateur PID par descente de gradient

Utiliser l’apprentissage automatique pour résoudre des problèmes d’optimisation en ingénierie

L'algorithme de descente de gradient descend pour minimiser une fonction de coût

L’apprentissage automatique. L’apprentissage profond. L’IA. De plus en plus de personnes utilisent ces technologies chaque jour. Cela a largement été stimulé par l’utilisation de grands modèles de langage déployés par des entreprises telles que ChatGPT, Bard et d’autres. Malgré leur utilisation généralisée, relativement peu de personnes sont familières avec les méthodes sous-jacentes à ces technologies.

Dans cet article, nous nous plongeons dans l’une des méthodes fondamentales utilisées en apprentissage automatique : l’algorithme de descente de gradient.

Au lieu d’examiner la descente de gradient du point de vue des réseaux neuronaux, où elle est utilisée pour optimiser les poids et les biais du réseau, nous examinerons plutôt l’algorithme comme un outil pour résoudre des problèmes classiques d’optimisation en ingénierie.

Plus précisément, nous utiliserons la descente de gradient pour régler les gains d’un régulateur PID (Proportionnel-Intégral-Dérivé) pour un système de régulation de vitesse de croisière de voiture.

La motivation pour suivre cette approche est double :

Premièrement, l’optimisation des poids et des biais d’un réseau neuronal est un problème de grande dimension. Il y a beaucoup de paramètres en mouvement et je pense que cela détourne de l’utilité sous-jacente de la descente de gradient pour résoudre des problèmes d’optimisation.

Deuxièmement, comme vous le verrez, la descente de gradient peut être un outil puissant lorsqu’elle est appliquée à des problèmes d’ingénierie classiques tels que l’accordage d’un régulateur PID, la cinématique inverse en robotique et l’optimisation de la topologie. La descente de gradient est un outil qui, selon moi, devrait être mieux connu et utilisé par les ingénieurs.

Après avoir lu cet article, vous comprendrez ce qu’est un régulateur PID, comment fonctionne l’algorithme de descente de gradient et comment il peut être appliqué pour résoudre des problèmes classiques d’optimisation en ingénierie. Vous pourriez être motivé pour utiliser la descente de gradient pour relever vos propres défis en matière d’optimisation.

Tout le code utilisé dans cet article est disponible ici sur GitHub.

Qu’est-ce qu’un régulateur PID ?

Un régulateur PID est un mécanisme de commande à rétroaction largement utilisé en ingénierie et dans les systèmes automatisés. Son objectif est de maintenir un point de consigne désiré en ajustant continuellement le signal de commande en fonction de l’erreur entre le point de consigne et la sortie mesurée du système (la variable de processus).

Réponse typique d'un régulateur PID à un échelon

Les régulateurs PID trouvent de nombreuses applications dans diverses industries et domaines. Ils sont largement utilisés dans les systèmes de contrôle de processus, tels que le contrôle de la température dans la fabrication, le contrôle du débit dans les usines chimiques et le contrôle de la pression dans les systèmes de chauffage, de ventilation et de climatisation. Les régulateurs PID sont également utilisés en robotique pour un positionnement précis et un contrôle de mouvement, ainsi que dans les systèmes automobiles pour le contrôle des gaz, la régulation de la vitesse du moteur et les systèmes de freinage antiblocage. Ils jouent un rôle vital dans les applications aérospatiales et de l’aviation, notamment les pilotes automatiques d’aéronefs et les systèmes de contrôle d’attitude.

Un régulateur PID est composé de trois composants : le terme proportionnel, le terme intégral et le terme dérivé. Le terme proportionnel fournit une réponse immédiate à l’erreur actuelle, le terme intégral cumule et corrige les erreurs passées, et le terme dérivé prévoit et contrebalance les tendances d’erreur futures.

Schéma bloc d'un régulateur PID

La boucle de contrôle d’un régulateur PID est présentée dans le schéma bloc ci-dessus. r(t) est le point de consigne et y(t) est la variable de processus. La variable de processus est soustraite du point de consigne pour obtenir le signal d’erreur, e(t).

Le signal de commande, u(t), est la somme des termes proportionnel, intégral et dérivé. Le signal de commande est injecté dans le processus, ce qui provoque la mise à jour de la variable de processus.

Signal de commande du régulateur PID u(t)

L’algorithme de descente de gradient

La descente de gradient est un algorithme d’optimisation couramment utilisé en apprentissage automatique et en optimisation mathématique. Son objectif est de trouver le minimum d’une fonction de coût donnée en ajustant itérativement les paramètres en fonction du gradient de la fonction de coût. Le gradient pointe dans la direction de la plus forte ascension, donc en prenant des pas dans la direction opposée, l’algorithme converge progressivement vers la solution optimale.

Une seule étape de mise à jour de la descente de gradient est définie comme suit :

Étape de mise à jour de la descente de gradient

aₙ est un vecteur de paramètres d’entrée. L’indice n indique l’itération. f(aₙ) est une fonction de coût à plusieurs variables et ∇f(a) est le gradient de cette fonction de coût. ∇f(aₙ) représente la direction de la plus forte ascension, donc il est soustrait de aₙ pour réduire la fonction de coût à la prochaine itération. 𝛾 est le taux d’apprentissage qui détermine la taille du pas à chaque itération.

Une valeur appropriée pour 𝛾 doit être sélectionnée. Si elle est trop grande, les pas effectués à chaque itération seront trop grands et l’algorithme de descente de gradient ne convergera pas. Si elle est trop petite, l’algorithme de descente de gradient sera coûteux en termes de calculs et prendra beaucoup de temps pour converger.

Algorithme de descente de gradient appliqué à la fonction de coût y=x² (initialement x=5) pour 𝛾=0.1 (à gauche) et 𝛾=1.02 (à droite)

La descente de gradient est appliquée dans un large éventail de domaines et disciplines. En apprentissage automatique et en apprentissage profond, c’est un algorithme d’optimisation fondamental utilisé pour entraîner des réseaux neuronaux et optimiser leurs paramètres. En mettant à jour de manière itérative les poids et les biais du réseau en fonction du gradient de la fonction de coût, la descente de gradient permet au réseau d’apprendre et d’améliorer ses performances au fil du temps.

Outre l’apprentissage automatique, la descente de gradient est utilisée dans divers problèmes d’optimisation dans les domaines de l’ingénierie, de la physique, de l’économie et d’autres domaines. Elle aide à l’estimation des paramètres, à l’identification des systèmes, au traitement des signaux, à la reconstruction d’images et à de nombreuses autres tâches qui nécessitent la recherche du minimum ou du maximum d’une fonction. La polyvalence et l’efficacité de la descente de gradient en font un outil essentiel pour résoudre des problèmes d’optimisation et améliorer des modèles et des systèmes dans des domaines diversifiés.

Optimisation des gains du régulateur PID à l’aide de la descente de gradient

Il existe plusieurs méthodes pour régler un régulateur PID. Celles-ci incluent la méthode de réglage manuel et des méthodes heuristiques telles que la méthode de Ziegler-Nichols. La méthode de réglage manuel peut prendre du temps et nécessiter plusieurs itérations pour trouver les valeurs optimales, tandis que la méthode de Ziegler-Nichols donne souvent des gains agressifs et un dépassement important, ce qui la rend inadaptée à certaines applications.

Nous présentons ici une approche de descente de gradient pour l’optimisation du régulateur PID. Nous allons optimiser le système de contrôle d’un régulateur de vitesse de voiture soumis à un changement brusque de consigne.

En contrôlant la position de la pédale, l’objectif du régulateur est d’accélérer la voiture jusqu’à la consigne de vitesse avec un minimum de dépassement, de temps d’établissement et d’erreur en régime permanent.

La voiture est soumise à une force de conduite proportionnelle à la position de la pédale. La résistance au roulement et les forces de traînée aérodynamique agissent dans la direction opposée à la force de conduite. La position de la pédale est contrôlée par le régulateur PID et est limitée à une plage de -50% à 100%. Lorsque la position de la pédale est négative, la voiture freine.

Il est utile d’avoir un modèle du système lors du réglage des gains du régulateur PID. Ainsi, nous pouvons simuler la réponse du système. Pour cela, j’ai implémenté une classe Car en Python :

import numpy as npclass Car:    def __init__(self, mass, Crr, Cd, A, Fp):        self.mass = mass # [kg]        self.Crr = Crr # [-]        self.Cd = Cd # [-]        self.A = A # [m^2]        self.Fp = Fp # [N/%]        def get_acceleration(self, pedal, velocity):        # Constants        rho = 1.225 # [kg/m^3]        g = 9.81 # [m/s^2]        # Driving force        driving_force = self.Fp * pedal        # Rolling resistance force        rolling_resistance_force = self.Crr * (self.mass * g)        # Drag force        drag_force = 0.5 * rho * (velocity ** 2) * self.Cd * self.A        acceleration = (driving_force - rolling_resistance_force - drag_force) / self.mass        return acceleration        def simulate(self, nsteps, dt, velocity, setpoint, pid_controller):        pedal_s = np.zeros(nsteps)        velocity_s = np.zeros(nsteps)        time = np.zeros(nsteps)        velocity_s[0] = velocity        for i in range(nsteps - 1):            # Get pedal position [%]            pedal = pid_controller.compute(setpoint, velocity, dt)            pedal = np.clip(pedal, -50, 100)            pedal_s[i] = pedal            # Get acceleration            acceleration = self.get_acceleration(pedal, velocity)                        # Get velocity            velocity = velocity_s[i] + acceleration * dt            velocity_s[i+1] = velocity            time[i+1] = time[i] + dt                return pedal_s, velocity_s, time

La classe PIDController est implémentée comme suit :

class PIDController:    def __init__(self, Kp, Ki, Kd):        self.Kp = Kp        self.Ki = Ki        self.Kd = Kd        self.error_sum = 0        self.last_error = 0        def compute(self, setpoint, process_variable, dt):        error = setpoint - process_variable                # Terme proportionnel        P = self.Kp * error                # Terme intégral        self.error_sum += error * dt        I = self.Ki * self.error_sum                # Terme dérivé        D = self.Kd * (error - self.last_error)        self.last_error = error                # Sortie PID        output = P + I + D                return output

En adoptant cette approche de programmation orientée objet, il est beaucoup plus facile de configurer et d’exécuter plusieurs simulations avec différentes valeurs de gains de contrôleur PID, comme nous devons le faire lors de l’exécution de l’algorithme de descente de gradient.

La classe GradientDescent est implémentée comme suit :

class GradientDescent:    def __init__(self, a, learning_rate, cost_function, a_min=None, a_max=None):        self.a = a        self.learning_rate = learning_rate        self.cost_function = cost_function        self.a_min = a_min        self.a_max = a_max        self.G = np.zeros([len(a), len(a)])        self.points = []        self.result = []        def grad(self, a):        h = 0.0000001        a_h = a + (np.eye(len(a)) * h)        cost_function_at_a = self.cost_function(a)        grad = []        for i in range(0, len(a)):            grad.append((self.cost_function(a_h[i]) - cost_function_at_a) / h)        grad = np.array(grad)        return grad        def update_a(self, learning_rate, grad):        if len(grad) == 1:            grad = grad[0]        self.a -= (learning_rate * grad)        if (self.a_min is not None) or (self.a_min is not None):            self.a = np.clip(self.a, self.a_min, self.a_max)        def update_G(self, grad):        self.G += np.outer(grad,grad.T)        def execute(self, iterations):        for i in range(0, iterations):            self.points.append(list(self.a))            self.result.append(self.cost_function(self.a))            grad = self.grad(self.a)            self.update_a(self.learning_rate, grad)        def execute_adagrad(self, iterations):        for i in range(0, iterations):            self.points.append(list(self.a))            self.result.append(self.cost_function(self.a))            grad = self.grad(self.a)            self.update_G(grad)            learning_rate = self.learning_rate * np.diag(self.G)**(-0.5)            self.update_a(learning_rate, grad)

L’algorithme est exécuté pendant un nombre spécifié d’itérations en appelant execute ou execute_adagrad. La méthode execute_adagrad exécute une forme modifiée de la descente de gradient appelée AdaGrad (descente de gradient adaptative).

AdaGrad a des taux d’apprentissage par paramètre qui augmentent pour les paramètres clairsemés et diminuent pour les paramètres moins clairsemés. Le taux d’apprentissage est mis à jour après chaque itération en fonction d’une somme historique des carrés des gradients.

Nous utiliserons AdaGrad pour optimiser les gains du contrôleur PID du système de régulateur de vitesse de la voiture. En utilisant AdaGrad, l’équation de mise à jour de la descente de gradient devient :

Étape de mise à jour de la descente de gradient AdaGrad

Maintenant, nous devons définir notre fonction de coût. La fonction de coût doit prendre un vecteur de paramètres d’entrée en tant qu’entrée et renvoyer un seul nombre ; le coût. L’objectif du régulateur de vitesse de la voiture est d’accélérer la voiture jusqu’à la consigne de vitesse avec un minimum de dépassement, de temps d’établissement et d’erreur à l’état stable. Il existe de nombreuses façons de définir la fonction de coût en fonction de cet objectif. Ici, nous la définirons comme l’intégrale de l’amplitude de l’erreur au fil du temps :

Fonction de coût du régulateur de vitesse de la voiture

Étant donné que notre fonction de coût est une intégrale, nous pouvons la visualiser comme l’aire sous la courbe de l’amplitude de l’erreur. Nous nous attendons à voir l’aire sous la courbe diminuer à mesure que nous nous approchons du minimum global. Programmation, la fonction de coût est définie comme suit :

def car_cost_function(a):    # Paramètres de la voiture    masse = 1000.0  # Masse de la voiture [kg]    Cd = 0.2  # Coefficient de traînée []    Crr = 0.02 # Coefficient de résistance au roulement []    A = 2.5 # Surface frontale de la voiture [m^2]    Fp = 30 # Force d'entraînement par position de pédale [%]    # Paramètres du contrôleur PID    Kp = a[0]    Ki = a[1]    Kd = a[2]    # Paramètres de simulation    dt = 0.1  # Pas de temps    total_time = 60.0  # Temps total de simulation    nsteps = int(total_time / dt)    vitesse_initiale = 0.0  # Vitesse initiale de la voiture [m/s]    vitesse_cible = 20.0 # Vitesse cible de la voiture [m/s]    # Définir les objets Car et PIDController    voiture = Car(masse, Crr, Cd, A, Fp)    regulateur_pid = PIDController(Kp, Ki, Kd)    # Exécuter la simulation    position_p, vitesse_p, temps = voiture.simuler(nsteps, dt, vitesse_initiale, vitesse_cible, regulateur_pid)    # Calculer le coût    coût = np.trapz(np.absolute(vitesse_cible - vitesse_p), temps)    return coût

La fonction de coût comprend les paramètres de simulation. La simulation est exécutée pendant 60 secondes. Pendant ce temps, nous observons la réponse du système à une variation brusque du point de consigne de 0 m/s à 20 m/s. En intégrant la magnitude de l’erreur dans le temps, le coût est calculé pour chaque itération.

Maintenant, il ne reste plus qu’à exécuter l’optimisation. Nous commencerons avec des valeurs initiales de Kp = 5,0, Ki = 1,0 et Kd = 0,0. Ces valeurs donnent une réponse stable et oscillante, avec un dépassement, qui finit par converger vers le point de consigne. À partir de ce point de départ, nous exécuterons l’algorithme de descente de gradient pendant 500 itérations en utilisant un taux d’apprentissage de base de 𝛾=0,1 :

a = np.array([5.0, 1.0, 0.0])gradient_descent = GradientDescent(a, 0.1, car_cost_function, a_min=[0,0,0])gradient_descent.execute_adagrad(500)
Réponse à l'échelon du régulateur de vitesse de la voiture (gauche), magnitude de l'erreur (milieu) et coût (droite) à mesure que l'algorithme de descente de gradient itère vers une solution optimale

Le graphique animé ci-dessus montre l’évolution de la réponse à l’échelon du régulateur de vitesse de la voiture alors que l’algorithme de descente de gradient ajuste les gains Kp, Ki et Kd du régulateur PID.

Au bout de 25 itérations, l’algorithme de descente de gradient a éliminé la réponse oscillatoire. Après ce point, quelque chose d’intéressant se produit. L’algorithme se retrouve dans un minimum local caractérisé par un dépassement d’environ 3 m/s. Cela se produit dans la région de 6,0 < Kp < 7,5, Ki ~= 0,5, Kd = 0,0 et dure jusqu’à l’itération 300.

Après l’itération 300, l’algorithme sort du minimum local pour trouver une réponse plus satisfaisante plus proche du minimum global. La réponse est maintenant caractérisée par un dépassement nul, un temps d’établissement rapide et une erreur à l’état stable proche de zéro.

En exécutant l’algorithme de descente de gradient pendant 500 itérations, nous obtenons les gains optimisés du régulateur PID : Kp = 8,33, Ki = 0,12 et Kd = 0,00.

Le gain proportionnel continue d’augmenter régulièrement. En exécutant plus d’itérations (non montrées ici), à mesure que Kp augmente lentement, nous constatons qu’une réduction supplémentaire de la fonction de coût est possible, bien que cet effet devienne de plus en plus marginal.

Résumé

En adoptant une méthode largement utilisée pour résoudre des problèmes d’apprentissage automatique et d’apprentissage profond, nous avons réussi à optimiser les gains du régulateur PID pour un système de régulateur de vitesse de voiture.

En commençant par des valeurs initiales de Kp = 5,0, Ki = 1,0 et Kd = 0,0 et en appliquant la forme AdaGrad de l’algorithme de descente de gradient, nous avons observé comment ce système de basse dimension se promène d’abord dans un minimum local avant de trouver finalement une réponse plus satisfaisante avec un dépassement nul, un temps d’établissement rapide et une erreur à l’état stable proche de zéro.

Dans cet article, nous avons vu comment la descente de gradient peut être un outil puissant lorsqu’elle est appliquée à des problèmes d’optimisation classiques en ingénierie. Au-delà de l’exemple présenté ici, la descente de gradient peut être utilisée pour résoudre d’autres problèmes d’ingénierie tels que la cinématique inverse en robotique, l’optimisation de la topologie et bien d’autres.

Avez-vous un problème d’optimisation auquel vous pensez que la descente de gradient pourrait s’appliquer ? Faites-le moi savoir dans les commentaires ci-dessous.

Vous avez aimé cet article ?

Suivez et abonnez-vous pour plus de contenu comme celui-ci – partagez-le avec votre réseau – essayez d’appliquer la descente de gradient à vos propres problèmes d’optimisation.

Toutes les images, sauf indication contraire, sont de l’auteur.

Références

Web

[1] GitHub (2023), pid_controller_gradient_descent

[2] Wikipedia (2023), méthode de Ziegler-Nichols (consulté le 10 juillet 2023)

We will continue to update IPGirl; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

AI

Cet article AI présente RuLES Un nouveau cadre d'apprentissage automatique pour évaluer la conformité aux règles dans les grands modèles de langage face aux attaques adverses.

En réponse au déploiement croissant des Modèles de Langue à Large Mémoire (LLMs) avec des responsabilités réelles, un...

AI

Prédictions de fréquentation en temps réel pour les voyageurs en train

Les voyageurs des Chemins de fer néerlandais peuvent utiliser l'application de l'agence ferroviaire néerlandaise pour...

AI

Les agents d'intelligence artificielle personnalisés sont là. Le monde est-il prêt pour eux?

L'ère des assistants autonomes d'intelligence artificielle pourrait avoir d'énormes implications.

AI

Améliorer la gestion des stocks grâce à l'apprentissage automatique et à l'intelligence artificielle

L'intelligence artificielle (IA) peut grandement améliorer l'efficacité des systèmes de gestion des stocks, en aidant...

AI

Analyse de la qualité de l'eau avec Python et analyse de la potabilité

Être en mesure de fournir suffisamment d'eau potable fraîche est une exigence fondamentale. Dans le débat sur le chan...

AI

Cette recherche en IA présente une nouvelle distillation de pose en deux étapes pour l'estimation de la pose du corps entier.

De nombreuses tâches de perception, de compréhension et de création centrées sur l’humain dépendent de l’...