Ich habe vor ungefähr einem Jahr an Courseras maschinellem Lernen teilgenommen, aber ich habe das Gefühl, die Grundlagen des maschinellen Lernens erlernen zu können. "Cross-Entropy" ist eine Fehlerfunktion, die im Klassifizierungsproblem verwendet wird. Um das Konzept zu berücksichtigen, haben wir erneut die Aufgabe der zweiten Woche von Coursera ML, der logistischen Regression, ausgeführt. Tatsächlich wurde Matlab (oder Octave) im Kurs verwendet, aber hier verwenden wir Python.
(Programmierumgebung: Python 2.7.11, numpy 1.11.0, scipy 0.17.0, tensorflow 0.9.0rc.)
Betrachten wir zunächst das Modell der logistischen Regression im Klassifizierungsproblem.
** Abb. Logistisches Regressionsmodell **
Dies ist ein Modell, bei dem die Eingabewerte x1, x2, ... xn gewichtet und addiert werden und der geschätzte Wert durch die Sigmoidfunktion erhalten wird, die die Aktivierungsfunktion ist. In der obigen Figur werden die Gewichte w1, w2, ... wn und der Vorspannungswert b verwendet, aber in der Erklärung von Coursera werden w und b gemeinsam als Parameter Theta verwendet.
Die Kreuzentropie ist ein numerischer Wert, der angibt, "wie stark der geschätzte Wert des obigen Modells vom tatsächlichen Wert abweicht". Es wird durch die folgende Gleichung ausgedrückt. (Englisch wird manchmal als Kreuzentropie, Xentropie, Xent abgekürzt.)
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}})
Hier ist h_theta (x) ein geschätzter Wert. Da es sich um einen geschätzten Wert im binären Klassifizierungsproblem handelt, beträgt die Wahrscheinlichkeit, dass die Klassifizierung y = 1 ist, [0,0 ... 1,0]. Außerdem ist y ^ (i) die tatsächliche Klasse (0 oder 1), die als Trainingsdaten angegeben wird. Der Fluss der logistischen Regression besteht darin, ein hochgenaues Modell zu erhalten, indem der Parameterwert Theta ermittelt wird, der diese Fehlerfunktion minimiert (Kostenfunktion in Coursera) J (Theta). Die Ableitung der Fehlerfunktion (Gradient) wird im Optimierungsprozess der Funktionsminimierung benötigt, der wie folgt ist.
\frac{\partial J(\theta)}{\partial \theta_j} = \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})x_j^{(i)}
Basierend auf diesen Ausdrücken erstellen wir Python-Code.
Erstellen Sie zunächst einen Code, um die Kostenfunktion zu ermitteln, und folgen Sie dann den Anweisungen im Kurs.
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
Definieren Sie zunächst die Sigmoidfunktion. Als nächstes berechnet compute_cost () die Kosten basierend auf der obigen Kreuzentropie-Gleichung. Der obige Code fügt die Variable xent in der for-Schleife für jedes Datenbeispiel hinzu. Aus Effizienzgründen ist es jedoch besser, die for-Schleife nicht zu verwenden, aber ich denke, dies ist für den ersten Code in Ordnung. Nach der Berechnung des Kreuzentropie-Xents wird der Term der L2-Norm (Gewichtsdämpfung) hinzugefügt, um eine Überanpassung zu verhindern, um die Kostenkosten zu erhalten.
Im Deep Learning-Framework wird die partielle Differenzierung (Gradient) des Parameters automatisch berechnet. Bei der Implementierung mit Scipy + Numpy ist es jedoch erforderlich, die partielle Differenzierung selbst zu erhalten.
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
Grundsätzlich wird der Ausdruck so wie er ist in den Code konvertiert, aber der Regularisierungsterm wird in der zweiten Hälfte hinzugefügt. (Ich erstelle ein Programm entsprechend der Vorgehensweise bei der Coursera-Aufgabe ...)
In Couseras Aufgabe wird eine Funktion für den Optimierungsprozess vorbereitet und der Ablauf besteht darin, die Aufgabe damit zu lösen. Dieses Mal verwenden wir jedoch die Scipy-Funktion 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))
Eine Funktion, die die Kostenfunktionsberechnung und ihre abgeleiteten Berechnungsfunktionen umschließt, wird vorbereitet und eingegeben, um Scipy zusammen mit jeder Option zu optimieren (). Wenn dies ausgeführt wird, kann die optimale Lösung wie folgt erhalten werden. (Der Zweck der Vorbereitung des Wrappers besteht darin, die Lesbarkeit durch Angabe des Parameters Theta zu verbessern.)
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
Obwohl der Datensatz klein sein kann, konnte die Lösung in sehr kurzer Zeit gefunden werden, selbst in der Situation, in der die Anzahl der Iterationen 555 betrug.
Die Geschichte geht hin und her, aber in dieser Aufgabe werden Merkmalsgrößen höherer Ordnung aus Daten mit zwei Merkmalsgrößen (x1, x2) generiert (abgebildet) und Berechnungen mit diesen durchgeführt.
mapFeature(x) = [1,\ x_1,\ x_2,\ x_1^2,\ x_1x_2,\ x_2^2,\ ...\ ,\ x_2^6] ^ T
Der Python-Code lautet wie folgt.
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
Wie oben erwähnt, wird das Modell erstellt, indem bis zur 6. Ordnung berücksichtigt und auf 28 Merkmalsgrößen erweitert wird, indem der Interaktionsterm von x1 und x2 eingeschlossen wird. Obwohl es in Lehrbüchern zur statistischen Modellierung erscheint, hatte ich das Gefühl, dass es nur wenige Möglichkeiten gibt, eine solche Verarbeitung zu programmieren. Der Grund dafür ist, dass es sich bei Verwendung eines neuronalen Netzwerkmodells häufig um ein mehrschichtiges Modell mit zwei oder mehr Schichten handelt (obwohl es sich diesmal um eine einschichtige logistische Regression handelt) und um die höhere Ordnung dieses Modells. Da das Modell ausgedrückt werden kann, wird davon ausgegangen, dass die Verarbeitung von mapFeature () nicht erforderlich ist. In diesem mapFeature () wird bis zur 6. Ordnung berücksichtigt. Stattdessen wird erwartet, dass das 6-Schicht-Mehrschicht-Perceptron-Modell (MLP) Berechnungen mit derselben Klassifizierungsfunktion durchführen kann.
Als nächstes habe ich versucht, mit TensorFlow zu implementieren. Da ich zuerst den Scipy.Optimize-Code erstellt habe, ist dies nicht sehr aufwändig.
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 hat auch eine Sigmond-Funktion tf.sigmod () und unterstützt tf.nn.l2_loss (), um den Gewichtsabfallterm für die Regularisierung zu finden. Noch dankbarer für die Berechnung von xent = -1. * Y_ * tf.log (pred) - (1. --y_) * tf.log (1. --pred)
ist die Funktion tf.nn.sigmoid_cross_entropy_with_logits ( ) Kann auch benutzt werden.
(In der [Dokumentation] dieser Funktion tf.nn.sigmoid _... (https://www.tensorflow.org/versions/r0.9/api_docs/python/nn.html#sigmoid_cross_entropy_with_logits) über die Kostenfunktion der logistischen Regression Es wird hilfreich sein, da es detaillierte Erklärungen enthält.)
Danach habe ich ein Programm nach der TensorFlow-Methode erstellt.
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)
Die Situation unterscheidet sich in Abhängigkeit vom Regularisierungskoeffizienten (Lambda), aber die Zahl des Ergebnisses der Klassifizierung ist wie folgt.
Fig. Training data with decision Boundary
Dieses Mal habe ich auf das Konzept der Kreuzentropie gemäß den Lehrmaterialien der zweiten Woche von Cousera Machine Learning zurückgeblickt. Ich konnte die Güte der Unterrichtsmaterialien wieder erkennen, aber für diejenigen, die interessiert sind, aber den Kurs nicht besucht haben, empfehle ich, dass Sie Zeit finden, um den Kurs zu belegen.
--Cousera Machine Learning (von Prof. Ng) Zuweisungstext der zweiten Woche (PDF-Text)
Recommended Posts