J'ai suivi l'apprentissage automatique de Coursera il y a environ un an, mais je pense que j'ai pu apprendre les bases de l'apprentissage automatique. "Cross-entropy" est une fonction d'erreur utilisée dans le problème de classification, mais encore une fois, dans le but de comprendre le concept, nous avons effectué la tâche de la semaine 2 de Coursera ML, régression logistique. En fait, Matlab (ou Octave) a été utilisé dans le cours, mais ici nous utilisons Python.
(Environnement de programmation: Python 2.7.11, numpy 1.11.0, scipy 0.17.0, tensorflow 0.9.0rc.)
Examinons d'abord le modèle de régression logistique dans le problème de classification.
** Fig. Modèle de régression logistique **
Il s'agit d'un modèle dans lequel les valeurs d'entrée x1, x2, ... xn sont pondérées et additionnées, et la valeur estimée est obtenue via la fonction sigmoïde, qui est la fonction d'activation. Dans la figure ci-dessus, les poids w1, w2, ... wn et la valeur de biais b sont utilisés, mais dans l'explication de Coursera, w et b sont collectivement utilisés comme paramètre thêta.
L'entropie croisée est une valeur numérique indiquant "dans quelle mesure la valeur estimée du modèle ci-dessus diffère de la valeur réelle". Il est exprimé par l'équation suivante. (L'anglais est parfois abrégé en entropie croisée, xentropie, xent.)
J(\theta) = \frac{1}{m}\sum_{i-1}^{m} [-y^{(i)}\ log(h_{\theta} (x^{(i)})) - (1-y^{(i)})\ log(1-h_{\theta}(x^{(i)}))]
\\
(h_{\theta}(x) = g(\theta^{T}x),\ g(z) = \frac{1}{1+e^{-z}})
Ici, h_theta (x) est une valeur estimée. Puisqu'il s'agit d'une valeur estimée dans le problème de classification binaire, la probabilité que la classification y = 1 soit [0,0 ... 1,0]. De plus, y ^ (i) est la classe réelle (0 ou 1) donnée comme données d'apprentissage. Le flux de régression logistique consiste à obtenir un modèle très précis en trouvant la valeur du paramètre thêta qui minimise cette fonction d'erreur (fonction de coût dans Coursera) J (thêta). La dérivée de la fonction d'erreur (gradient) est requise dans le processus d'optimisation de la minimisation de fonction, qui est le suivant.
\frac{\partial J(\theta)}{\partial \theta_j} = \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})x_j^{(i)}
Sur la base de ces expressions, nous allons créer du code Python.
Commencez par créer un code pour trouver la fonction de coût, en suivant comment procéder avec les tâches du cours.
import numpy as np
def sigmoid(x):
s = 1. / (1. + np.exp(-x))
return s
def compute_cost(theta, xm, ym, lamb):
'''
function:
compute the cost of a particular choice of theta
args:
theta : parameter related to weight, bias
xm, ym : data of features, labels
'''
m, n = xm.shape
xent = 0.0
logits = np.dot(xm, theta)
for i in range(m):
# J calculation, J is scalar
sigmd_x = sigmoid(logits[i])
xent += 1. / m *(-ym[i] * np.log(sigmd_x) - (1. - ym[i])
* np.log(1.0 - sigmd_x))
xent = np.asscalar(xent)
# add regularization term to cost
theta_sq = sum([item **2 for item in theta[1:]])
cost = xent + lamb /2. /m * theta_sq
return cost
Tout d'abord, définissez la fonction sigmoïde. Ensuite, compute_cost () calcule le coût basé sur l'équation d'entropie croisée ci-dessus. Le code ci-dessus ajoute la variable xent dans la boucle for pour chaque échantillon de données, mais pour plus d'efficacité, il est préférable de ne pas utiliser la boucle for, mais je pense que c'est bien pour le premier code. Après avoir calculé le xent d'entropie croisée, le terme de norme L2 (atténuation de poids) pour éviter le surajustement est ajouté pour obtenir le coût de revient.
Dans le framework Deep Learning, la différenciation partielle (gradient) du paramètre est calculée automatiquement, mais lors de l'implémentation avec Scipy + Numpy, il est nécessaire d'obtenir la différenciation partielle par vous-même.
def compute_grad(theta, xm, ym, lamb):
'''
function:
compute the cost gradient of a particular choice of theta
args:
theta : parameter related to weight, bias
xm, ym : data of features, labels
'''
m, n = xm.shape
xent_grad = np.zeros_like(theta)
logits = np.dot(xm, theta)
for i in range(m):
# grad(J) calculation
sigmd_x = sigmoid(logits[i])
delta = sigmd_x - ym[i]
xent_grad += 1. / m * (delta * xm[i])
xent_grad = xent_grad.flatten()
theta = theta.flatten()
# add regularization term to grad
cost_grad = np.zeros_like(xent_grad)
cost_grad[0] = xent_grad[0]
cost_grad[1:] = xent_grad[1:] + lamb / m * theta[1:]
return cost_grad
Fondamentalement, l'expression est convertie en code tel quel, mais le terme de régularisation est ajouté dans la seconde moitié. (Je crée un programme en fonction de la façon de procéder avec la mission Coursera ...)
Dans la tâche de Cousera, une fonction pour le processus d'optimisation est préparée et le flux est de résoudre la tâche qui l'utilise, mais cette fois, nous utiliserons la fonction Scipy scipy.optimize.minimize.
from scipy import optimize
def compute_cost_sp(theta):
global xmat, ymat, lamb
j = compute_cost(theta, xmat, ymat, lamb)
return j
def compute_grad_sp(theta):
global xmat, ymat, lamb
j_grad = compute_grad(theta, xmat, ymat, lamb)
return j_grad
if __name__ == '__main__':
x_raw, ymat = load_data(DATA)
xmat = map_feature(x_raw[:,0], x_raw[:, 1])
m, n = xmat.shape
theta_ini = np.zeros((n, 1))
lamb = 1.e-6
print('initial cost ={:9.6f}'.format(
np.asscalar(compute_cost_sp(theta_ini))))
res1 = optimize.minimize(compute_cost_sp, theta_ini, method='BFGS',
jac=compute_grad_sp, options={'gtol': 1.e-8, 'disp': True})
print('lambda ={:9.6f}, cost ={:9.6f}'.format(lamb, res1.fun))
Une fonction qui encapsule le calcul de la fonction de coût et ses fonctions de calcul dérivées est préparée, et elle est entrée pour optimiser.minimize () de Scipy avec chaque option. Lorsque ceci est exécuté, la solution optimale peut être obtenue comme suit. (Le but de la préparation du wrapper est d'améliorer la lisibilité en spécifiant le paramètre theta.)
initial cost = 0.693147
Optimization terminated successfully.
Current function value: 0.259611
Iterations: 555
Function evaluations: 556
Gradient evaluations: 556
lambda = 0.000001, cost = 0.259611
Bien que l'ensemble de données puisse être petit, la solution pourrait être trouvée en très peu de temps, même dans le cas où le nombre d'itérations était de 555.
L'histoire va et vient, mais dans cette tâche, des quantités d'entités d'ordre supérieur sont générées (mappées) à partir de données avec deux quantités d'entités (x1, x2) et des calculs sont effectués à l'aide de celles-ci.
mapFeature(x) = [1,\ x_1,\ x_2,\ x_1^2,\ x_1x_2,\ x_2^2,\ ...\ ,\ x_2^6] ^ T
Le code Python est le suivant.
def map_feature(x1, x2):
degree = 6 # accordint to coursera exercise
m = len(x1)
out = np.ones((m, 28))
index = 1
for i in range(1, degree+1):
for j in range(i+1):
out[:, index] = x1[:] ** (i-j) * x2[:] ** j
index += 1
return out
Comme mentionné ci-dessus, le modèle est créé en considérant jusqu'au 6ème ordre et en l'étendant à 28 quantités de caractéristiques en incluant le terme d'interaction de x1 et x2. Bien qu'il apparaisse dans les manuels de modélisation statistique, j'ai senti qu'il y avait peu d'occasions de programmer un tel traitement. La raison en est que lors de l'utilisation d'un modèle de réseau neuronal, il s'agit souvent d'un modèle multicouche avec deux couches ou plus (bien que cette fois-ci il s'agisse d'une régression logistique à une couche), et de l'ordre supérieur sur ce modèle. Puisque le modèle peut être exprimé, on considère que le traitement mapFeature () n'est pas nécessaire. Dans cette mapFeature (), le 6ème ordre est pris en compte, mais à la place, on s'attend à ce que le modèle MLP (Multi-layer Perceptron) à 6 couches puisse effectuer des calculs avec la même fonction de classification.
Ensuite, j'ai essayé de mettre en œuvre en utilisant TensorFlow. Depuis que j'ai créé le code Scipy.Optimize en premier, cela ne demande pas beaucoup d'efforts.
def compute_cost_tf(theta, x, y_, lamb):
logits = tf.matmul(x, theta)
pred = tf.sigmoid(logits)
xent = -1. * y_ * tf.log(pred) - (1. - y_) * tf.log(1. - pred)
# xent = tf.nn.sigmoid_cross_entropy_with_logits(logits, y_)
xent_mean = tf.reduce_mean(xent)
L2_sqr = tf.nn.l2_loss(w)
cost = xent_mean + lamb * L2_sqr
return cost, pred
TensorFlow a également une fonction sigmond tf.sigmod () et prend en charge tf.nn.l2_loss () pour trouver le terme de décroissance de poids pour la régularisation. Encore plus heureusement, pour le calcul de xent = -1. * Y_ * tf.log (pred) - (1. --Y_) * tf.log (1. --pred)
, la fonction tf.nn.sigmoid_cross_entropy_with_logits ( ) Peut également être utilisé.
(Dans la [Documentation] de cette fonction tf.nn.sigmoid _... (https://www.tensorflow.org/versions/r0.9/api_docs/python/nn.html#sigmoid_cross_entropy_with_logits) sur la fonction de coût de la régression logistique Il sera utile car il contient des explications détaillées.)
Après cela, j'ai créé un programme selon la méthode TensorFlow.
if __name__ == '__main__':
x_raw, ymat = load_data(DATA)
xmat = map_feature(x_raw[:,0], x_raw[:, 1])
# Variables
x = tf.placeholder(tf.float32, [None, 28])
y_ = tf.placeholder(tf.float32, [None, 1])
w = tf.Variable(tf.zeros([28, 1], tf.float32))
lamb = 1.0 / len(xmat)
cost, y_pred = compute_cost_tf(w, x, y_, lamb)
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cost)
delta = tf.abs((y_ - y_pred))
correct_prediction = tf.cast(tf.less(delta, 0.5), tf.int32)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# Train
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
print('Training...')
for i in range(10001):
batch_xs, batch_ys = xmat, ymat
fd_train = {x: batch_xs, y_: batch_ys.reshape((-1, 1))}
train_step.run(fd_train)
if i % 1000 == 0:
cost_step = cost.eval(fd_train)
train_accuracy = accuracy.eval(fd_train)
print(' step, loss, accurary = %6d: %8.3f,%8.3f' % (i,
cost_step, train_accuracy))
# final model's parameter
w_np = sess.run(w)
La situation diffère selon le coefficient de régularisation (lambda), mais le chiffre du résultat de la classification est le suivant.
Fig. Training data with decision Boundary
Cette fois, j'ai repensé au concept d'entropie croisée selon le matériel pédagogique de la semaine 2 de Cousera Machine Learning. J'ai pu à nouveau réaliser la bonté du matériel pédagogique, mais pour ceux qui sont intéressés mais qui n'ont pas suivi le cours, je vous recommande de trouver le temps de suivre le cours.
--Cousera Machine Learning (par le prof. Ng) Texte du devoir de la semaine 2 (texte PDF)