[PYTHON] Apprenez en implémentant avec Scipy Les bases de la régression logistique et du perceptron multicouche

Dans Optimisation telle que l'interpolation et l'ajustement de courbe, nous avons appris à approximer diverses courbes. Alors, quelle courbe devrions-nous approximer si $ Y $ n'a que 0 $ ou 1 $, comme suit?

X1 = [4.7, 4.5, 4.9, 4.0, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 
      3.5, 4.2, 4.0, 4.7, 3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 
      4.8, 4.0, 4.9, 4.7, 4.3, 4.4, 4.8, 5.0, 4.5, 3.5, 
      3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4.0, 
      4.4, 4.6, 4.0, 3.3, 4.2, 4.2, 4.2, 4.3, 3.0, 4.1, 
      6.0, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 
      5.1, 5.3, 5.5, 5.0, 5.1, 5.3, 5.5, 6.7, 6.9, 5.0, 
      5.7, 4.9, 6.7, 4.9, 5.7, 6.0, 4.8, 4.9, 5.6, 5.8, 
      6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 
      5.6, 5.1, 5.1, 5.9, 5.7, 5.2, 5.0, 5.2, 5.4, 5.1]

Y = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Illustrons les données pour le moment.

%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(12,4))
plt.scatter(X1, Y)
plt.grid()
plt.show()

output_3_1.png

Retour logistique

Pour approcher une telle relation, nous utilisons la "régression logistique", qui se rapproche d'une courbe sigmoïde. Implémentons-le avec scipy.optimize.curve_fit.

#Convertissons une liste Python en un tableau Numpy.
import numpy as np
X1 = np.array(X1)
Y = np.array(Y)

La variable explicative se rapproche d'une courbe sigmoïde

Définit une courbe sigmoïde func1 avec une variable explicative. Vous optimiserez $ a $ et $ b $.

import numpy as np
def func1(X, a, b): #Courbe Sigmaid
    f = a + b * X
    return 1. / (1. + np.exp(-f))

Un exemple d'utilisation de func1 ressemble à ceci.

func1(X1, 1, 1)
array([0.99666519, 0.99592986, 0.99726804, 0.99330715, 0.99631576,
       0.99592986, 0.99666519, 0.98661308, 0.99631576, 0.99260846,
       0.98901306, 0.9945137 , 0.99330715, 0.99666519, 0.9900482 ,
       0.99550373, 0.99592986, 0.9939402 , 0.99592986, 0.99260846,
       0.99698158, 0.99330715, 0.99726804, 0.99666519, 0.9950332 ,
       0.99550373, 0.99698158, 0.99752738, 0.99592986, 0.98901306,
       0.99183743, 0.9909867 , 0.99260846, 0.99776215, 0.99592986,
       0.99592986, 0.99666519, 0.99550373, 0.9939402 , 0.99330715,
       0.99550373, 0.99631576, 0.99330715, 0.98661308, 0.9945137 ,
       0.9945137 , 0.9945137 , 0.9950332 , 0.98201379, 0.9939402 ,
       0.99908895, 0.99776215, 0.99899323, 0.99864148, 0.99888746,
       0.9994998 , 0.99592986, 0.99932492, 0.99888746, 0.99917558,
       0.99776215, 0.99816706, 0.99849882, 0.99752738, 0.99776215,
       0.99816706, 0.99849882, 0.99954738, 0.99962939, 0.99752738,
       0.9987706 , 0.99726804, 0.99954738, 0.99726804, 0.9987706 ,
       0.99908895, 0.99698158, 0.99726804, 0.99864148, 0.99888746,
       0.99917558, 0.99938912, 0.99864148, 0.99776215, 0.99864148,
       0.99917558, 0.99864148, 0.99849882, 0.99698158, 0.9983412 ,
       0.99864148, 0.99776215, 0.99776215, 0.99899323, 0.9987706 ,
       0.99797468, 0.99752738, 0.99797468, 0.9983412 , 0.99776215])

Utilisez scipy.optimize.curve_fit pour obtenir la solution optimale pour $ a $ et $ b $.

from scipy.optimize import curve_fit  
popt, pcov = curve_fit(func1,X1,Y) #popt est l'estimation optimale, pcov est la covariance
popt
array([-47.16056308,   9.69474387])

C'est la solution optimale pour $ a $ et $ b $.

Lorsque $ X_1 $ est renvoyé à la courbe sigmoïde en utilisant la solution optimale obtenue, la valeur prédite de $ Y $ est "correctement classée comme 1 lors de la prédiction de sa classification comme 0 ou 1." Cela peut être interprété comme une «probabilité d'être». Regardons la distribution de cette probabilité.

plt.figure(figsize=(12,4))
plt.hist(func1(X1, -47.16056308,   9.69474387))
plt.grid()
plt.show()

output_13_0.png

Lorsque $ X_1 $ est renvoyé à la courbe sigmoïde en utilisant la solution optimale obtenue, la figure ci-dessous est obtenue. Les points bleus sont les données d'origine, les courbes sont les courbes de régression et les points orange sont les données après la régression. Cet axe vertical représente «la probabilité que le classement à 1 $ soit correct pour prédire s'il sera classé comme 0 $ ou 1 $».

output_15_0.png

Défi 1

Utilisez matplotlib pour illustrer la courbe de régression comme indiqué ci-dessus.

Estimation de la précision des prévisions

La classification réelle (0 $ ou 1 $) est dans une variable appelée $ Y $. Si vous définissez un seuil, vous pouvez calculer sa précision, par exemple, si la valeur obtenue par régression est égale ou supérieure à 0,5 USD, elle est classée comme 1 USD et si elle est inférieure à 0,5 USD, elle est classée comme 0 USD. ici,

ça ira.

Défi 2

Il existe différents index d'évaluation. Le plus simple ici

«Précision = (TP + TN) / (TP + FP + FN + TN)».

Montrez également la distribution de probabilité pour chaque "TP", "FP", "FN", "TN" comme indiqué dans la figure ci-dessous.

print("Accuracy: ", len(TP + TN) / len(TP + FP + FN + TN))
plt.figure(figsize=(12,4))
plt.hist([TP, FP, FN, TN], label=['TP', 'FP', 'FN', 'TN'], color=['blue', 'green', 'orange', 'red'])
plt.legend()
plt.grid()
plt.show()

output_20_1.png

La variable explicative se rapproche de deux courbes sigmoïdes

Essayons le cas avec deux variables explicatives.

X2 = [1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1.0, 1.3, 1.4, 
      1.0, 1.5, 1.0, 1.4, 1.3, 1.4, 1.5, 1.0, 1.5, 1.1, 
      1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1.0, 
      1.1, 1.0, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 
      1.2, 1.4, 1.2, 1.0, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 
      2.5, 1.9, 2.1, 1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 
      2.0, 1.9, 2.1, 2.0, 2.4, 2.3, 1.8, 2.2, 2.3, 1.5, 
      2.3, 2.0, 2.0, 1.8, 2.1, 1.8, 1.8, 1.8, 2.1, 1.6, 
      1.9, 2.0, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8, 1.8, 2.1, 
      2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2.0, 2.3, 1.8]

X = np.array([X1, X2])

Les variables explicatives définissent une courbe sigmoïde func2 avec deux. Vous optimiserez $ a $, $ b $ et $ c $.

Défi 3

Illustration de la surface de régression

Puisqu'il y a deux variables explicatives, il s'agira d'une régression «surface courbe» au lieu d'une «courbe» de régression. Utilisons matplotlib pour illustrer le tracé 3D.

N = 1000
x1_axis = np.linspace(min(X[0]), max(X[0]), N)
x2_axis = np.linspace(min(X[1]), max(X[1]), N)
x1_grid, x2_grid = np.meshgrid(x1_axis, x2_axis)
x_mesh = np.c_[np.ravel(x1_grid), np.ravel(x2_grid)]

En supposant que les $ a $, $ b $ et $ c $ résultants ont les valeurs suivantes:

y_plot = func2(x_mesh.T, -34.73855674,   4.53539756,   7.68378862).reshape(x1_grid.shape)
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(x1_grid, x2_grid, y_plot, cmap='bwr', linewidth=0)
fig.colorbar(surf)
ax.set_title("Surface Plot")
fig.show()

output_32_0.png

L'important ici est que l'on retourne à la courbe sigmoïde (ou surface courbe), mais lorsqu'on la considère comme un problème de classification, la frontière de classification est une «ligne droite» (ou plan).

Plus proche d'une courbe sigmoïde plus multivariée

Améliorons-le pour qu'il puisse gérer plus de variables explicatives.

X3 = [7.0, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 
      5.0, 5.9, 6.0, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 
      5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7, 6.0, 5.7, 
      5.5, 5.5, 5.8, 6.0, 5.4, 6.0, 6.7, 6.3, 5.6, 5.5, 
      5.5, 6.1, 5.8, 5.0, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 
      6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 
      6.5, 6.4, 6.8, 5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6.0, 
      6.9, 5.6, 7.7, 6.3, 6.7, 7.2, 6.2, 6.1, 6.4, 7.2, 
      7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6.0, 6.9, 
      6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9]

X4 = [3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 
      2.0, 3.0, 2.2, 2.9, 2.9, 3.1, 3.0, 2.7, 2.2, 2.5, 
      3.2, 2.8, 2.5, 2.8, 2.9, 3.0, 2.8, 3.0, 2.9, 2.6, 
      2.4, 2.4, 2.7, 2.7, 3.0, 3.4, 3.1, 2.3, 3.0, 2.5, 
      2.6, 3.0, 2.6, 2.3, 2.7, 3.0, 2.9, 2.9, 2.5, 2.8, 
      3.3, 2.7, 3.0, 2.9, 3.0, 3.0, 2.5, 2.9, 2.5, 3.6, 
      3.2, 2.7, 3.0, 2.5, 2.8, 3.2, 3.0, 3.8, 2.6, 2.2, 
      3.2, 2.8, 2.8, 2.7, 3.3, 3.2, 2.8, 3.0, 2.8, 3.0, 
      2.8, 3.8, 2.8, 2.8, 2.6, 3.0, 3.4, 3.1, 3.0, 3.1, 
      3.1, 3.1, 2.7, 3.2, 3.3, 3.0, 2.5, 3.0, 3.4, 3.0]

X = np.array([X1, X2, X3, X4])

Améliorez la fonction pour accueillir n'importe quel nombre de variables explicatives.

import numpy as np
def func(X, *params):
    f = np.zeros_like(X[0])
    for i, param in enumerate(params):
        if i == 0:
            f = f + param
        else:
            f = f + np.array(param * X[i - 1])
    return 1. / (1. + np.exp(-f))

Exercice 4

Reportez-vous à Optimisation telle que l'interpolation et l'ajustement de courbe

Recommandation de scikit-learn

Le calcul ci-dessus est appelé "régression logistique". La régression logistique est utilisée comme l'une des méthodes de «classification» de l'apprentissage automatique. Cette fois, le but était de comprendre la régression logistique et comment utiliser scipy.optimize.curve_fit, mais en pratique, il est pratique de calculer en utilisant une bibliothèque d'apprentissage automatique appelée scikit-learn.

Perceptron multicouche

Le perceptron multicouche (MLP) est un type de réseau neuronal à propagation directe constitué d'au moins trois couches de nœuds (couche d'entrée «X», couche cachée «H», couche de sortie «O»). Chaque nœud autre que le nœud d'entrée est un neurone qui utilise une fonction d'activation non linéaire, et une technique d'apprentissage supervisé appelée rétropropagation d'erreur peut être utilisée pour identifier des données séparables de manière non linéaire. .. L'une des fonctions utilisées comme fonction d'activation non linéaire est la fonction sigmoïde.

Cette fois, je vais implémenter MLP avec scipy.optimize.curve_fit comme suit.

def mlp(X, *params):
    h01, h02, h03, h04, h0b = params[0], params[1], params[2], params[3], params[4]
    h11, h12, h13, h14, h1b = params[5], params[6], params[7], params[8], params[9]
    h21, h22, h23, h24, h2b = params[10], params[11], params[12], params[13], params[14]

    o01, o02, o03, o0b = params[15], params[16], params[17], params[18]

    h0 = 1. / (1. + np.exp(-(h01 * X[0] + h02 * X[1] + h03 * X[2] + h04 * X[3] + h0b)))
    h1 = 1. / (1. + np.exp(-(h11 * X[0] + h12 * X[1] + h13 * X[2] + h14 * X[3] + h1b)))
    h2 = 1. / (1. + np.exp(-(h21 * X[0] + h22 * X[1] + h23 * X[2] + h24 * X[3] + h2b)))

    o0 = 1. / (1. + np.exp(-(o01 * h0 + o02 * h1 + o03 * h2 + o0b)))

    return o0

Défi 5

scikit-learn et pytorch

MLP a la configuration la plus simple des méthodes d'apprentissage automatique appelée apprentissage en profondeur. Cette fois, le but était de comprendre MLP et comment utiliser scipy.optimize.curve_fit, mais en pratique, il est pratique de calculer en utilisant des bibliothèques telles que scikit-learn et pytorch.

Article de référence: De la régression linéaire multiple à la régression logistique, perceptron multicouche, encodeur automatique, gouverner avec PyTorch

Recommended Posts

Apprenez en implémentant avec Scipy Les bases de la régression logistique et du perceptron multicouche
Implémentation de la régression logistique avec NumPy
Découvrez la puissance de l'accélération avec NumPy / SciPy
J'ai appris les bases de l'apprentissage intensif et joué avec Cart Pole (implémentation simple de Q Learning)
Apprenez les bases de Python ① Débutants élémentaires
[Python] J'ai expliqué en détail la théorie et la mise en œuvre de la régression logistique
Apprenez à nouveau les bases de Theano
Apprenez les bases en touchant les variables python
Visualisez la valeur limite du perceptron multicouche
Revoir le concept et la terminologie de la régression
[Linux] Découvrez les bases des commandes shell
J'ai mesuré la vitesse de la notation d'inclusion de liste, pendant et pendant avec python2.7.
Apprenez les tendances des mots clés dans les textes avec Jubatus et classez vos textes d'entrée
J'ai comparé la moyenne mobile du type de filtre IIR avec les pandas et scipy
Gérez beaucoup avec PyTorch de la régression linéaire multiple à la régression logistique, perceptron multicouche, auto-encodeur
Apprenez Nim avec Python (dès le début de l'année).
Visualisez la gamme d'insertions internes et externes avec python
Calculer le coefficient de régression d'une analyse de régression simple avec python
Régression linéaire multiple, régression logistique, perceptron multicouche, encodeur automatique, Chainer Yo!
Résolution du problème de l'iris avec scikit-learn ver1.0 (régression logistique)
Animer les bases de la planification dynamique et des problèmes de sac à dos
Principes de base et mise en œuvre de Perceptron
La fondation de la fondation Perceptron
Bases de l'analyse de régression
L'histoire de la mise en œuvre du sujet Facebook Messenger Bot avec python
Jouez avec le mécanisme de mot de passe de GitHub Webhook et Python