[PYTHON] Recherche de points de selle à l'aide de la méthode du gradient

1. Qu'est-ce qu'une pointe de selle?

Un point de selle est un point où la pente est de 0 et le minimum est pris dans une certaine direction et le maximum est pris dans une certaine direction. C'est un thème important dans divers domaines, comme représenté par le GAN dans l'apprentissage automatique et les états de transition dans la recherche de voies de réaction chimique. Le GAN se compose d'un générateur qui génère des données qui ressemblent exactement à la chose réelle et d'un discriminateur qui fait la distinction entre les données réelles et les données générées. Le générateur apprend à prendre le maximum et le discriminateur apprend à prendre le minimum. Dans la réaction chimique, diverses matières premières stables passent par les points de selle sur la surface incurvée d'énergie potentielle et se transforment en composés plus stables. Dans cet article, nous rechercherons des points de selle en utilisant la méthode du dégradé. Cette méthode est efficace pour les modèles simples, mais elle se comporte quelque peu instable pour les modèles complexes (par exemple, chimie quantique, etc.), donc je l'ajouterai dès qu'elle pourra être améliorée. Si cet article vous intéresse, LGTM! S'il vous plaît.

2. Définition du point de selle

Décrivez le point de selle comme suit. La fonction objectif est $ y = f (\ boldsymbol {x}) $, $ \ boldsymbol {x} = (x_1, x_2, \ cdots, x_n) ^ \ rm {T} $, et le vecteur unitaire correspondant à la valeur minimale est $ \ boldsymbol {b} = (b_1, b_2, \ cdots, b_n) ^ \ rm {T} $, le vecteur unitaire correspondant à la valeur maximale est $ \ boldsymbol {c} = (c_1, c_2, \ cdots, c_n) ^ Défini comme \ rm {T} $. A ce moment, le gradient de $ f $ devient $ 0 $, et $ y = f (\ boldsymbol {x} + \ boldsymbol {b} t) $ prend la valeur minimale à $ t = 0 $ par rapport à $ t $, et $ y Le point de selle est que = f (\ boldsymbol {x} + \ boldsymbol {c} t) $ prend la valeur maximale à $ t = 0 $ par rapport à $ t $. La formule est la suivante.

Au point de selle $ \ boldsymbol {x} = \ boldsymbol {x} _0 $

\left.\frac{\partial f(\boldsymbol{x})}{\partial \boldsymbol{x}}\right |_{\boldsymbol{x}=\boldsymbol{x}_0}= 0\\

\left.\frac{\partial^2 f(\boldsymbol{x}+\boldsymbol{b}t)}{\partial t^2}\right |_{\boldsymbol{x}=\boldsymbol{x}_0, t=0} > 0\\

\left.\frac{\partial^2 f(\boldsymbol{x}+\boldsymbol{c}t)}{\partial t^2}\right |_{\boldsymbol{x}=\boldsymbol{x}_0, t=0} < 0

Est établi.

Considérez $ y = x_1 ^ 2-x_2 ^ 2 $ comme exemple. À $ x_1 = 0 $, $ x_2 = 0 $, le dégradé devient $ 0 $, et à $ \ boldsymbol {b} = (1, 0) ^ \ rm {T} $, $ y = (0 + 1 t) ^ 2- (0 + 0 t) ^ 2 = t ^ 2 $ prend une valeur minimale à $ t = 0 $, et $ y = à $ \ boldsymbol {c} = (0, 1) ^ \ rm {T} $ (0 + 0 t) ^ 2- (0 + 1t) ^ 2 = -t ^ 2 $ prend la valeur maximale à $ t = 0 $. Par conséquent, ce point peut être estimé comme étant un point de selle.

3. Recherche de point de selle

Cette méthode comprend deux étapes: l'initialisation et l'exploration. L'initialisation trouve les valeurs initiales appropriées pour $ \ boldsymbol {b} $ et $ \ boldsymbol {c} $. Dans la recherche, les points de selle sont recherchés en fonction du gradient.

3.1 Initialisation

Comme mentionné ci-dessus, $ \ boldsymbol {b} $ correspond à la valeur maximale, et $ \ boldsymbol {c} $ correspond à la valeur minimale. Tout d'abord, déterminez $ \ boldsymbol {b} $ qui maximise la différenciation de second ordre de $ y = f (\ boldsymbol {x} + \ boldsymbol {b} t) $ par rapport à $ t $. Par souci de simplicité, nous utiliserons la méthode répétitive utilisant la méthode re-deep. La formule est la suivante.

\mathrm{grad}\ \boldsymbol{b}_1 \leftarrow \frac{1}{\delta} \left( \nabla f \left(\boldsymbol{x}+\delta \boldsymbol{b} \right) - \nabla f \left(\boldsymbol{x}-\delta \boldsymbol{b} \right) \right)\\

\mathrm{grad}\ \boldsymbol{b}_2 \leftarrow \mathrm{grad}\ \boldsymbol{b}_1 - \left( \boldsymbol{b} \cdot \mathrm{grad}\ \boldsymbol{b}_1 \right)\boldsymbol{b}\\

\boldsymbol{b} \leftarrow \boldsymbol{b} + \epsilon_1 \ \mathrm{grad}\ \boldsymbol{b}_2\\

\boldsymbol{b} \leftarrow \frac{\boldsymbol{b}}{\mathrm{norm} \left(\boldsymbol{b}\right)}\\

Le montant des minutes est de $ \ delta $ et le taux d'apprentissage est de $ \ epsilon_1 $. La première équation est la différenciation de l'espace euclidien de dimension $ n $ par rapport à la base. En tant qu'appareil, la formule a été transformée pour que le dégradé puisse être utilisé. Si cela est utilisé comme montant de mise à jour tel quel, il n'est pas approprié pour le vecteur unitaire $ \ boldsymbol {b} $, il est donc nécessaire de le convertir en montant de mise à jour de $ \ boldsymbol {b} $ le long de la sphère unitaire dans la deuxième équation. il y a. La troisième formule est mise à jour vers la valeur maximale et la quatrième formule est normalisée pour en faire un vecteur unitaire. De même, déterminez $ \ boldsymbol {c} $ tel que le différentiel du second ordre de $ y = f (\ boldsymbol {x} + \ boldsymbol {c} t) $ par rapport à $ t $ soit maximisé. La formule est la suivante.

\mathrm{grad}\ \boldsymbol{c}_1 \leftarrow \frac{1}{\delta} \left( \nabla f \left(\boldsymbol{x}+\delta \boldsymbol{c} \right) - \nabla f \left(\boldsymbol{x}-\delta \boldsymbol{c} \right) \right)\\

\mathrm{grad}\ \boldsymbol{c}_2 \leftarrow \mathrm{grad}\ \boldsymbol{c}_1 - \left( \boldsymbol{c} \cdot \mathrm{grad}\ \boldsymbol{c}_1 \right)\boldsymbol{c}\\

\boldsymbol{c} \leftarrow \boldsymbol{c} - \epsilon_1 \ \mathrm{grad}\ \boldsymbol{c}_2\\

\boldsymbol{c} \leftarrow \frac{\boldsymbol{c}}{\mathrm{norm} \left(\boldsymbol{c}\right)}

La différence avec $ \ boldsymbol {b} $ est qu'il est mis à jour dans le sens de la valeur minimale dans la troisième équation. Vous pouvez utiliser $ \ mathrm {grad} \ \ boldsymbol {b} \ _2 $ et $ \ mathrm {grad} \ \ boldsymbol {c} \ _2 $ comme jugements de convergence.

3.2 Recherche de point de selle

La recherche utilise $ \ mathrm {grad} \ \ boldsymbol {b} \ _2 $ et $ \ mathrm {grad} \ \ boldsymbol {c} \ _2 $. En effet, il existe une valeur minimale dans le sens $ - \ mathrm {grad} \ \ boldsymbol {b} \ _2 $ et une valeur maximale dans le sens $ \ mathrm {grad} \ \ boldsymbol {c} \ _2 $. Vous pouvez atteindre le point de selle en mettant à jour en fonction de. La formule est la suivante.

\boldsymbol{x} \leftarrow \boldsymbol{x} + \epsilon_2 \ \left( -\mathrm{grad}\ \boldsymbol{b}_2 +\mathrm{grad}\ \boldsymbol{c}_2 \right)

De plus, $ \ mathrm {grad} \ \ boldsymbol {b} _2 $ et $ \ mathrm {grad} \ \ boldsymbol {c} _2 $ ont changé en fonction de la mise à jour de $ \ boldsymbol {x} $, donc l'initialisation Vous devez également faire $ \ boldsymbol {b} $ et $ \ boldsymbol {c} $ en même temps.

4. Mise en œuvre

Les points de selle de diverses fonctions ont été calculés selon l'algorithme ci-dessus. La méthode de mise à jour a utilisé la méthode de re-plongée et a été exécutée en Python. La ligne rouge est le vecteur de valeur minimum et la ligne verte est le vecteur de valeur maximum.

・ Fonction $ y = x_1 ^ 2-x_2 ^ 2 $ Valeur initiale $ x_1 = -2 $, $ x_2 = -1 $ Petit montant $ \ delta = 0,001 $ Taux d'apprentissage $ \ epsilon_1 = 0,1 $, $ \ epsilon_1 = 0,1 $ résultat Point de selle $ x_1 = -0,0003 $, $ x_2 = -0,001 $  \boldsymbol{b}=(1,0)^\rm{T}\boldsymbol{c}=(0,1)^\rm{T}

Initialisation

Recherche de point de selle

・ Fonction $ y = x_1 ^ 2 + x_2 ^ 3-x_2 $ Valeur initiale $ x_1 = -2 $, $ x_2 = -0,5 $ Petit montant $ \ delta = 0,05 $ Taux d'apprentissage $ \ epsilon_1 = 0,1 $, $ \ epsilon_1 = 0,1 $ résultat Point de selle $ x_1 = -0,0011 $, $ x_2 = -0,5774 $  \boldsymbol{b}=(1,0)^\rm{T}\boldsymbol{c}=(0,1)^\rm{T}

Initialisation

Recherche de point de selle

5. Défis

Comme amélioration, puisqu'il s'agit d'une méthode de gradient, divers optimiseurs (par exemple Momentum, RMSProp, Adam, RAdam) et des méthodes wegstain dans la méthode du gradient conjugué et l'apprentissage automatique peuvent être utilisés. Le problème est qu'il n'est pas stable. Je me suis demandé s'il pouvait être utilisé pour la recherche de point de selle qui pourrait être utilisé pour la prédiction de réactions chimiques, mais il a convergé avec une structure étrange. De plus, en fonction de la valeur initiale, il peut ne pas converger vers le point de selle. Un exemple est présenté ci-dessous. Ceci est différent de la valeur initiale de l'exemple précédent.

・ Fonction $ y = x_1 ^ 2 + x_2 ^ 3-x_2 $ Valeur initiale $ x_1 = -2 $, $ x_2 = -0,5 $ Petit montant $ \ delta = 0,05 $ Taux d'apprentissage $ \ epsilon_1 = 0,1 $, $ \ epsilon_1 = 0,1 $

Initialisation

Recherche de point de selle

Dans cet exemple, $ \ boldsymbol {b} $ et $ \ boldsymbol {c} $ ont été mis à jour afin que la direction de $ x_2 $ ait la valeur minimale et la direction de $ x_1 $ la valeur maximale. Par conséquent, tout en actualisant vers la valeur minimale de la fonction cubique, nous montons régulièrement la pente de la fonction quadratique.

6. Conclusion

Dans cet article, nous avons recherché des points de selle à l'aide de la méthode du dégradé. Un exemple de fonction à deux variables est présenté pour la visibilité, mais vous pouvez en fait utiliser une fonction de variable arbitraire. Si vous avez des questions, nous vous répondrons dans les commentaires. N'hésitez pas à commenter si vous avez des demandes de transformations de formules ou de code source.

7. Code source (fonction quadratique)

Il existe des paramètres tels que les fonctions, les valeurs initiales et la vitesse d'apprentissage dans «Initialisation du calcul 1». Vous pouvez modifier le contenu de la classe SDG en différents optimiseurs.

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from datetime import datetime
np.set_printoptions(precision=4, floatmode='maxprec')

class SDG:
    def __init__(self, learning_rate):
        self.learning_rate = learning_rate
        
    def solve(self, coord, gradient):
        return coord - self.learning_rate*gradient

class SaddlePoint:
    
    def __init__(self, function, gradient, coordinate, delta=1.0e-3,
                 learning_rate=0.5, max_iteration=1000,
                 judgment1=1.0e-8, judgment2=1.0e-8, log_span=100):
        """
Constructeur d'initialisation
        function --Fonction objective
        differential --Différenciation de premier ordre des fonctions
        coordinates --Coordonnées initiales
        delta --Petite valeur
        learning_rate --Taux d'apprentissage
        judgment --Jugement de convergence 1
        judgment --Arrêt de convergence 2
        log_span --Intervalle d'affichage du journal
        """
        self.function = function
        self.gradient = gradient
        self.coordinate = coordinate.copy()
        self.dim = len(coordinate)
        self.delta = delta
        self.learning_rate = learning_rate
        self.max_iteration = max_iteration
        self.judgment1 = judgment1
        self.judgment2 = judgment2
        self.log_span = log_span
        
        #Vecteur de base
        self.b = np.random.rand(self.dim)
        self.b /= np.linalg.norm(self.b)
        self.c = np.random.rand(self.dim)
        self.c /= np.linalg.norm(self.c)
        
        # SDG
        self.sdg_b_init = SDG(learning_rate)
        self.sdg_c_init = SDG(learning_rate)
        self.sdg_b_solv = SDG(learning_rate)
        self.sdg_c_solv = SDG(learning_rate)
        self.sdg_a_solv = SDG(learning_rate)
        
    def initialize(self):
        """
Fonction à initialiser. Approprié b,Déterminer c
Valeur de retour--Vecteur de direction de valeur minimale b,Vecteur de direction de valeur maximale c
        """
        #Pente
        gradient = self.gradient
        #Coordonnée b
        coordinate = self.coordinate
        #Vecteur de base
        b = self.b.copy()
        c = self.c.copy()
        #Mettre à jour le montant
        diff_b = np.zeros_like(b)
        diff_c = np.zeros_like(c)
        #Taux d'apprentissage
        learning_rate = self.learning_rate
        #Petite valeur
        delta = self.delta
        #Standardisation
        norm = np.linalg.norm
        #Jugement
        judgement1 = self.judgment1
        #Intervalle de journalisation
        log_span = self.log_span
        # SDG
        sdg_b = self.sdg_b_init
        sdg_c = self.sdg_c_init
        
        z, _ = gradient(coordinate)
        
        print("-----Initialization of b has started.-----")
        for i in range(self.max_iteration):
            #Différentiel de premier ordre
            z_b1, grad_b1 = gradient(coordinate + delta*b)
            z_b2, grad_b2 = gradient(coordinate - delta*b)
            #Modifier le calcul du montant
            nabla_b = (grad_b1 - grad_b2)/delta
            grad_b = nabla_b - (np.dot(b, nabla_b))*b
            #mise à jour
            b = sdg_b.solve(b, -grad_b)
            #Standardisation
            b /= norm(b)
            #Jugement de convergence
            error = np.linalg.norm(grad_b)
            if i%log_span == 0:
                print("Iteration = {}, Error = {}".format(i, error))
            if error < judgement1:
                print("Converged! Iteration = {}, Error = {}".format(i, error))
                break
        self.b = b.copy()
        
        print()
        print("-----Initialization of c has started.-----")
        for i in range(self.max_iteration):
            #Calcul du gradient
            z_c1, grad_c1 = gradient(coordinate + delta*c)
            z_c2, grad_c2 = gradient(coordinate - delta*c)
            #Modifier le calcul du montant
            nabla_c = (grad_c1 - grad_c2)/delta
            grad_c = nabla_c - (np.dot(c, nabla_c))*c
            #mise à jour
            c = sdg_c.solve(c, grad_c)
            #Standardisation
            c /= norm(c)
            #Jugement de convergence
            error = np.linalg.norm(grad_c)
            if i%log_span == 0:
                print("Iteration = {}, Error = {}".format(i, error))
            if error < judgement1:
                print("Converged! Iteration = {}, Error = {}".format(i, error))
                break
        self.c = c.copy()
        
        print()
        print("Result")
        print("b = {}".format(self.b))
        print("c = {}".format(self.c))
        print()
        return self.b, self.c
    
    def solve(self):
        """
Rechercher des points de selle
Valeur de retour--Coordonnée des coordonnées du point de selle,Vecteur de direction de valeur minimale b,Vecteur de direction de valeur maximale c
        """
        #Pente
        gradient = self.gradient
        #Coordonnées, une collection de coordonnées
        coordinate = self.coordinate.copy()
        coordinate_Array = coordinate.copy()
        #Vecteur de base
        b = self.b.copy()
        c = self.c.copy()
        #Mettre à jour le montant
        diff_b = np.zeros_like(b)
        diff_c = np.zeros_like(c)
        #Taux d'apprentissage
        learning_rate = self.learning_rate
        #Petite valeur
        delta = self.delta
        #Standardisation
        norm = np.linalg.norm
        #Jugement
        judgement1 = self.judgment1
        judgement2 = self.judgment2
        #Intervalle de journalisation
        log_span = self.log_span
        # SDG
        sdg_a = self.sdg_a_solv
        sdg_b = self.sdg_b_solv
        sdg_c = self.sdg_c_solv
        
        print("-----Saddle-point solver has started.-----")
        for i in range(self.max_iteration):
            #Différentiel de premier ordre
            z_b1, grad_b1 = gradient(coordinate + delta*b)
            z_b2, grad_b2 = gradient(coordinate - delta*b)
            z_c1, grad_c1 = gradient(coordinate + delta*c)
            z_c2, grad_c2 = gradient(coordinate - delta*c)
            grad_through_b = (z_b1-z_b2) / (2.0*delta)
            grad_through_c = (z_c1-z_c2) / (2.0*delta)
            #Différentiel de second ordre
            z, _ = gradient(coordinate)
            grad2_through_b = (z_b1-2.0*z+z_b2) / delta**2.0
            grad2_through_c = (z_c1-2.0*z+z_c2) / delta**2.0
            
            #mise à jour
#            coordinate = sdg_a.solve(coordinate,
#                                     grad_through_b*b/(np.linalg.norm(grad_through_b)+np.linalg.norm(grad2_through_b))
#                                     -grad_through_c*c/(np.linalg.norm(grad_through_c)+np.linalg.norm(grad2_through_c)))
            coordinate = sdg_a.solve(coordinate, grad_through_b*b - grad_through_c*c)
            coordinate_Array = np.vstack([coordinate_Array, coordinate])
            #Jugement de convergence
            error_coordinate = np.linalg.norm(grad_through_b**2 + grad_through_c**2)
            
            # b,mise à jour de c
            nabla_b = -(grad_b1 - grad_b2)/delta
            grad_b = nabla_b - (np.dot(b, nabla_b))*b
            #mise à jour
            b = sdg_b.solve(b, grad_b)
            #Standardisation
            b /= norm(b)
            #Jugement de convergence
            error_b = np.linalg.norm(grad_b)
            
            nabla_c = (grad_c1 - grad_c2)/delta
            grad_c = nabla_c - (np.dot(c, nabla_c))*c
            #mise à jour
            c = sdg_c.solve(c, grad_c)
            #Standardisation
            c /= norm(c)
            #Jugement de convergence
            error_c = np.linalg.norm(grad_c)
            
            if i%log_span == 0:
                print("B converged! Iteration = {}, Error = {}".format(i, error_b))
                print("C converged! Iteration = {}, Error = {}".format(i, error_c))
                print("Iteration = {}, Error = {}".format(i, error_coordinate))
                print()
            if error_coordinate < judgement2:
                print("Converged! Iteration = {}, Error = {}".format(i, error_coordinate))
                break
        
        self.coordinate = coordinate.copy()
        self.b = b.copy()
        self.c = c.copy()
        
        print()
        print("Result")
        print("coordinate = {}".format(self.coordinate))
        print("b = {}".format(self.b))
        print("c = {}".format(self.c))
        print()
        return self.coordinate, coordinate_Array, self.b, self.c
# =============================================================================
#Initialisation du calcul 1
# =============================================================================
def f(x):
    #une fonction
    return x[0]**2 - x[1]**2

def gradient_f(x):
    #Différenciation de premier ordre des fonctions
    return f(x), np.array([2*x[0], -2*x[1]])

x_init = np.array([-2.0, -1.0], dtype="float")

saddlePoint = SaddlePoint(f, gradient_f, x_init, delta=1e-3,
                          learning_rate=0.1, max_iteration=100,
                          judgment1=1.0e-5, judgment2=1.0e-5, log_span=1)

b, c = saddlePoint.initialize() #Initialisation

# =============================================================================
#Dessin graphique(2D)
# =============================================================================
t = np.linspace(-1.0, 1.0, 100)
tb = np.linspace(x_init-1.0*b, x_init+1.0*b, 100)
tc = np.linspace(x_init-1.0*c, x_init+1.0*c, 100)
fb = f(tb.T)
fc = f(tc.T)
plt.xlabel("t")
plt.ylabel("z")
plt.plot(t, fb, c="red")
plt.plot(t, fc, c="green")
plt.savefig("file/" + str(datetime.now().strftime("%Y_%m_%d_%H_%M_%S")) + "_2d1.png ", dpi=300)
plt.show()

# =============================================================================
#Dessin graphique(3D)
# =============================================================================
#Cadre en fil
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
X = np.linspace(-2.5, 2.5, 50)
Y = np.linspace(-2.5, 2.5, 50)
X, Y = np.meshgrid(X, Y)
Z = f([X,Y])

#Vecteur de base
width = 1.0
bt = np.linspace(x_init-width*b,x_init+width*b,10)
bz = f(bt.T)
ct = np.linspace(x_init-width*c,x_init+width*c,10)
cz = f(ct.T)

#Trajectoire
zArray = f(x_init)
#afficher
ax.plot_wireframe(X,Y,Z,color="gray",linewidth=0.2) #Cadre en fil
ax.plot(bt[:,0],bt[:,1],bz,color="red") #Minimal
ax.plot(ct[:,0],ct[:,1],cz,color="green") #maximum
ax.scatter(x_init[0],x_init[1],f(x_init),color="blue") #Trajectoire
plt.savefig("file/" + str(datetime.now().strftime("%Y_%m_%d_%H_%M_%S")) + "_3d1.png ", dpi=300)
plt.show()

# =============================================================================
#Calcul 2 recherche de point de selle
# =============================================================================
x, xArray, b, c = saddlePoint.solve() #Calcul du point de selle

# =============================================================================
#Dessin graphique(2D)
# =============================================================================
t = np.linspace(-1.0, 1.0, 100)
tb = np.linspace(x-1.0*b, x+1.0*b, 100)
tc = np.linspace(x-1.0*c, x+1.0*c, 100)
fb = f(tb.T)
fc = f(tc.T)
plt.xlabel("t")
plt.ylabel("z")
plt.plot(t, fb, c="red")
plt.plot(t, fc, c="green")
plt.savefig("file/" + str(datetime.now().strftime("%Y_%m_%d_%H_%M_%S")) + "_2d2.png ", dpi=300)
plt.show()

# =============================================================================
#Dessin graphique(2D)
# =============================================================================
#Cadre en fil
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
X = np.linspace(-2.5, 2.5, 50)
Y = np.linspace(-2.5, 2.5, 50)
X, Y = np.meshgrid(X, Y)
Z = f([X,Y])

#Vecteur de base
width = 1.0
bt = np.linspace(x-width*b,x+width*b,10)
bz = f(bt.T)
ct = np.linspace(x-width*c,x+width*c,10)
cz = f(ct.T)

#Trajectoire
zArray = f(xArray.T)

#afficher
ax.plot_wireframe(X,Y,Z,color="gray",linewidth=0.2) #Cadre en fil
ax.plot(bt[:,0],bt[:,1],bz,color="red") #Minimal
ax.plot(ct[:,0],ct[:,1],cz,color="green") #maximum
ax.scatter(xArray[:,0],xArray[:,1],zArray,color="blue") #Trajectoire
ax.text(xArray[0,0],xArray[0,1],zArray[0], "start")
ax.text(xArray[-1,0],xArray[-1,1],zArray[-1], "goal")
plt.savefig("file/" + str(datetime.now().strftime("%Y_%m_%d_%H_%M_%S")) + "_3d2.png ", dpi=300)
plt.show()

Recommended Posts

Recherche de points de selle à l'aide de la méthode du gradient
Pensez grossièrement à la méthode de descente de gradient
Essayez l'analyse de cluster par K-means
Méthode de planification secondaire par méthode de point interne
Rechercher la structure d'adsorption à l'aide de la méthode Minima Hopping
Implémentation de la méthode de gradient 1
Générez des valeurs de hachage à l'aide de la méthode HMAC.
Approximer une courbe de Bézier à travers un point spécifié en utilisant la méthode des moindres carrés en Python
Calcul de l'itinéraire le plus court selon la méthode de Monte Carlo
Déterminer le seuil à l'aide de la méthode P-tile en python
J'ai essayé de regrouper les données ECG en utilisant la méthode K-Shape
Utiliser l'API de recherche de la Bibliothèque du Parlement national en Python
Liste des méthodes de descente de gradient (2020)
Rechercher sur Twitter avec Python
Appel de méthode avec __getattr__
Essayez une recherche similaire de recherche d'images à l'aide du SDK Python [Recherche]
[Python] Régression LASSO avec contrainte d'équation utilisant la méthode du multiplicateur
Sortie du résultat de la méthode de descente de dégradé sous forme d'animation matplotlib