"Que pensez-vous de ce type?"
"Très ... magnifique ..."
Un sentiment de sortie.
J'ai eu l'occasion de gratter le Perceptron multicouche, c'est donc un article de synthèse.
Cette fois, je l'ai écrit pour que vous puissiez apprendre avec une interface comme scicit-learn tout en le rendant agréable et général.
Presque tous les paramètres tels que le nombre de couches cachées, le nombre de nœuds, le nombre d'apprentissage, le taux d'apprentissage, etc. peuvent être ajustés en passant des arguments. Il existe des preuves d'un défi dans la normalisation des lots, mais elle n'a pas été normalisée avec succès à l'aide de la distribution.
Cet article en contient un non général mais concis, veuillez donc vous y référer également.
Après tout, si vous faites en sorte que vous puissiez utiliser n'importe quoi dans une certaine mesure, ce sera compliqué. Je veux le rendre plus beau. Ce qui suit est celui qui a entraîné le Perceptron multicouche à apprendre la somme logique exclusive (souvent vue).
mlp.py
import numpy as np
class MultilayerPerceptron:
def __init__(self, featureNum, rho, classNum, hidden, normalization=True):
self.featureNum = featureNum
self.rho = rho
self.classNum = classNum
self.hidden = hidden
self.normalization = normalization
rc = [self.featureNum]+self.hidden+[self.classNum]
self.W = [np.random.randn(rc[i]+1, rc[i+1]) for i in range(len(hidden)+1)]
self.h = [[] for _ in range(len(self.hidden)+1)]
self.g = [[] for _ in range(len(self.hidden)+1)]
def fit(self, X, y, learn_times=1000, batch_size="full"):
self.X = np.array(X)
one = np.ones((len(self.X), 1))
self.learn_times = learn_times
self.X_train_mean = np.sum(self.X, axis=0)/len(self.X)
self.X_train_sigma = np.var(self.X, axis=0)**0.5
if (self.normalization):
self.X = (self.X - self.X_train_mean)/self.X_train_sigma
self.X = np.hstack((self.X, one))
self.y = np.tile(y, (1, 1))
self.eps = [[] for _ in range(len(self.hidden)+1)]
self.sigmoid = np.vectorize(lambda x: 1.0 / (1.0 + np.exp(-x)))
self.batch_size = len(self.X) if (batch_size == "full") else int(batch_size)
for _ in range(self.learn_times):
self.shuffled_index = np.random.permutation(len(self.X))
self.X_shuffled = self.X[self.shuffled_index]
self.y_shuffled = self.y[self.shuffled_index]
self.X_batch_list = np.array_split(self.X_shuffled, len(self.X)//self.batch_size, 0)
self.y_batch_list = np.array_split(self.y_shuffled, len(self.y)//self.batch_size, 0)
for p in range(len(self.X_batch_list)):
self.X_batchp = self.X_batch_list[p]
self.y_batchp = self.y_batch_list[p]
self.X_batch_mean = np.sum(self.X_batchp, axis=0) / self.batch_size
one_batchp = np.ones((len(self.X_batchp), 1))
#La fonction d'activation de la couche d'entrée n'est pas calculée,Calculer la sortie autre que la couche d'entrée
self.h[0] = self.X_batchp @ self.W[0]
self.g[0] = np.hstack((self.sigmoid(self.h[0]), one_batchp))
for j in range(1,len(self.hidden)):
#Étant donné que les poids sont déjà générés dans la forme appropriée lorsque les poids sont générés,Effectuez simplement l'opération de matrice dans le sens de propagation vers l'avant
self.h[j] = self.g[j-1] @ self.W[j]
#Lorsque la sortie est différente de la dernière couche, collez 1 sur le côté pour correspondre au vecteur de poids étendu
self.g[j] = np.hstack((self.sigmoid(self.h[j]), one_batchp))
self.h[-1] = self.g[-2] @ self.W[-1]
self.g[-1] = self.sigmoid(self.h[-1])
#La sortie de la couche d'entrée est,Même valeur que lorsque la fonction d'activation est considérée comme une fonction égale,Par conséquent, il suffit de créer une branche pour que la valeur de la couche d'entrée ne soit utilisée que lors du calcul de l'erreur avec la couche d'entrée.
self.eps[-1] = np.array((self.g[-1] - self.y_batchp) * self.g[-1]*(1-self.g[-1]))
for j in range(1, len(self.eps)):
#Pour le produit matriciel des poids et des erreurs,Prenez le produit élément
#Parce que la dernière colonne du vecteur de poids est le biais,De la couche avant,Vous ne pouvez pas voir le biais de la couche précédente
#Alors supprimez la dernière colonne
self.eps[-(j+1)] = self.eps[-j] @ self.W[-j].T * self.g[-(j+1)]*(1-self.g[-(j+1)])
self.eps[-(j+1)] = np.delete(self.eps[-(j+1)], -1, axis=1)
self.W[0] -= self.rho * self.X_batchp.T @ self.eps[0] / len(self.X_batchp)
for j in range(1, len(self.hidden)+1):
self.W[j] -= self.rho * self.g[j-1].T @ self.eps[j] / len(self.X_batchp)
def pred(self, X_test):
self.X_test = np.array(X_test)
one = np.ones((len(self.X_test), 1))
if (self.normalization):
self.X_test = (self.X_test - self.X_train_mean)/self.X_train_sigma
self.X_test = np.hstack((self.X_test, one))
self.h[0] = self.X_test @ self.W[0]
self.g[0] = np.hstack((self.sigmoid(self.h[0]), one))
for j in range(1, len(self.hidden)):
self.h[j] = self.g[j-1] @ self.W[j]
self.g[j] = np.hstack((self.sigmoid(self.h[j]), one))
self.h[-1] = self.g[-2] @ self.W[-1]
self.g[-1] = self.sigmoid(self.h[-1])
return np.argmax(self.g[-1], axis=1)
def score(self, X_test, y_test):
self.X_test = np.array(X_test)
self.y_test = np.array(y_test)
self.loss_vector = (np.argmax(np.array(self.y_test),axis=1) == self.pred(self.X_test))
return np.count_nonzero(self.loss_vector)/len(self.X_test)
#Un biais (le poids initial est 1) est ajouté aux neurones dans la couche cachée.
mlp = MultilayerPerceptron(featureNum=2, rho=1, classNum=2, hidden=[4, 3])
x = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [[1, 0], [0, 1], [0, 1], [1, 0]]
mlp.fit(x, y, 1000, 2)
print(mlp.pred(x))
print(mlp.score(x, y))
Cliquez ici pour la version sans commentaires
mlp.py
import numpy as np
class MultilayerPerceptron:
def __init__(self, featureNum, rho, classNum, hidden, normalization=True):
self.featureNum = featureNum
self.rho = rho
self.classNum = classNum
self.hidden = hidden
self.normalization = normalization
rc = [self.featureNum]+self.hidden+[self.classNum]
self.W = [np.random.randn(rc[i]+1, rc[i+1]) for i in range(len(hidden)+1)]
self.h = [[] for _ in range(len(self.hidden)+1)]
self.g = [[] for _ in range(len(self.hidden)+1)]
def fit(self, X, y, learn_times=1000, batch_size="full"):
self.X = np.array(X)
one = np.ones((len(self.X), 1))
self.learn_times = learn_times
self.X_train_mean = np.sum(self.X, axis=0)/len(self.X)
self.X_train_sigma = np.var(self.X, axis=0)**0.5
if (self.normalization):
self.X = (self.X - self.X_train_mean)/self.X_train_sigma
self.X = np.hstack((self.X, one))
self.y = np.tile(y, (1, 1))
self.eps = [[] for _ in range(len(self.hidden)+1)]
self.sigmoid = np.vectorize(lambda x: 1.0 / (1.0 + np.exp(-x)))
self.batch_size = len(self.X) if (batch_size == "full") else int(batch_size)
for _ in range(self.learn_times):
self.shuffled_index = np.random.permutation(len(self.X))
self.X_shuffled = self.X[self.shuffled_index]
self.y_shuffled = self.y[self.shuffled_index]
self.X_batch_list = np.array_split(self.X_shuffled, len(self.X)//self.batch_size, 0)
self.y_batch_list = np.array_split(self.y_shuffled, len(self.y)//self.batch_size, 0)
for p in range(len(self.X_batch_list)):
self.X_batchp = self.X_batch_list[p]
self.y_batchp = self.y_batch_list[p]
self.X_batch_mean = np.sum(self.X_batchp, axis=0) / self.batch_size
one_batchp = np.ones((len(self.X_batchp), 1))
self.h[0] = self.X_batchp @ self.W[0]
self.g[0] = np.hstack((self.sigmoid(self.h[0]), one_batchp))
for j in range(1,len(self.hidden)):
self.h[j] = self.g[j-1] @ self.W[j]
self.g[j] = np.hstack((self.sigmoid(self.h[j]), one_batchp))
self.h[-1] = self.g[-2] @ self.W[-1]
self.g[-1] = self.sigmoid(self.h[-1])
self.eps[-1] = np.array((self.g[-1] - self.y_batchp) * self.g[-1]*(1-self.g[-1]))
for j in range(1, len(self.eps)):
self.eps[-(j+1)] = self.eps[-j] @ self.W[-j].T * self.g[-(j+1)]*(1-self.g[-(j+1)])
self.eps[-(j+1)] = np.delete(self.eps[-(j+1)], -1, axis=1)
self.W[0] -= self.rho * self.X_batchp.T @ self.eps[0] / len(self.X_batchp)
for j in range(1, len(self.hidden)+1):
self.W[j] -= self.rho * self.g[j-1].T @ self.eps[j] / len(self.X_batchp)
def pred(self, X_test):
self.X_test = np.array(X_test)
one = np.ones((len(self.X_test), 1))
if (self.normalization):
self.X_test = (self.X_test - self.X_train_mean)/self.X_train_sigma
self.X_test = np.hstack((self.X_test, one))
self.h[0] = self.X_test @ self.W[0]
self.g[0] = np.hstack((self.sigmoid(self.h[0]), one))
for j in range(1, len(self.hidden)):
self.h[j] = self.g[j-1] @ self.W[j]
self.g[j] = np.hstack((self.sigmoid(self.h[j]), one))
self.h[-1] = self.g[-2] @ self.W[-1]
self.g[-1] = self.sigmoid(self.h[-1])
return np.argmax(self.g[-1], axis=1)
def score(self, X_test, y_test):
self.X_test = np.array(X_test)
self.y_test = np.array(y_test)
self.loss_vector = (np.argmax(np.array(self.y_test),axis=1) == self.pred(self.X_test))
return np.count_nonzero(self.loss_vector)/len(self.X_test)
mlp = MultilayerPerceptron(featureNum=2, rho=1, classNum=2, hidden=[4, 3])
x = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [[1, 0], [0, 1], [0, 1], [1, 0]]
mlp.fit(x, y, 1000, 2)
print(mlp.pred(x))
print(mlp.score(x, y))
Colle et élan maléfiques, et échapper à la réalité avant le test.
Recommended Posts