Hallo Habr.
Im
ersten Teil wurde NVIDIA Jetson Nano in Betracht gezogen - ein Board im Raspberry Pi-Formfaktor, das sich auf Performance Computing mit der GPU konzentriert. Es ist Zeit, das Board so zu testen, wie es erstellt wurde - für AI-orientierte Berechnungen.

Überlegen Sie, wie unterschiedliche Aufgaben auf der Tafel ablaufen, z. B. das Klassifizieren von Bildern oder das Erkennen von Fußgängern oder Robben (wo ohne sie). Für alle Tests kann der Quellcode auf dem Desktop, Jetson Nano oder Raspberry Pi ausgeführt werden. Für diejenigen, die interessiert sind, weiter unter dem Schnitt.
Es gibt zwei Möglichkeiten, dieses Board zu verwenden. Das erste besteht darin, Standard-Frameworks wie Keras und Tensorflow auszuführen. Es wird im Prinzip funktionieren, aber wie bereits im ersten Teil zu sehen ist, ist Jetson Nano natürlich einer vollwertigen Desktop- oder Laptop-Grafikkarte unterlegen. Der Benutzer muss die Optimierung des Modells übernehmen. Der zweite Weg besteht darin, vorgefertigte Kurse zu belegen, die mit dem Board geliefert werden. Es ist einfacher und funktioniert "out of the box". Das Minus ist, dass alle Implementierungsdetails in viel größerem Maße verborgen sind. Außerdem müssen Sie custom-sdk studieren und verwenden, was neben diesen Boards nirgendwo anders nützlich sein wird. Wir werden jedoch beide Wege betrachten, beginnend mit dem ersten.
Bildklassifizierung
Betrachten Sie das Problem der Bilderkennung. Dazu verwenden wir das mit Keras gelieferte ResNet50-Modell (dieses Modell war der Gewinner der ImageNet Challenge im Jahr 2015). Um es zu verwenden, reichen ein paar Codezeilen aus.
import tensorflow as tf import numpy as np import time IMAGE_SIZE = 224 IMG_SHAPE = (IMAGE_SIZE, IMAGE_SIZE, 3) resnet = tf.keras.applications.ResNet50(input_shape=IMG_SHAPE) img = tf.contrib.keras.preprocessing.image.load_img('cat.png', target_size=(IMAGE_SIZE, IMAGE_SIZE)) t_start = time.time() img_data = tf.contrib.keras.preprocessing.image.img_to_array(img) x = tf.contrib.keras.applications.resnet50.preprocess_input(np.expand_dims(img_data, axis=0)) probabilities = resnet.predict(x) print(tf.contrib.keras.applications.resnet50.decode_predictions(probabilities, top=5)) print("dT", time.time() - t_start)
Ich habe nicht einmal angefangen, den Code unter dem Spoiler zu entfernen, weil Er ist sehr klein. Wie Sie sehen können, wird die Bildgröße zunächst auf 224 x 224 geändert (dies ist das Eingangsnetzwerkformat). Am Ende erledigt die Vorhersagefunktion die gesamte Arbeit.
Wir machen ein Foto von der Katze und führen das Programm aus.

Ergebnisse:
[[('n02123045', 'tabby', 0.765179), ('n02123159', 'tiger_cat', 0.19059166), ('n02124075', 'Egyptian_cat', 0.013605555), ('n04493381', 'tub', 0.0025916891), ('n04553703', 'washbasin', 0.0021566998)]]
Noch einmal, verärgert über seine Englischkenntnisse (ich frage mich, wie viele Nicht-Muttersprachler wissen, was „Tabby“ ist?), Überprüfte ich die Ausgabe mit dem Wörterbuch. Ja, alles funktioniert.
Die Ausführungszeit des PC-Codes betrug
0,5 s für Berechnungen auf der CPU und 2 s (!) Für Berechnungen auf der GPU. Dem Protokoll nach zu urteilen, liegt das Problem entweder im Modell oder in Tensorflow, aber beim Start versucht der Code, viel Speicher zuzuweisen, und es werden mehrere Warnungen der Form "Allocator (GPU_0_bfc) hat nicht genügend Speicher, um 2.13GiB mit freed_by_count = 0 zuzuweisen" angezeigt. . Dies ist eine Warnung und kein Fehler, der Code funktioniert, aber viel langsamer als er sollte.
Auf Jetson Nano ist es immer noch langsamer:
2,8 c auf der CPU und
18,8 c auf der GPU, während die Ausgabe folgendermaßen aussieht:

Im Allgemeinen ist dies sogar 3s pro Bild noch nicht in Echtzeit. Das Festlegen der Option gpu_options.allow_growth, die für den Stapelüberlauf empfohlen wird, hilft nicht. Wenn jemand einen anderen Weg kennt, schreiben Sie in die Kommentare.
Bearbeiten : Wie in den Kommentaren angegeben, dauert der erste Start des Tensorflusses immer lange und es ist falsch, die Zeit damit zu messen. In der Tat sind die Ergebnisse bei der Verarbeitung der zweiten und der nachfolgenden Dateien viel besser - 0,6 Sekunden ohne GPU und 0,2 Sekunden mit einer GPU. Auf dem Desktop beträgt die Geschwindigkeit jedoch 2,0 s bzw. 0,05 s.
Eine praktische Funktion von ResNet50 ist, dass beim ersten Start das gesamte Modell auf die Festplatte (ca. 100 MB) gepumpt wird und der Code dann völlig autonom ohne Registrierung und SMS arbeitet. Das ist besonders schön, da die meisten modernen KI-Dienste nur auf dem Server funktionieren und das Gerät ohne Internet zu einem "Kürbis" wird.
Katzen gegen Hunde
Betrachten Sie das folgende Problem. Mit Keras erstellen wir ein neuronales Netzwerk, das zwischen Katzen und Hunden unterscheiden kann. Es wird ein Faltungs-Neuronales Netzwerk (CNN - Convolutional Neural Network) sein, wir werden das Netzwerkdesign aus
dieser Veröffentlichung übernehmen. Das Paket tensorflow_datasets enthält bereits einen Trainingssatz mit Bildern von Katzen und Hunden, sodass Sie sie nicht selbst fotografieren müssen.
Wir laden eine Reihe von Bildern und teilen sie in drei Blöcke auf - Training, Verifikation und Test. Wir "normalisieren" jedes Bild und bringen die Farben in den Bereich 0..1.
import tensorflow as tf from tensorflow.keras import layers import tensorflow_datasets as tfds from keras.preprocessing import image import numpy as np import time IMAGE_SIZE = 64 IMG_SHAPE = (IMAGE_SIZE, IMAGE_SIZE, 3) splits = tfds.Split.TRAIN.subsplit(weighted=(80, 10, 10)) (cat_train, cat_valid, cat_test), info = tfds.load('cats_vs_dogs', split=list(splits), with_info=True, as_supervised=True) label_names = info.features['label'].int2str def pre_process_image(image, label): image = tf.cast(image, tf.float32) image = image / 255.0
Wir schreiben die Funktion der Erzeugung eines Faltungsnetzwerks.
def custom_model():
Jetzt können wir mit unserem „Cat-Dog“ -Kit ein Netzwerktraining durchführen. Das Training dauert lange (20 Minuten auf der GPU und 1-2 Stunden auf der CPU), daher speichern wir das Modell am Ende in einer Datei.
tl_model = custom_model() t_start = time.time() tl_model.fit(train_batch, steps_per_epoch=8000, epochs=2, validation_data=validation_batch, validation_steps=10, callbacks=None) print("Training done, dT:", time.time() - t_start) print(tl_model.summary()) validation_steps = 20 loss0, accuracy0 = tl_model.evaluate(validation_batch, steps=validation_steps) print("Loss: {:.2f}".format(loss0)) print("Accuracy: {:.2f}".format(accuracy0)) tl_model.save("dog_cat_model.h5")
Der Versuch, das Training direkt auf dem Jetson Nano zu starten, schlug übrigens fehl - nach 5 Minuten war das Board überhitzt und hing. Für ressourcenintensive Berechnungen ist ein Kühler für das Board erforderlich, obwohl es im Großen und Ganzen keinen Sinn macht, solche Aufgaben direkt auf Jetson Nano auszuführen - das Modell kann auf einem PC trainiert werden und die fertig gespeicherte Datei kann auf Nano verwendet werden.
Hier kam eine weitere Gefahr heraus: Die Tensowflow-Bibliothek der Version 14 wurde auf dem PC installiert, und die neueste Version für Jetson Nano ist bisher 13. Und das in der 14. Version gespeicherte Modell wurde in der 13. Version nicht gelesen. Ich musste dieselben Versionen mit pip installieren.
Schließlich können wir das Modell aus einer Datei laden und damit Bilder erkennen.
def predict_model(model, image_file): img = image.load_img(image_file, target_size=(IMAGE_SIZE, IMAGE_SIZE)) t_start = time.time() img_arr = np.expand_dims(img, axis=0) result = model.predict_classes(img_arr) print("Result: {}, dT: {}".format(label_names(result[0][0]), time.time() - t_start)) model = tf.keras.models.load_model('dog_cat_model.h5') predict_model(model, "cat.png") predict_model(model, "dog1.png") predict_model(model, "dog2.png")
Das Foto der Katze wurde genauso verwendet, aber für den "Hund" -Test wurden 2 Bilder verwendet:

Der erste hat richtig geraten, und der zweite hatte zuerst Fehler und das neuronale Netzwerk dachte, es sei eine Katze. Ich musste die Anzahl der Trainingsiterationen erhöhen. Allerdings hätte ich wahrscheinlich beim ersten Mal einen Fehler gemacht;)
Die Ausführungszeit auf Jetson Nano erwies sich als recht kurz - das allererste Foto wurde in 0,3 Sekunden verarbeitet, aber alle nachfolgenden Fotos waren viel schneller, anscheinend werden die Daten im Speicher zwischengespeichert.

Im Allgemeinen können wir davon ausgehen, dass in solch einfachen neuronalen Netzen die Geschwindigkeit der Karte auch ohne Optimierungen völlig ausreicht. 100 fps sind ein Wert, der selbst für Videos in Echtzeit ausreicht.
Fazit
Wie Sie sehen, können sogar Standardmodelle von Keras und Tensorflow auf Nano verwendet werden, wenn auch mit unterschiedlichem Erfolg - etwas funktioniert, etwas nicht. Die Ergebnisse können jedoch verbessert werden, Anweisungen zur Optimierung des Modells und zur Reduzierung der Speichergröße können hier gelesen
werden .
Aber zum Glück haben die Hersteller dies bereits für uns getan. Wenn die Leser immer noch Interesse haben, wird der letzte Teil
vorgefertigten Bibliotheken gewidmet sein, die für die Arbeit mit Jetson Nano optimiert sind.