Der Inhalt ist ["Deep Learning von Grund auf neu"](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4% BD% 9C% E3% 82% 8BDeep-Learning-% E2% 80% 95Python% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% A3% E3 % 83% BC% E3% 83% 97% E3% 83% A9% E3% 83% BC% E3% 83% 8B% E3% 83% B3% E3% 82% B0% E3% 81% AE% E7% 90 % 86% E8% AB% 96% E3% 81% A8% E5% AE% 9F% E8% A3% 85-% E6% 96% 8E% E8% 97% A4-% E5% BA% B7% E6% AF % 85 / dp / 4873117585) 4.4.2 Gradient für neuronales Netzwerk (gemäß S.110). Da die Frage gelöst wurde, werde ich einen Artikel schreiben.
Was ich mich gefragt habe, war der Code am Ende von S.111. (folgende)
>>> def f(W):
... return net.loss(x, t)
...
>>> dW = numerical_gradient(f, net.W)
>>> print(dW)
[[ 0.21924763 0.14356247 -0.36281009]
[ 0.32887144 0.2153437 -0.54421514]]
Ich habe die Funktion "f" definiert und als Argument an die Funktion "numerischer Gradient" übergeben, die kurz vor diesem Buch definiert wurde. Als ich das zweite Argument dieser Funktion "numerischer Gradient" auf einen geeigneten Wert änderte, änderte sich der Wert von "dW". (folgende)
#Net als zweites Argument.Geben Sie W. an.(net.Für W, p in diesem Buch.Siehe den Kommentar von 110.)
>>> dW = numerical_gradient(f, net.W)
>>> print(dW)
[[ 0.06281915 0.46086202 -0.52368118]
[ 0.09422873 0.69129304 -0.78552177]]
#Speichern Sie das numpy-Array in a und geben Sie es als zweites Argument an.
>>> a = np.array([[0.2, 0.1, -0.3],
[0.12, -0.17, 0.088]])
>>> dW = numerical_gradient(f, a)
>>> print(dW)
[[0. 0. 0.]
[0. 0. 0.]]
Ich habe nicht verstanden, warum sich der Wert von "dW" geändert hat. Dieser Artikel ist die Antwort auf diese Frage.
Ich werde erklären, warum ich mich gefragt habe, warum sich der Wert von "dW" geändert hat.
Erstens hat der Rückgabewert dieser f
-Funktion nichts mit dem Wert des Arguments W
zu tun.
Dies liegt daran, dass "W" nicht nach "return" in der Funktion "f" erscheint.
Unabhängig davon, welchen Wert Sie für das Funktionsargument f`` W
ändern, ändert sich der Rückgabewert überhaupt nicht. (Siehe unten)
#Geben Sie 3 als Argument der Funktion f an.
>>> f(3)
2.0620146712373737
#net to f Funktion.Geben Sie W. an.
>>> f(net.W)
2.0620146712373737
#Definieren Sie ein Numpy-Array und weisen Sie es einem zu. Vergleichen Sie, wann a an die Funktion f übergeben wird und wann 3 übergeben wird.
>>> a = np.array([[0.2, 0.1, -0.3],
[0.12, -0.17, 0.088]])
>>> f(a) == f(3)
True
Als weiteren Punkt werde ich die Funktion "numerischer Gradient" vorstellen. (folgende)
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x) # f(x+h)
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val #Stellen Sie den Wert wieder her
it.iternext()
return grad
Diese Funktion gibt den in der Funktion definierten Grad zurück.
Wenn Sie am Ende des Codes folgen, wie dieser "Grad" abgeleitet wird,
Sie finden den Code grad [idx] = (fxh1 --fxh2) / (2 * h)
.
Was sind also "fxh1" und "fxh2"?
Sie finden den Code fxh1 = f (x)
fxh2 = f (x)
.
Ab Punkt 2 kann der Rückgabewert der Funktion "numerischer Gradient" grad "dem Wert von" f (x) "zugeordnet werden.
Ab Punkt 1 gibt die Funktion f
unabhängig vom Wert des Arguments einen konstanten Wert zurück.
Von den Punkten 1 und 2 aus wird unabhängig davon, welcher Wert dem zweiten Argument "x" der Funktion "numerischer Gradient" zugewiesen wird
Ich fand es seltsam, dass sich der Rückgabewert der Funktion numerischer_gradient
ändern würde.
Schauen wir uns zunächst die Funktion numerischer_gradient
genauer an.
Und ich werde die Funktion f
etwas genauer erklären.
numerischer_gradient
Eine kleine Änderung am Code "numerischer_gradient".
Insbesondere unter "fxh1 = f (x)" fxh2 = f (x) "
Geben Sie print (fxh1)
print (fxh2)
ein. (folgende)
def numerical_gradient(f, x):
h = 1e-4
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
print('idx:', idx)
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x) # f(x+h)
print('fxh1:', fxh1) # print(fxh1)Eingeben
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
print('fxh2:', fxh2) # print(fxh2)Eingeben
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val
it.iternext()
return grad
Verschieben wir nun den Code, indem wir das zweite Argument ändern.
Ersetzen Sie das zweite Argument durch "net.W"
>>> dW = numerical_gradient(f, net.W)
fxh1: 2.062020953321506
fxh2: 2.0620083894906935
fxh1: 2.062060757760379
fxh2: 2.061968585355599
fxh1: 2.061962303319411
fxh2: 2.062067039554999
fxh1: 2.062024094490122
fxh2: 2.062005248743893
fxh1: 2.062083801262337
fxh2: 2.0619455426551796
fxh1: 2.061936119510309
fxh2: 2.06209322386368
Ersetzen Sie das zweite Argument durch Ihr eigenes numpy-Array "a"
>>> a = np.array([[0.2, 0.1, -0.3],
[0.12, -0.17, 0.088]])
>>> dW = numerical_gradient(f, a)
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
fxh1: 2.0620146712373737
fxh2: 2.0620146712373737
Für diejenigen, die dem zweiten Argument "net.W" zugewiesen haben, unterscheiden sich die Werte geringfügig zwischen "fxh1" und "fxh2". Wenn Sie dagegen Ihr eigenes numpy-Array "a" ersetzen, haben "fxh1" und "fxh2" den gleichen Wert. Warum? Von nun an werde ich erklären, indem ich den Fall betrachte, in dem "net.W" im zweiten Argument eingegeben wird.
Schauen wir uns die Funktion "numerischer Gradient" genauer an. In der Mitte befindet sich der folgende Code. Dieser Code ändert die Indexnummer von "idx", ruft das "x" dieser Indexnummer ab und Ein kleines "h" wird zu dem extrahierten "x" hinzugefügt und der "f" -Funktion zugewiesen.
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index #Ändern Sie die Indexnummer von idx
tmp_val = x[idx] #Nehmen Sie das x dieser Indexnummer heraus
x[idx] = tmp_val + h #Fügen Sie dem extrahierten x ein kleines h hinzu
fxh1 = f(x) # f(x+h) #Der Funktion f zugeordnet.
Hat sich der Rückgabewert der Funktion "f" aufgrund der Hinzufügung eines kleinen "h" zu "x" geändert? Die Tatsache, dass sich der Rückgabewert der Funktion "f" aufgrund von Änderungen in den Argumenten nicht ändert, wird in Punkt 1 von "Warum haben Sie sich gefragt?"
Tatsächlich gibt es einen Teil, der sich durch Hinzufügen eines kleinen "h" zu "x" geändert hat. Das "x" hier ist das "net.W", das dem zweiten Argument der Funktion "numerischer_gradient" zugewiesen ist. Nach dem Hinzufügen eines kleinen "h" zu "net.W" wird es an das Argument der "f" -Funktion übergeben. Der folgende Teil der zuvor gezeigten Funktion "numerischer Gradient".
x[idx] = tmp_val + h #Fügen Sie dem extrahierten x ein kleines h hinzu
fxh1 = f(x) #Der Funktion f zugeordnet.
Wichtig ist hier die Reihenfolge, in der die Funktion "f" aufgerufen wird, nachdem sich "net.W" geändert hat. Wie wirkt sich die Änderung in "net.W" auf die "f" -Funktion aus?
Mal sehen, wie sich die Änderung in "net.W" auf die "f" -Funktion auswirkt.
Die f
Funktion ist unten gezeigt.
def f(W):
return net.loss(x, t)
Die "Verlust" -Funktion, die in der "f" -Funktion angezeigt wird, ist in der auf S.110 dieses Handbuchs definierten "simpleNet" -Klasse definiert.
Die simpleNet
Klasse ist unten gezeigt.
import sys, os
sys.path.append(os.pardir)
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradient
class simpleNet:
def __init__(self):
self.W = np.random.randn(2,3)
def predict(self, x):
return np.dot(x, self.W)
def loss(self, x, t):
z = self.predict(x)
y = softmax(z)
loss = cross_entropy_error(y, t)
return loss
Sie sehen die "Verlust" -Funktion am unteren Rand von "simpleNet". Innerhalb der "Verlust" -Funktion gibt es eine "Vorhersage" -Funktion. Die "Vorhersage" -Funktion wird direkt über der "Verlust" -Funktion definiert. Wenn Sie sich die Funktion "Vorhersagen" genauer ansehen, sehen Sie den Gewichtungsparameter "W".
Wie wirkt sich die Änderung in "net.W" am Ende von "Erfahren Sie mehr über die Funktion" numerischer Gradient "auf die Funktion" f "aus? Die Antwort ist hier. Durch Ändern von "net.W" hat sich der Gewichtungsparameter "W" der "Vorhersage" -Funktion geändert, die von der "Verlust" -Funktion in der "f" -Funktion aufgerufen wird. Dann ändert sich natürlich der Rückgabewert der "Verlust" -Funktion.
Die Erklärung ist endlich vorbei.
Kehren wir zur Funktion numerischer_gradient
zurück. Die Funktion numerischer_gradient
wird unten noch einmal gezeigt.
def numerical_gradient(f, x):
h = 1e-4
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
print('idx:', idx)
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x) # f(x+h)
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
print('fxh2:', fxh2)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val
it.iternext()
return grad
Wie oben erwähnt, ändert sich der Rückgabewert der "Verlust" -Funktion in der "f" -Funktion aufgrund der Änderung von "net.W".
In diesem Code wurde durch Hinzufügen eines kleinen "h" zu "x" ("net.W") die Funktion "f" und der Wert von "fxh1" geändert.
Gleiches gilt für das nachfolgende "fxh2".
Dann an den nachfolgenden Code übergeben, druckt die Funktion numerischer_gradient
den Rückgabewert.
Dies löste die erste Frage, die ich stellte.
Der wichtige Punkt ist
● Unterdrücken Sie, dass das zweite Argument der Funktion "numerischer Gradient", "x", "net.W" ist.
● Der Rückgabewert der Funktion f
hat sich geändert, als sich net.W
geändert hat.
Lesen wir weiter "Deep Learning von Grund auf neu"!
Recommended Posts