Grundsätzlich ist bekannt, dass Deep Learning nur dann genau sein kann, wenn die Anzahl der Daten bis zu einem gewissen Grad groß ist, aber "metrisches Lernen" ist genau, selbst wenn die Anzahl von N klein ist. In den folgenden Artikeln finden Sie detaillierte Erklärungen und Implementierungsmethoden.
Erläuterung: Moderne Lernmethode für tiefe Metriken: SphereFace, CosFace, ArcFace Keras-Implementierung: [Keras] Ich habe versucht, Haustierflaschen mit MobileNetV2 + ArcFace zu klassifizieren!
Arcface, eines der metrischen Lernprogramme, verwendet den Merkmalsmengenvektor nach dem globalen durchschnittlichen Pooling von CNN zum Zeitpunkt der Inferenz. Die Klassifizierung wird durchgeführt, indem die cos-Ähnlichkeit (Winkel zwischen mehrdimensionalen Vektoren) mit den Bewertungsdaten basierend auf dem repräsentativen Merkmalsmengenvektor der Trainingsdaten berechnet wird. Da es cos ist, nimmt es einen Wert von -1 bis 1 an, und wenn es 1 ist, bedeutet dies, dass der Winkel 0 ist, dh der Winkel, der durch die zwei Vektoren gebildet wird, ist 0, und es kann gesagt werden, dass die zwei Merkmalsgrößenvektoren ähnlich sind. Wenn es sich also um eine 3-Klassen-Klassifikation handelt, ist es eine Möglichkeit, einen repräsentativen Vektor für jede Klasse zu erstellen und den mit der höchsten cos-Ähnlichkeit als vorhergesagten Wert auszugeben.
Übrigens ist es nach dem Erlernen des Modells des tiefen Lernens möglich, zu realisieren, was Sie tun möchten, indem Sie es mit einem Edge-PC berechnen lassen. Wenn Sie jedoch eine GPU verwenden und mehrere Blätter gleichzeitig ableiten möchten, ist es besser, mehrere Blätter gleichzeitig abzuleiten. Natürlich ist die Berechnungszeit von schneller. Ich denke nicht, dass es so schwierig ist, mehrere Blätter gleichzeitig zu stapeln (ich weiß nicht, ob dieses Wort richtig ist ...), mit einer normalen Klassifizierung mehrerer Klassen. Im Fall von cos-Ähnlichkeit ist jedoch ein wenig Einfallsreichtum erforderlich, daher werde ich Folgendes schreiben.
① So stapeln Sie die Ähnlichkeit, die bei der Bogenflächeninferenz verwendet wird (2) Integrieren Sie cos-Ähnlichkeit in Keras (Tensorflow), indem Sie das Keras-Modell und das Backend kombinieren
das ist alles. Bitte beachten Sie, dass das Lernen der Arcface selbst und die Implementierung zum Erhalten des repräsentativen Vektors übersprungen werden.
tensorflow 1.15.0
keras 2.3.1
Python 3.7.6
numpy 1.18.1
core i7
GTX1080ti
Keras-Implementierung: [Keras] Ich habe versucht, Haustierflaschen mit MobileNetV2 + ArcFace zu klassifizieren! Ich werde mich beziehen.
Dies ist eine Funktion zur Berechnung der vorausgesetzten cos-Ähnlichkeit.
cosine_similarity.py
def cosine_similarity(x1, x2):
if x1.ndim == 1:
x1 = x1[np.newaxis]
if x2.ndim == 1:
x2 = x2[np.newaxis]
x1_norm = np.linalg.norm(x1, axis=1)
x2_norm = np.linalg.norm(x2, axis=1)
cosine_sim = np.dot(x1, x2.T)/(x1_norm*x2_norm+1e-10)
return cosine_sim
Erstens, wie man die cos-Ähnlichkeit eins nach dem anderen findet.
backend_result.py
from keras.applications.xception import Xception
from keras.preprocessing.image imload_img, img_to_array
import time
import os
imgpath = "Ein Pfad, der mehrere geeignete Bilder enthält"
#Modelldefinition
#Erstellen Sie vorübergehend ein Modell mit GAP, das an xception angehängt ist
#Die Ausgabe ist(N, 2048)
input_tensor = Input(shape=(299, 299, 3))
xception_model = Xception(include_top=False, weights='imagenet', input_tensor=input_tensor)
x = xception_model.output
outputs = GlobalAveragePooling2D()(x)
model = Model(inputs=input_tensor, outputs=outputs)
#Definieren Sie einen vorläufigen repräsentativen Vektor → 1 Bildvektor für jede der 10 Klassen
#Definieren Sie diesmal alle 1 Vektoren entsprechend.
master_vector = np.ones([10, 2048])
#Liste der Bildnamen
#Es ist in Ordnung, glob zu verwenden
img_name_list = os.listdir(imgpath)
for i in imglist:
absname = os.path.join(imgpath, i)
img_rgb = load_img(absname, color_mode='rgb', target_size=(299,299))
img_rgb = img_to_array(img_rgb)
img_rgb = np.expand_dims(img_rgb, axis=0)
pred_vector = model.predict(img_rgb)
#Berechnen Sie die cos-Ähnlichkeit
#pred_vector=(1, 2048)×master_vector=(10, 2048)→(1, 10)
cos_sim = cosine_similarity(pred_vector, master_vector)
pred_class = np.argmax(cos_sim[0])
print(pred_class)
Die nächste Methode besteht darin, die cos-Ähnlichkeit für mehrere Bilder gleichzeitig zu ermitteln.
Lassen Sie uns die Funktion ändern, die die cos-Ähnlichkeit berechnet.
Die Änderung besteht darin, dass bei der Berechnung des inneren Produkts dieses zuerst durch die Quadratnorm jedes Vektors geteilt und dann berechnet wird.
Bei der Berechnung der Quadratnorm mit np.linalg.norm
wird beispielsweise keepdims = True
gesetzt
Merkmalsvektorform für 10 Bilder: (10, 2048)
Im Falle von
Form der quadratischen Norm des Merkmalsvektors für 10 Bilder: (10, 1)
Und Sie können sich normal teilen. (Fügen Sie danach einen kleinen Wert hinzu, damit er nicht durch 0 geteilt wird.) Mit dieser Methode ist es möglich, unabhängig von der Form jedes Merkmalsvektors zu berechnen. (Wenn Sie interessiert sind, versuchen Sie es bitte, während Sie die Form des Vektors mit der Form überprüfen.)
cosine_similarity_batch.py
def cosine_similarity_batch(x1, x2):
if x1.ndim == 1:
x1 = x1[np.newaxis]
if x2.ndim == 1:
x2 = x2[np.newaxis]
x1_norm = np.linalg.norm(x1, axis=1, keepdims=True)
x2_norm = np.linalg.norm(x2, axis=1, keepdims=True)
#Teilen Sie zuerst durch die Quadratnorm (Länge des Vektors) jedes Merkmalsvektors und berechnen Sie dann das innere Produkt
cosine_sim = np.dot(x1/(x1_norm+1e-10), (x2/(x2_norm+1e-10)).T)
return cosine_sim
Danach können Sie dies verwenden, um im Batch abzuleiten und dann mit der obigen Funktion zu berechnen.
backend_result.py
from keras.applications.xception import Xception
from keras.preprocessing.image imload_img, img_to_array
import time
import os
imgpath = "Ein Pfad, der mehrere geeignete Bilder enthält"
#Modelldefinition
#Erstellen Sie vorübergehend ein Modell mit GAP, das an xception angehängt ist
#Die Ausgabe ist(N, 2048)
input_tensor = Input(shape=(299, 299, 3))
xception_model = Xception(include_top=False, weights='imagenet', input_tensor=input_tensor)
x = xception_model.output
outputs = GlobalAveragePooling2D()(x)
model = Model(inputs=input_tensor, outputs=outputs)
#Definieren Sie einen vorläufigen repräsentativen Vektor → 1 Bildvektor für jede der 10 Klassen
#Definieren Sie diesmal alle 1 Vektoren entsprechend.
master_vector = np.ones([10, 2048])
#Liste der Bildnamen
#Es ist in Ordnung, glob zu verwenden
img_name_list = os.listdir(imgpath)
#Fügen Sie es mit der for-Anweisung in eine leere Liste ein und machen Sie es zu einem numpy-Array
imgs = []
for i in imglist:
absname = os.path.join(imgpath, i)
img_rgb = load_img(absname, color_mode='rgb', target_size=(299,299))
img_rgb = img_to_array(img_rgb)
imgs.append(img_rgb)
imgs = np.array(imgs, np.float32)
#Schliessen und berechnen Sie mit der vorherigen Funktion
#Berechnen Sie die cos-Ähnlichkeit
#pred_vector=(N Blätter, 2048)×master_vector=(10, 2048)→(N, 10)
pred_vector = model.predict(imgs)
cos_sim = cosine_similarity_batch(pred_vector, master_vecter)
#Da sich für die Anzahl der Chargen eine Ähnlichkeit von 10 cos ergibt, ist argmax die Achse=Laufen Sie auf 1
pred_class = np.argmax(cos_sim, axis=1)
print(pred_class)
Danach können Sie das Ergebnis kochen oder backen und es mögen.
Dies ist das Hauptthema. Da wir Keras (Tensorflow) verwenden, mit denen dieselbe Verarbeitung für mehrere Bilder gleichzeitig berechnet werden kann, ist es schneller, die Berechnung mit Numpy nach Inferenz in das Modell aufzunehmen. Es ist ein Plan. Das heißt, es ist nicht so schwierig, weil Sie nur neu implementieren müssen, was Sie mit numpy im Keras-Backend tun.
cosine_simlarity_kerasbackend.py
def cosine_similarity_eval(args):
x1, x2 = args
x2 = K.constant(x2)
x1_norm = K.sqrt(K.sum(K.square(x1), axis=1, keepdims=True))
x2_norm = K.sqrt(K.sum(K.square(x2), axis=1, keepdims=True))
cosine_sim = K.dot(x1/(x1_norm+1e-10), K.transpose(x2/(x2_norm+1e-10)))
return cosine_sim
Nachfolgend sind die Unterschiede zur Numpy-Implementierung aufgeführt. -Der repräsentative Vektor wird durch Numpy hergestellt und in dieser Funktion in einen konstanten Tensor umgewandelt.
l2_normalize
verwenden, können Sie es in eine Zeile schreiben.)
Als nächstes erfahren Sie, wie Sie sich mit dem Keras-Modell verbinden.cosine_simlarity_kerasbackend.py
#Definiert ein Modell, das einen Feature-Vektor ausgibt
input_tensor = Input(shape=(299, 299, 3))
xception_model = Xception(include_top=False, weights='imagenet', input_tensor=input_tensor)
x = xception_model.output
outputs = GlobalAveragePooling2D()(x)
model = Model(inputs=input_tensor, outputs=outputs)
#Definieren Sie einen vorläufigen repräsentativen Vektor → 1 Bildvektor für jede der 10 Klassen
#Definieren Sie diesmal alle 1 Vektoren entsprechend.
master_vector = np.ones([10, 2048])
#Geben Sie den Tensor des Merkmalsvektors und den repräsentativen Vektor ein, die die Ausgaben des Modells sind.
cosine_sim = cosine_similarity_eval([model.output, master_vecter])
Wenn Sie dies tun, wird das Berechnungsdiagramm des Tensorflusses, der die Kosinussimulation mit der Modelleingabe als Eingabe ausgibt, abgeschlossen. Verwenden Sie diese Option, um Daten mit sess.run zu übertragen, und Sie sind fertig. Unten ist der gesamte Code.
cosine_simlarity_kerasbackend.py
from keras.applications.xception import Xception
from keras.preprocessing.image imload_img, img_to_array
from keras import backend as K
import time
import os
#Definieren Sie eine Sitzung
sess = K.get_session()
imgpath = "Ein Pfad, der mehrere geeignete Bilder enthält"
#Modelldefinition
#Erstellen Sie vorübergehend ein Modell mit GAP, das an xception angehängt ist
#Die Ausgabe ist(N, 2048)
input_tensor = Input(shape=(299, 299, 3))
xception_model = Xception(include_top=False, weights='imagenet', input_tensor=input_tensor)
x = xception_model.output
outputs = GlobalAveragePooling2D()(x)
model = Model(inputs=input_tensor, outputs=outputs)
#Geben Sie den Tensor des Merkmalsvektors und den repräsentativen Vektor ein, die die Ausgaben des Modells sind.
cosine_sim = cosine_similarity_eval([model.output, master_vecter])
#Definieren Sie einen vorläufigen repräsentativen Vektor → 1 Bildvektor für jede der 10 Klassen
#Definieren Sie diesmal alle 1 Vektoren entsprechend.
master_vector = np.ones([10, 2048])
#Liste der Bildnamen
#Es ist in Ordnung, glob zu verwenden
img_name_list = os.listdir(imgpath)
#Fügen Sie es mit der for-Anweisung in eine leere Liste ein und machen Sie es zu einem numpy-Array
imgs = []
for i in imglist:
absname = os.path.join(imgpath, i)
img_rgb = load_img(absname, color_mode='rgb', target_size=(299,299))
img_rgb = img_to_array(img_rgb)
imgs.append(img_rgb)
imgs = np.array(imgs, np.float32)
cos_sim = sess.run(
cosine_sim,
feed_dict={
model.input: imgs,
K.learning_phase(): 0
})
#Da sich für die Anzahl der Chargen eine Ähnlichkeit von 10 cos ergibt, ist argmax die Achse=Laufen Sie auf 1
#Sie können es hier auch in das Modell integrieren
pred_class = np.argmax(cos_sim, axis=1)
print(pred_class)
Ich werde es als Referenz setzen Es ist die Zeit vom Laden des Bildes bis zur Inferenz.
Methode | Zeit[s/100 Blatt] |
---|---|
Schliessen Sie eins nach dem anderen | 1.37 |
Batch-Inferenz mit Numpy | 0.72 |
Batch-Inferenz mit Keras | 0.66 |
Es ist ein bisschen schnell. Diese Methode mit dem Keras-Backend kann an vielen Stellen angewendet werden. Ich denke, es lohnt sich, sich daran zu erinnern.
das ist alles. Wenn Sie Fragen oder Bedenken haben, hinterlassen Sie bitte einen Kommentar.