[PYTHON] Gérez beaucoup avec PyTorch de la régression linéaire multiple à la régression logistique, perceptron multicouche, auto-encodeur

Utilisez PyTorch pour apprendre les idées de base de l'apprentissage profond.

Éléments de base de PyTorch

Supposons que vous ayez des données représentées par le type de tableau de numpy comme suit:

import numpy as np
x1 = np.array([0.12, 0.21])
x2 = np.array([0.34, 0.43])
x3 = np.array([0.56, 0.65])

Vous pouvez créer une jointure linéaire comme suit.

z = 0.5 * x1 + 0.3 * x2 + 0.2 * x3
z
array([0.274, 0.364])

Pytorch utilise le tableau de numpy converti en type tenseur.

import torch
x1 = torch.from_numpy(x1).float()
x2 = torch.from_numpy(x2).float()
x3 = torch.from_numpy(x3).float()

Vous pouvez créer des jointures linéaires de la même manière.

z = 0.5 * x1 + 0.3 * x2 + 0.2 * x3
z
tensor([0.2740, 0.3640])

Cela peut sembler ennuyeux, mais en convertissant davantage le type tenseur en type Variable, il devient possible de différencier automatiquement (calculer le gradient).

from torch.autograd import Variable
x1 = Variable(x1)
x2 = Variable(x2)
x3 = Variable(x3)

Vous pouvez créer des jointures linéaires de la même manière.

z = 0.5 * x1 + 0.3 * x2 + 0.2 * x3
z
tensor([0.2740, 0.3640])

Pytoach fournit une fonction de jointure linéaire. Avant cela, exprimons la jointure linéaire avec numpy.

import numpy as np
W = np.array([[ 5,  1, -2 ],
       [ 3,  -5, -1 ]], dtype=np.float32) #Matrice de poids

b = np.array([2, -3], dtype=np.float32) #Terme de biais

Vous pouvez créer une jointure linéaire comme suit.

x = np.array([0, 1, 2]) #1 enregistrement de données composé de 3 variables
y = x.dot(W.T) + b
y
array([ -1., -10.])

Si les données constituées de 3 variables correspondent à 5 enregistrements, ce sera comme suit.

x = np.array(range(15)).astype(np.float32).reshape(5, 3)
x
array([[ 0.,  1.,  2.],
       [ 3.,  4.,  5.],
       [ 6.,  7.,  8.],
       [ 9., 10., 11.],
       [12., 13., 14.]], dtype=float32)
y = x.dot(W.T) + b
y
array([[ -1., -10.],
       [ 11., -19.],
       [ 23., -28.],
       [ 35., -37.],
       [ 47., -46.]], dtype=float32)

Ce qui précède est la jointure linéaire utilisant numpy. Dans Pytorch, la fonction qui représente une jointure linéaire est définie comme suit:

h = torch.nn.Linear(3,2) #Fonction d'action linéaire y qui entre un vecteur tridimensionnel et produit un vecteur bidimensionnel= Wx + b

Par défaut, la matrice de poids W et le terme de biais b contiennent des nombres aléatoires. Le but du deep learning est d'optimiser ces coefficients.

h.weight #L'aléatoire est entré par défaut
Parameter containing:
tensor([[-0.2569, -0.5403,  0.4155],
        [-0.5554,  0.5284,  0.3978]], requires_grad=True)
h.bias #L'aléatoire est entré par défaut
Parameter containing:
tensor([-0.5164, -0.2875], requires_grad=True)

À propos, pour convertir des données de type tensoriel en type tableau numpy, procédez comme suit.

h.weight.detach().numpy()
array([[-0.256898  , -0.54026437,  0.41552007],
       [-0.55537015,  0.5283861 ,  0.39781755]], dtype=float32)
h.bias.detach().numpy()
array([-0.5163672 , -0.28754294], dtype=float32)

Faisons maintenant une transformation linéaire en utilisant Pytorch.

x = Variable(torch.from_numpy(x).float()) #Conversion du type de tableau → type de tenseur → type de variable
y = h(x) #Transformation linéaire
y.data.detach().numpy() #Vérifiez la valeur obtenue avec le type de tableau
array([[-0.22559142,  1.0364783 ],
       [-1.3705183 ,  2.1489787 ],
       [-2.515445  ,  3.2614794 ],
       [-3.660372  ,  4.37398   ],
       [-4.805299  ,  5.48648   ]], dtype=float32)
x = x.detach().numpy()
x.dot(h.weight.detach().numpy().T) + h.bias.detach().numpy() #vérification des comptes
array([[-0.22559142,  1.0364783 ],
       [-1.3705183 ,  2.1489787 ],
       [-2.515445  ,  3.2614794 ],
       [-3.660372  ,  4.37398   ],
       [-4.805299  ,  5.48648   ]], dtype=float32)

Données Ayame

Maintenant, en tant que pratique de Pytorch, faisons une régression multiple linéaire. En tant que données à traiter, les données Iris, souvent utilisées dans le domaine de l'apprentissage automatique, sont traitées.

import numpy as np
from sklearn import datasets
iris = datasets.load_iris() #Lecture des données d'iris
data = iris.data.astype(np.float32)
X = data[:, :3] #Les trois premières données de mesure de l'iris sont utilisées comme variables explicatives.
Y = data[:, 3].reshape(len(data), 1) #Soit la dernière variable objective.
#Soit les données impaires les données de l'enseignant et les données paires les données de test.
index = np.arange(Y.size)
X_train = X[index[index % 2 != 0], :] #Variable explicative (données enseignants)
X_test = X[index[index % 2 == 0], :] #Variable explicative (données de test)
Y_train = Y[index[index % 2 != 0], :] #Variable objective (données enseignants)
Y_test = Y[index[index % 2 == 0], :] #Variable objective (données de test)

Les données sont représentées par le type de tenseur.

import torch
X_train = torch.from_numpy(X_train).float()
X_test = torch.from_numpy(X_test).float()
Y_train = torch.from_numpy(Y_train).float()
Y_test = torch.from_numpy(Y_test).float()
X_train.shape
torch.Size([75, 3])

Combinez les variables explicatives et objectives dans des données de type TensorDataset.

from torch.utils.data import TensorDataset
train = TensorDataset(X_train, Y_train)
train[0]
(tensor([4.9000, 3.0000, 1.4000]), tensor([0.2000]))

Dans l'apprentissage profond, les données des enseignants sont divisées en petits «lots» et apprises.

from torch.utils.data import DataLoader
train_loader = DataLoader(train, batch_size=10, shuffle=True)

Régression linéaire multiple (MLR)

Définit une classe qui effectue une régression multiple linéaire.

class MLR(torch.nn.Module):
    def __init__(self, n_input, n_output):
        super(MLR, self).__init__()
        self.l1 = torch.nn.Linear(n_input, n_output)

    def forward(self, x):
        return self.l1(x)

Créez un objet de cette classe.

model = MLR(3, 1) #Modèle de régression multiple linéaire avec 3 entrées de variables et 1 sortie de variable

Le but est de minimiser l'erreur (appelée «perte» en apprentissage profond), mais de définir cette erreur.

criterion = torch.nn.MSELoss() # mean square error

Sélectionnez un algorithme qui minimise l'erreur.

optimizer = torch.optim.SGD(model.parameters(), lr=0.01) #Méthode de descente de gradient probabiliste

"Prédire" avec un calcul avant, calculer l'erreur, puis répéter l'opération de propagation de l'erreur dans le sens inverse.

from torch.autograd import Variable
loss_history = []
for epoch in range(100):
    total_loss = 0
    for x_train, y_train in train_loader:
        x_train = Variable(x_train)
        y_train = Variable(y_train)
        optimizer.zero_grad()
        y_pred = model(x_train)
        loss = criterion(y_pred, y_train)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    loss_history.append(total_loss)
    if (epoch +1) % 10 == 0:
        print(epoch + 1, total_loss)
10 0.5098993554711342
20 0.49431246891617775
30 0.37891835160553455
40 0.38362359534949064
50 0.602457270026207
60 0.4444280909374356
70 0.41419393196702003
80 0.4345690496265888
90 0.38460623472929
100 0.3826814219355583

Avez-vous vu l'erreur (perte) diminuer? Illustrons l'histoire.

%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(loss_history)
[<matplotlib.lines.Line2D at 0x7fc33444d128>]

output_54_1.png

Regardons maintenant le graphique y-y comparant les valeurs prédites et mesurées. Plus elle est proche de la diagonale, meilleure est la prédiction.

%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(6,6))
plt.scatter(Y_train.flatten(), model.forward(X_train).data.flatten(), alpha=0.5)
plt.plot([min(Y), max(Y)], [min(Y), max(Y)])
plt.grid()
plt.legend()
plt.xlabel('Observed')
plt.ylabel('Predicted')
plt.show()

output_56_1.png

Régression logistique (LR)

Ensuite, effectuons une régression logistique, qui est une méthode de retour à la fonction sigmoïde (fonction logistique) et qui est également utilisée comme méthode de classification.

Données Ayame

Cette fois, utilisons les quatre données de mesure d'Ayame comme variable explicative et les variétés d'Ayame (3 types) comme variable objective.

import numpy as np
from sklearn import datasets
iris = datasets.load_iris() #Lecture des données d'iris
X = iris.data.astype(np.float32) #4 variables comme variables explicatives
Y = iris.target #Variétés d'Ayame (3 types) comme variables objectives
#Une variété d'iris-Convertir en vecteur chaud.
Y_ohv = np.zeros(3 * Y.size).reshape(Y.size, 3).astype(np.float32)
for i in range(Y.size):
    Y_ohv[i, Y[i]] = 1.0 # one-hot vector
#Soit les données impaires les données de l'enseignant et les données paires les données de test.
index = np.arange(Y.size)
X_train = X[index[index % 2 != 0], :] #Variable explicative (données enseignants)
X_test = X[index[index % 2 == 0], :] #Variable explicative (données de test)
Y_train = Y_ohv[index[index % 2 != 0], :] #Objectif, variable 1-vecteur chaud (données de l'enseignant)
Y_test = Y_ohv[index[index % 2 == 0], :] #Objectif, variable 1-vecteur chaud (données de test)
Y_ans_train = Y[index[index % 2 != 0]] #Variable objective (données enseignants)
Y_ans_test = Y[index[index % 2 == 0]] #Variable objective (données de test)
import torch
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader

X_train = torch.from_numpy(X_train).float()
X_test = torch.from_numpy(X_test).float()
Y_train = torch.from_numpy(Y_train).float()
Y_test = torch.from_numpy(Y_test).float()

train = TensorDataset(X_train, Y_train)

train_loader = DataLoader(train, batch_size=10, shuffle=True)
train[0]
(tensor([4.9000, 3.0000, 1.4000, 0.2000]), tensor([1., 0., 0.]))
#import torch.nn.functional as F
class LR(torch.nn.Module):
    def __init__(self, n_input, n_output):
        super(LR, self).__init__()
        self.l1 = torch.nn.Linear(n_input, n_output)

    def forward(self, x):
        h1 = self.l1(x)
        h2 = torch.sigmoid(h1)
        return h2
model = LR(4, 3)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

from torch.autograd import Variable
loss_history = []
for epoch in range(1000):
    total_loss = 0
    for x_train, y_train in train_loader:
        x_train = Variable(x_train)
        y_train = Variable(y_train)
        optimizer.zero_grad()
        y_pred = model(x_train)
        loss = criterion(y_pred, y_train)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    loss_history.append(total_loss)
    if (epoch +1) % 100 == 0:
        print(epoch + 1, total_loss)
100 1.63955856859684
200 1.2039469927549362
300 0.9843573123216629
400 0.9481473788619041
500 0.847799651324749
600 0.857478104531765
700 0.8010830879211426
800 0.8148728087544441
900 0.8013908714056015
1000 0.7699911445379257
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(loss_history)
[<matplotlib.lines.Line2D at 0x7fc3317298d0>]

output_65_1.png

Trouvons le taux de réponse correct lorsque le produit avec la valeur de sortie maximale est le "produit prédit".

Y_pred = model.forward(X_train)
nrow, ncol = Y_pred.data.shape

count = 0
for i in range(nrow):
    cls = np.argmax(Y_pred.data[i, :])
    if cls == Y_ans_train[i]:
        count += 1

print(count, " / ", nrow, " = ", count / nrow)
65  /  75  =  0.8666666666666667

Perceptron multicouche (MLP)

Jusqu'à présent, j'ai créé des modèles de régression multiple linéaire et de régression logistique à l'aide de Pytorch. De la même manière, si vous épaississez la couche, cela devient un «apprentissage profond». Le modèle le plus simple d'apprentissage en profondeur est le perceptron multicouche.

Retour par MLP

import numpy as np
from sklearn import datasets
iris = datasets.load_iris() #Lecture des données d'iris
data = iris.data.astype(np.float32)
X = data[:, :3] #Les trois premières données de mesure de l'iris sont utilisées comme variables explicatives.
Y = data[:, 3].reshape(len(data), 1) #Soit la dernière variable objective.

#Soit les données impaires les données de l'enseignant et les données paires les données de test.
index = np.arange(Y.size)
X_train = X[index[index % 2 != 0], :] #Variable explicative (données enseignants)
X_test = X[index[index % 2 == 0], :] #Variable explicative (données de test)
Y_train = Y[index[index % 2 != 0], :] #Variable objective (données enseignants)
Y_test = Y[index[index % 2 == 0], :] #Variable objective (données de test)

import torch
X_train = torch.from_numpy(X_train).float()
X_test = torch.from_numpy(X_test).float()
Y_train = torch.from_numpy(Y_train).float()
Y_test = torch.from_numpy(Y_test).float()

from torch.utils.data import TensorDataset
train = TensorDataset(X_train, Y_train)

from torch.utils.data import DataLoader
train_loader = DataLoader(train, batch_size=10, shuffle=True)
#import torch.nn.functional as F
class MLPR(torch.nn.Module):
    def __init__(self, n_input, n_hidden, n_output):
        super(MLPR, self).__init__()
        self.l1 = torch.nn.Linear(n_input, n_hidden)
        self.l2 = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        h1 = self.l1(x)
        h2 = torch.sigmoid(h1)
        h3 = self.l2(h2)
        return h3
model = MLPR(3, 3, 1)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

from torch.autograd import Variable
loss_history = []
for epoch in range(1000):
    total_loss = 0
    for x_train, y_train in train_loader:
        x_train = Variable(x_train)
        y_train = Variable(y_train)
        optimizer.zero_grad()
        y_pred = model(x_train)
        loss = criterion(y_pred, y_train)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    loss_history.append(total_loss)
    if (epoch +1) % 100 == 0:
        print(epoch + 1, total_loss)
100 0.40582243632525206
200 0.3966686334460974
300 0.4202105160802603
400 0.3585368797648698
500 0.3776881340891123
600 0.3534861374646425
700 0.40271759033203125
800 0.37439848855137825
900 0.40052078012377024
1000 0.35703002475202084
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(loss_history)
[<matplotlib.lines.Line2D at 0x7fc3316929e8>]

output_72_1.png

%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(6,6))
plt.scatter(Y_train.flatten(), model.forward(X_train).data.flatten(), alpha=0.5)
plt.plot([min(Y), max(Y)], [min(Y), max(Y)])
plt.grid()
plt.legend()
plt.xlabel('Observed')
plt.ylabel('Predicted')
plt.show()
No handles with labels found to put in legend.

output_73_1.png

Classification par MLP

import numpy as np
from sklearn import datasets
iris = datasets.load_iris() #Lecture des données d'iris
X = iris.data.astype(np.float32) #4 variables comme variables explicatives
Y = iris.target #Variétés d'Ayame (3 types) comme variables objectives
#Une variété d'iris-Convertir en vecteur chaud.
Y_ohv = np.zeros(3 * Y.size).reshape(Y.size, 3).astype(np.float32)
for i in range(Y.size):
    Y_ohv[i, Y[i]] = 1.0 # one-hot vector
#Soit les données impaires les données de l'enseignant et les données paires les données de test.
index = np.arange(Y.size)
X_train = X[index[index % 2 != 0], :] #Variable explicative (données enseignants)
X_test = X[index[index % 2 == 0], :] #Variable explicative (données de test)
Y_train = Y_ohv[index[index % 2 != 0], :] #Objectif, variable 1-vecteur chaud (données de l'enseignant)
Y_test = Y_ohv[index[index % 2 == 0], :] #Objectif, variable 1-vecteur chaud (données de test)
Y_ans_train = Y[index[index % 2 != 0]] #Variable objective (données enseignants)
Y_ans_test = Y[index[index % 2 == 0]] #Variable objective (données de test)
import torch
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader

X_train = torch.from_numpy(X_train).float()
X_test = torch.from_numpy(X_test).float()
Y_train = torch.from_numpy(Y_train).float()
Y_test = torch.from_numpy(Y_test).float()

train = TensorDataset(X_train, Y_train)

train_loader = DataLoader(train, batch_size=10, shuffle=True)
class MLPC(torch.nn.Module):
    def __init__(self, n_input, n_hidden, n_output):
        super(MLPC, self).__init__()
        self.l1 = torch.nn.Linear(n_input, n_hidden)
        self.l2 = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        h1 = self.l1(x)
        h2 = torch.sigmoid(h1)
        h3 = self.l2(h2)
        h4 = torch.sigmoid(h3)
        return h4
model = MLPC(4, 3, 3)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

from torch.autograd import Variable
loss_history = []
for epoch in range(5000):
    total_loss = 0
    for x_train, y_train in train_loader:
        x_train = Variable(x_train)
        y_train = Variable(y_train)
        optimizer.zero_grad()
        y_pred = model(x_train)
        loss = criterion(y_pred, y_train)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    loss_history.append(total_loss)
    if (epoch +1) % 500 == 0:
        print(epoch + 1, total_loss)
500 1.645580604672432
1000 1.3838596642017365
1500 1.1801470965147018
2000 1.0481771975755692
2500 1.004256546497345
3000 0.9521581381559372
3500 0.9244466200470924
4000 0.8533390164375305
4500 0.845703762024641
5000 0.7936465740203857
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(loss_history)
[<matplotlib.lines.Line2D at 0x7fc331581c18>]

output_81_1.png

Y_pred = model.forward(X_train)
nrow, ncol = Y_pred.data.shape

count = 0
for i in range(nrow):
    cls = np.argmax(Y_pred.data[i, :])
    if cls == Y_ans_train[i]:
        count += 1

print(count, " / ", nrow, " = ", count / nrow)
67  /  75  =  0.8933333333333333

Encodeur automatique (AE)

Un auto-encodeur est un réseau neuronal qui revient à lui-même. Le convertisseur de couche d'entrée vers couche intermédiaire est appelé le codeur codeur, et le convertisseur de couche intermédiaire vers couche de sortie est appelé décodeur décodeur. La "réduction de dimension" (réduction de dimension) peut être effectuée en réduisant le nombre de neurones dans la couche intermédiaire à moins que les données d'entrée.

import numpy as np
from sklearn import datasets
iris = datasets.load_iris() #Lecture des données d'iris
data = iris.data.astype(np.float32)
X = data 

index = np.arange(Y.size)
X_train = X[index[index % 2 != 0], :] #Variable explicative (données enseignants)
X_test = X[index[index % 2 == 0], :] #Variable explicative (données de test)

import torch
X_train = torch.from_numpy(X_train).float()
X_test = torch.from_numpy(X_test).float()

from torch.utils.data import TensorDataset
train = TensorDataset(X_train, X_train)

from torch.utils.data import DataLoader
train_loader = DataLoader(train, batch_size=10, shuffle=True)
class MLPR(torch.nn.Module):
    def __init__(self, n_input, n_hidden, n_output):
        super(MLPR, self).__init__()
        self.l1 = torch.nn.Linear(n_input, n_hidden)
        self.l2 = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        h1 = self.l1(x)
        h2 = torch.sigmoid(h1)
        h3 = self.l2(h2)
        return h3

    def project(self, x):
        h1 = self.l1(x)
        h2 = torch.sigmoid(h1)
        return h2
model = MLPR(4, 2, 4)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

from torch.autograd import Variable
loss_history = []
for epoch in range(500):
    total_loss = 0
    for x_train, y_train in train_loader:
        x_train = Variable(x_train)
        y_train = Variable(y_train)
        optimizer.zero_grad()
        y_pred = model(x_train)
        loss = criterion(y_pred, y_train)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    loss_history.append(total_loss)
    if (epoch +1) % 50 == 0:
        print(epoch + 1, total_loss)
50 7.260494828224182
100 3.8141910433769226
150 2.6670321971178055
200 1.9922174364328384
250 1.538402482867241
300 1.2299609556794167
350 1.1305854469537735
400 1.0665423274040222
450 1.0088475532829762
500 0.9823619686067104
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(loss_history)
[<matplotlib.lines.Line2D at 0x7fc33154e2e8>]

output_87_1.png

Afficher les données projetées sur la couche intermédiaire

latent = model.project(X_train)
%matplotlib inline
import matplotlib.pyplot as plt
plt.scatter(latent.data[0:50, 0], latent.data[0:50, 1], alpha=0.5)
plt.scatter(latent.data[50:100, 0], latent.data[50:100, 1], alpha=0.5)
plt.scatter(latent.data[100:150, 0], latent.data[100:150, 1], alpha=0.5)
plt.grid()

output_90_0.png

Tâche

Recommended Posts

Gérez beaucoup avec PyTorch de la régression linéaire multiple à la régression logistique, perceptron multicouche, auto-encodeur
Régression linéaire multiple, régression logistique, perceptron multicouche, encodeur automatique, Chainer Yo!
[Apprentissage automatique] Comprendre la régression multiple linéaire à partir de scikit-learn et des mathématiques
Premier TensorFlow (édition révisée) - Régression linéaire et logistique
Apprenez en implémentant avec Scipy Les bases de la régression logistique et du perceptron multicouche
Introduction à OPTIMIZER ~ De la régression linéaire à Adam à Eve
"Régression linéaire" et "Version probabiliste de la régression linéaire" en Python "Régression linéaire de Bayes"