[SWIFT] So bearbeiten Sie eine Ebene mit Core ML Tools

Wenn Sie ein Modell mit Core ML Tools konvertieren, möchten Sie möglicherweise Ebenen hinzufügen und Berechnungen dazwischen einfügen oder einen Teil der Ebene ausschneiden. In diesem Artikel wird jedoch erläutert, wie dies funktioniert.

Da Core ML Tools nur wenige Dokumente und wenig Informationen im Internet hat, muss ich sie beim Lesen des Quellcodes nachschlagen, aber ich denke, dass das Bearbeiten von Ebenen ein häufiger Anwendungsfall bei der Konvertierung in Core ML ist. Ich hoffe dieser Artikel hilft Ihnen.

Modellfall: Stellen Sie die Form vor die Ausgabe, um die Form der Ausgabe zu ändern

Fügen wir als Modellfall eine Umformung hinzu, um die Ausgabeform des Modells (19) (1,1,19) zu erhalten.

Es ist fast bedeutungslos, weil ich nur Dimensionen hinzufüge, aber ich mache das, weil ich es zu einem einfachen Fall machen möchte.

Das zu verwendende Modell ist eines, das das Ergebnis der Addition von zwei einstelligen Zahlen vorhersagt (klassifiziert). Das Klassifizierungsergebnis besteht aus 19 Sequenzen. Dies liegt daran, dass das Hinzufügen von einstelligen Zahlen insgesamt 19 Arten von Klassifizierungsproblemen von 0 bis 18 ergibt.

In der Abbildung sieht es so aus.

Dieses Modell ist das gleiche wie das im vorherigen Artikel verwendete. Im vorherigen Artikel haben wir die Ausgabe bis zum Labelnamen angegeben, aber dieses Mal werden wir einfach 19 Wahrscheinlichkeiten so ausgeben, wie sie sind.

Führen Sie ein einfaches Modell aus, das mit Keras unter iOS unter Verwendung von CoreML erstellt wurde

Verfahren

Fügen wir nun die Ebene "Umformen" hinzu. Arbeiten Sie an Google Colaboratory.

Den vollständigen Code für diese Arbeit finden Sie hier. https://gist.github.com/TokyoYoshida/2fada34313385d63b666253490b5f3f4

** 1. Keras-Modell laden **

Ich werde ein mit Keras hergestelltes Modell verwenden. Der Modellerstellungsteil wird weggelassen, da er im vorherigen Artikel enthalten ist.

notebook


from keras.models import load_model
keras_model = load_model('my_model.h5')

** 2. In CoreML konvertieren **

In CoreML konvertieren. Ich habe diesmal kein Etikett angebracht, also konvertiere ich es einfach so, wie es ist.

notebook


from coremltools.converters import keras as converter
mlmodel = converter.convert(keras_model)

** 3. Mit Builder laden **

Laden Sie es in den Neural Network Builder in den Core ML Tools.

notebook


import coremltools
spec = coremltools.utils.load_spec(coreml_model_path)
builder = coremltools.models.neural_network.NeuralNetworkBuilder(spec=spec)

Lassen Sie uns die Modellinformationen anzeigen. Daraus können Sie ersehen, dass die Ausgabe des Modells als output1 bezeichnet wird und die Form 19 ist.

notebook


spec.description.output

#Ausgabeergebnis
# [name: "output1"
# type {
#   multiArrayType {
#     shape: 19
#     dataType: DOUBLE
#   }
# }
# ]

Zeigt Ebeneninformationen an.

notebook


builder.layers
#Ausgabe
# ['dense_4',
#  'dense_4__activation__',
#  'dense_5',
#  'dense_5__activation__',
#  'dense_6',
#  'activation_18']

Das Ziel ist diesmal activity_18, die Ausgabeschicht. Formieren Sie die Ausgabe dieser Ebene neu.

** 4. Rehape-Ebene hinzufügen **

NeuralNetworkBuilder verfügt über eine Methode namens add_reshape, mit der Sie eine Umformebene hinzufügen können.

~~ Es ist wichtig anzumerken, dass ich mit dem Builder dem Builder intuitiv eine Ebene hinzufügen kann, die das ursprüngliche Modell darstellt, aber diese Methode funktioniert nicht. ~~ (Hinzugefügt am 27. Oktober 2020, ich habe festgestellt, dass ich dem Builder eine Ebene hinzufügen kann, die das ursprüngliche Modell darstellt, also werde ich es korrigieren.)

Fügen wir beispielsweise die Umformungsebene so hinzu, wie sie dem zuvor im Builder geladenen Modell entspricht.

notebook


reshape = builder.add_reshape(name='Reshape', input_name='activation_18', output_name='output', target_shape=(1,1,19), mode=0)

Wenn ich dies mit Xcode lese, erhalte ich diesen Fehler.

Xcode-Fehler


There was a problem decoding this CoreML document
validator error: Layer 'Reshape' consumes an input named 'activation_18' which is not present in this network.

Wenn ich versuche, eine CoreML-Inferenz für Python durchzuführen, wird folgende Fehlermeldung angezeigt:

Python-Fehler


RuntimeError: Error compiling model: "Error reading protobuf spec. validator error: Layer 'Reshape' consumes an input named 'activation_18' which is not present in this network.".

Es fiel mir schwer, es im Internet zu finden, aber ich bin mir sicher, dass es Menschen gibt, die es schwer haben, dasselbe zu tun. Der Grund für diesen Fehler ist, dass ich input_name = 'activity_18' gesetzt habe. Hier müssen Sie den Namen der Eingabe oder Ausgabe angeben, die im ursprünglichen Modell in "builder.spec.description" angezeigt wird.

~~ Verwenden Sie zur Umgehung dieses Problems NeuralNetworkBuilder, um ein vollständiges Modell mit nur einer Ebene zu erstellen und es dem ursprünglichen Modell hinzuzufügen. ~~ (Korrigiert am 27. Oktober 2020) Wenn das Argument input_name von add_reshape mit dem Argument output_name des ursprünglichen Modells übereinstimmt, können Sie die Ebenen erfolgreich verbinden.

Fügen Sie Ihrem Modell eine Umformebene hinzu. Eingabe gibt die Ausgabe des Originalmodells an, dh "Ausgabe1". Ich hatte das Gefühl, dass dies die Eingabe des neuen Modells "input2" war, aber es scheint, dass die Ausgabe des ursprünglichen Modells und die Eingabe in die Umformebene nicht gut funktionieren. Ausgabe gibt die Ausgabe des neuen Modells "output2" an. target_shape gibt (1,1,19) an, welche Form Sie dieses Mal konvertieren möchten.

notebook


builder.add_reshape(name='Reshape', input_name='output1', output_name='output2', target_shape=(1,1,19), mode=0)

Sie haben jetzt ein Modell mit hinzugefügter Umformung.

Überprüfen Sie die Ebeneninformationen.

notebook


builder.layers

#Ausgabe
# ['dense_4',
#  'dense_4__activation__',
#  'dense_5',
#  'dense_5__activation__',
#  'dense_6',
#  'activation_18',
#  'Reshape']

** 5. Ändern Sie die Ausgabeinformationen des Modells **

Die Umformebene wurde am Ende des Modells hinzugefügt, dies ersetzte jedoch nur die letzte Ebene des Modells, und die Ausgabeinformationen des gesamten Modells haben sich nicht geändert.

Wenn Sie die Ausgabeinformationen als Test überprüfen, können Sie feststellen, dass sie immer noch (19) anstelle der erwarteten Form (1,1,19) sind.

notebook


spec.description.output
# [name: "output1"
# type {
#   multiArrayType {
#     shape: 19
#     dataType: DOUBLE
#   }
# }
# ]

Das Ändern der Ausgabeinformationen des Modells ist ebenfalls sehr eigenartig und führt zu einem Fehler, wenn Sie versuchen, sie builder.spec.description.output [0] zuzuweisen. Geben Sie es daher beim Poppen oder Hinzufügen an.

notebook


//Löschen Sie eine Ausgabeinformation. Da diesmal nur eine Ausgabeinformation vorhanden war, verschwinden die Ausgabeinformationen
builder.spec.description.output.pop()
//Fügen Sie eine Ausgabeinformation hinzu
builder.spec.description.output.add()
//Geben Sie Attribute der Ausgabeinformationen an
output = builder.spec.description.output[0]
output.name = "output2"
output.type.multiArrayType.dataType = coremltools.proto.FeatureTypes_pb2.ArrayFeatureType.ArrayDataType.Value('DOUBLE')
//Als Forminformation(1,1,19)Einstellen
output.type.multiArrayType.shape.append(1)
output.type.multiArrayType.shape.append(1)
output.type.multiArrayType.shape.append(19)

(Ergänzung) Im obigen Beispiel wurden die Informationen hinzugefügt, nachdem sie durch Löschen mit pop () und Hinzufügen mit add () bereinigt wurden. Es ist jedoch möglich, nur den Attributwert der ursprünglich vorhandenen Ausgabe direkt neu zu schreiben.

Schreiben Sie die Form beispielsweise wie folgt neu.

Beispiel für das Umschreiben der Form


builder.spec.description.output[0].type.multiArrayType.shape[0] = 100

(Ende der Ergänzung)

Wenn Sie die Ausgabeinformationen überprüfen, können Sie feststellen, dass die Einstellungen erfolgreich sind.

notebook


builder.spec.description.output
# [name: "output2"
# type {
#   multiArrayType {
#     shape: 1
#     shape: 1
#     shape: 19
#     dataType: DOUBLE
#   }
# }
# ]

** 6. Überprüfen Sie das Ausgabeergebnis des Modells mit Jupyter Notebook **

Überprüfen Sie das Ausgabeergebnis des Modells mit Jupyter Notebook, das auf einem Mac ausgeführt wird. Warum Jupyter Notebook auf Mac? Da das Back-End von Google Colaboratory jedoch Linux ist, kann auf CoreML nicht geschlossen werden, und es kann nicht bestätigt werden, ob das Modell ordnungsgemäß funktioniert.

Sie können mit Xcode schließen, aber Xcode kann Ihnen beim Lesen eines seltsamen Modells einen Fehler geben, aber es kann auch den folgenden Fehler beim Erstellen löschen.

Xcode-Fehler


Command CoreMLModelCompile failed with a nonzero exit code

Wenn Sie einen solchen Fehler erhalten, sollten Sie ihn in Jupyter Notebook ausführen, um die Details des Fehlers anzuzeigen.

Starten Sie also Jupyter Notebook.

Hier ist der vollständige Code. https://gist.github.com/TokyoYoshida/632b4c8070aa6c937539e4ae261a2740

Geben Sie [2,3] als Eingabe für das Modell und versuchen Sie, die Inferenz durchzuführen.

JupyterNoteBook


coreml_model_path= "my_model_with_builder.mlmodel"

import coremltools
spec = coremltools.utils.load_spec(coreml_model_path)
builder = coremltools.models.neural_network.NeuralNetworkBuilder(spec=spec)

mlmodel = coremltools.models.MLModel(spec)

mlmodel.predict({'input1': np.array([2.0,3.0])})

# {'output2': array([[[2.56040733e-21, 7.25779588e-15, 1.99342376e-10, 1.11184195e-09,
#           5.92091055e-05, 9.99939799e-01, 9.72097268e-07, 1.13292452e-14,
#           4.43997455e-23, 5.00404492e-33, 0.00000000e+00, 0.00000000e+00,
#           0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
#           0.00000000e+00, 0.00000000e+00, 0.00000000e+00]]])}

Da es sich bei diesem Modell um ein Modell handelt, das zwei Elemente hinzufügt, beträgt die Wahrscheinlichkeit für das fünfte Element fast 1, sodass Sie sehen können, dass es korrekt abgeleitet werden kann.

Da das Ausgabearray "[[[19 Arrays mit Wahrscheinlichkeit]]]" ist, wird auch bestätigt, dass die Form wie beabsichtigt (1,1,19) ist. Ich kann es schaffen

** 7. Überprüfen Sie das Ausgabeergebnis des Modells mit Xcode & App **

Stellen Sie abschließend das Ausgabeergebnis des Modells auf Xcode und überprüfen Sie es mit der Anwendung.

Der vollständige Code ist hier. https://github.com/TokyoYoshida/CoreMLSimpleTest

ViewController.swift


let model = my_model_with_builder()
let inputArray = try! MLMultiArray([2,3])
let inputToModel = my_model_with_builderInput(input1: inputArray)
if let prediction = try? model.prediction(input: inputToModel) {
print(prediction.output2)
try! print(prediction.output2.reshaped(to: [19]))
}

// # Double 1 x 1 x 19 array
// # Double 19 vector
// # [2.422891379885771e-21,7.01752566646674e-15,1.959301054732521e-10,1.089580203839091e-09,5.933549255132675e-05,0.9999396800994873,9.530076567898504e-07,1.087061586308846e-14,4.16250629238845e-23,4.617410135639087e-33,1.401298464324817e-45,1.401298464324817e-45,1.401298464324817e-45,1.401298464324817e-45,1.401298464324817e-45,1.401298464324817e-45,0,0,0]
// 

Sie können sehen, dass dies auch wie beabsichtigt ist. Die Wahrscheinlichkeitszahlen können leicht abweichen, aber keine Sorge, dies liegt an der Umschulung des Modells.

Extra Edition So löschen Sie eine Ebene

Ich habe den Vorgang nicht bestätigt, werde aber auch schreiben, wie die Ebene gelöscht wird.

Löschen Sie die Ebene.

notebook


layers = builder.spec.neuralNetwork.layers
#Holen Sie sich die zweite von der Rückseite der Ebene(activation_18)
item = layers[-2]
#Löschen Sie dieses Element
layers.remove(item)

Wenn Sie sich die Ebeneninformationen ansehen, können Sie sehen, dass sie gelöscht wurden.

notebook


for layer in layers:
  print(layer.name)
# dense_4
# dense_4__activation__
# dense_5
# dense_5__activation__
# dense_6
# Reshape

Schließlich

Hinweis veröffentlicht regelmäßig Informationen zur iOS-Entwicklung. Folgen Sie uns daher. https://note.com/tokyoyoshida

Es wird auch auf Twitter gepostet. https://twitter.com/jugemjugemjugem

Recommended Posts

So bearbeiten Sie eine Ebene mit Core ML Tools
Wie schreibe ich einen Core Mod in Minecraft Forge 1.15.2
Wie man Lombok im Frühling benutzt
So finden Sie May'n in XPath
So blenden Sie die Bildlaufleiste in WebView aus
So führen Sie JUnit in Eclipse aus
Wie man in Ruby auf unbestimmte Zeit iteriert
Wie man Ant in Gradle ausführt
Wie man die Programmierung in 3 Monaten beherrscht
Wie man JAVA in 7 Tagen lernt
So erhalten Sie Parameter in Spark
So installieren Sie Bootstrap in Ruby
Verwendung von InjectorHolder in OpenAM
So installieren Sie jQuery in Rails 6
Wie verwende ich Klassen in Java?
So benennen Sie Variablen in Java
So setzen Sie Lombok in Eclipse
So verketten Sie Zeichenfolgen mit Java
So installieren Sie Swiper in Rails
[swift5] So legen Sie die Farbe hexadezimal fest
So implementieren Sie Suchfunktionen in Rails
So implementieren Sie die Datumsberechnung in Java
So implementieren Sie den Kalman-Filter mit Java
Mehrsprachige Unterstützung für Java Verwendung des Gebietsschemas
So ändern Sie den App-Namen in Rails
Verwendung des benannten Volumes in docker-compose.yml
So fügen Sie ein Video in Rails ein
So standardisieren Sie die Kopfzeile in Thymeleaf
Wie kann ich Spring Tool in Eclipse 4.6.3 einbinden?
So fügen Sie eine JAR-Datei in ScalaIDE hinzu
So führen Sie eine Basiskonvertierung in Java durch
Wie man Parameter in der link_to-Methode hat
Verwendung von Docker in VSCode DevContainer
Verwendung von MySQL im Rails-Tutorial
So beheben Sie das Systemdatum in JUnit
So erzwingen Sie Codierungskonventionen in Java
Einbetten von Janus Graph in Java
[Rails] So konfigurieren Sie das Routing in Ressourcen
So erhalten Sie das Datum mit Java
So implementieren Sie Ranking-Funktionen in Rails
Verwendung von Umgebungsvariablen in RubyOnRails
So implementieren Sie die asynchrone Verarbeitung in Outsystems
So veröffentlichen Sie eine Bibliothek in jCenter
So geben Sie das ID-Attribut in JSF an
Verstehe in 5 Minuten !! Wie man Docker benutzt
So überschreiben Sie Firebase-Daten mit Swift
Verwendung von credentials.yml.enc aus Rails 5.2
So montieren Sie JSON direkt in Jackson
[Für Anfänger] So debuggen Sie mit Eclipse
Verwendung von ExpandableListView in Android Studio
So zeigen Sie Fehlermeldungen auf Japanisch an
Zusammenfassung der Auswahl von Elementen in Selen
So erhalten Sie Keycloak-Anmeldeinformationen in der Interceptor-Klasse