Hier ist eine Zusammenfassung dessen, was ich gelernt habe, als ich Tensorberechnungen usw. direkt über das Keras-Backend durchgeführt habe.
Beim Aufbau eines Netzwerks mit Keras denke ich, dass die meisten Ebenen in der Ebene definiert sind. Für eine spezielle Ebene ist es jedoch erforderlich, eine Funktion zu erstellen und in die Lambda-Ebene oder die Zusammenführungsebene einzutauchen. Im Folgenden wird beispielsweise ein Modell mit einer Ebene erstellt, die den absoluten Wert der Eingabe zurückgibt.
lambda_layer_exp.py
from keras.models import Model
from keras.layers import Input, Lambda
import keras.backend as K
x_in = Input(shape=(3, 3))
x = Lambda(lambda x: K.abs(x))(x_in)
model = Model(input=x_in, output=x)
Lassen Sie uns einen Wert in dieses Modell setzen.
>>> import numpy as np
>>> model.predict([np.array([[[-1,2,3],[4,-5,6],[7,8,-9]]])])
array([[[ 1., 2., 3.],
[ 4., 5., 6.],
[ 7., 8., 9.]]], dtype=float32)
Wenn zwei oder mehr Eingaben vorhanden sind, werden diese von der Zusammenführungsebene verarbeitet. Im folgenden Beispiel wird eine Ebene hinzugefügt, die die Summe der Absolutwerte der beiden Eingaben verwendet. Wenn Sie eine Funktion in der Zusammenführungsebene verwenden, müssen Sie output_shape angeben.
merge_layer_exp.py
from keras.models import Model
from keras.layers import Input, merge
import keras.backend as K
x_in1 = Input(shape=(3,))
x_in2 = Input(shape=(3,))
x = merge([x_in1, x_in2], mode=lambda x: K.abs(x[0]) + K.abs(x[1]), output_shape=(3,))
model = Model(input=[x_in1, x_in2], output=x)
Wenn die Berechnung mit diesem Modell ausgeführt wird, sieht es wie folgt aus.
>>> import numpy as np
>>> model.predict([np.array([[-1,-2,3]]), np.array([[4,-5,-6]])])
array([[ 5., 7., 9.]], dtype=float32)
Viele der Funktionen, die im Back-End vorhanden sind, sind fast die gleichen wie die in Numpy, Tensorflow, Theano usw. verwendeten, aber es gibt einige, die schwierig zu verwenden sind, daher werde ich mich auf sie konzentrieren.
dot, batch_dot
Wenn Sie das Keras-Backend verwenden und wenn Sie es nicht verwenden, sollten Sie berücksichtigen, dass Sie beim Backend die Stapelabmessungen wie bei Tensorflow und mehr berücksichtigen müssen.
Diejenigen in Keras Layer, die Formargumente annehmen, werden grundsätzlich ohne die Stapeldimension berücksichtigt. Geben Sie für RGB-Bilder "shape = (3, 32, 32)" an. Berücksichtigen Sie jedoch in der Backend-Funktion die Stapeldimension wie "shape = (None, 3, 32, 32)". Und muss über die Berechnung nachdenken.
Die hier vorgestellten Punktproduktfunktionen dot
und batch_dot
sind Funktionen, die die Abmessungen der Charge berücksichtigen bzw. nicht berücksichtigen.
Ein Beispiel ist unten gezeigt.
import keras.backend as K
a = K.variable([[1,2],[3,4]])
b = K.variable([[5,6],[7,8]])
print K.eval(K.dot(a, b)) #Multiplizieren einer Matrix und einer b-Matrix
print K.eval(K.batch_dot(a, b, 1)) # a[i]Und B[i]Array von Punktprodukten von
print K.eval(a * b) #Multiplikation für jedes Element
Dies führt zu folgenden Ergebnissen:
[[ 19., 22.],
[ 43., 50.]]
[[ 17.],
[ 53.]]
[[ 5., 12.],
[ 21., 32.]]
Wenn Sie eine solche Dimensionsänderungsberechnung in die Lambda-Ebene verschieben möchten, müssen Sie explizit "output_shape" angeben.
import numpy as np
from keras.models import Model
from keras.layers import Input, Lambda
import keras.backend as K
x_in = Input(shape=(2, 2))
x = Lambda(lambda x: K.dot(K.variable([0, 1]), x), output_shape=(2,))(x_in)
model = Model(input=x_in, output=x)
print model.predict([np.array([[[1,2],[3,4]]])])
# [[ 3. 4.]]
one_hot Wie jeder, der die Verarbeitung natürlicher Sprache oder Tensorflow verwendet, möglicherweise "1" kennt, wie in Wikipedia erläutert. Erzeugt eine Bitfolge ❞, sodass nur eine hoch (1) und die andere niedrig (0) ist. Ein Beispiel ist unten gezeigt.
print K.eval(K.one_hot(K.variable([0,2,1,0], dtype=int), 3))
# [[ 1. 0. 0.]
# [ 0. 0. 1.]
# [ 0. 1. 0.]
# [ 1. 0. 0.]]
Sie können Dimensionen durch "permute_dimensions", "expand_dims" und "Squeeze" ersetzen, hinzufügen und löschen.
a = K.variable([[[1,2],[3,4]]])
print K.eval(K.shape(a))
# [1, 2, 2]
print K.eval(K.permute_dimensions(a, [1, 2, 0]))
# [[[ 1.],
# [ 2.]],
#
# [[ 3.],
# [ 4.]]]
print K.eval(K.expand_dims(a, 2))
# [[[[ 1., 2.]],
#
# [[ 3., 4.]]]]
print K.eval(K.squeeze(a, 0))
# [[ 1., 2.],
# [ 3., 4.]]
gather Dies ist ein sogenanntes Slicing, aber Sie können einen Index nur für die erste Dimension angeben. Wenn Sie also für eine Achse indizieren möchten, müssen Sie ihn mit "permute_dimensions" kombinieren.
a = K.variable([[1,2],[3,4],[5,6]])
print K.eval(K.gather(a, 0))
# [ 1., 2.]
print K.eval(K.gather(K.permute_dimensions(a, [1, 0]), 0)) # K.eval(K.gather(K.transpose(a), 0))Gleichwertig
# [ 1., 3., 5.]
Schließlich habe ich mit dem bisherigen Wissen versucht, das in Chainer geschriebene Modell mit Keras neu zu implementieren. Die Geschichte ist Value Iteration Networks (@ peisukes Chainer-Implementierung). Es scheint, dass es das beste Papier von NIPS2016 war. Ich poste es auf Github.
Recommended Posts