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()
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)
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()
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 $».
Utilisez matplotlib pour illustrer la courbe de régression comme indiqué ci-dessus.
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.
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()
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 $.
func2
et utilisez scipy.optimize.curve_fit
pour obtenir la solution optimale pour les coefficients $ a $, $ b $ et $ c $.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()
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).
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))
Reportez-vous à Optimisation telle que l'interpolation et l'ajustement de courbe
func
pour faire une prédiction en utilisant uniquement la première variable, $ X_1 $, et calculer le pourcentage de réponses correctes.func
pour faire une prédiction en utilisant uniquement les deux premières variables $ X_1 $ et $ X_2 $, et calculez le taux de réponse correct.func
pour faire une prédiction en utilisant uniquement les trois premières variables $ X_1 $, $ X_2 $ et $ X_3 $, et calculez le taux de réponse correct.func
pour faire une prédiction en utilisant les quatre variables $ X_1 $, $ X_2 $, $ X_3 $, $ X_4 $, et calculer le taux de réponse correct.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
.
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
mlp
ci-dessus.mlp
pour faire une prédiction en utilisant les quatre variables $ X_1 $, $ X_2 $, $ X_3 $, $ X_4 $, et calculer le taux de réponse correct.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