Tensorflow Lite, Skript mit EdgeTPU ohne Beschleunigung

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Benutzeravatar
joernius
User
Beiträge: 31
Registriert: Donnerstag 11. Juni 2020, 13:47
Wohnort: Dresden
Kontaktdaten:

Hallo an alle,

ich streife nun interessante Gebiete, in denen meine Kenntnisse leider rudimentär sind. Mein kleines Projekt ist Bilderkennung.
Ich habe nun mit Googel "Teachable Machines" eine Model erstellt
https://teachablemachine.withgoogle.com ... kNxYfxmZM/
um Singvögel von Katzen und Tauben zu unterscheiden und dann Störenfriede per Wasserstrahl vom dem Futterhaus zu vertreiben.

Dann habe ebenfalls mangels Programmierkenntnisse eine Auswertung gesucht und ein Python-Skript für Tensorflow Lite mit TPU-Unterstützung gefunden,
https://github.com/google-coral/tflite/ ... sification
welche mit dem von der Google-Seite generierten Model funktioniert und gut per Bash-Skript auswertbar ist:

Code: Alles auswählen

TIER=`python3 classify_image.py --model tflite.tpu_model/model_edgetpu.tflite --labels tflite.tpu_model/labels.txt --input html/usbcambild.jpg |tail -1|cut -d: -f1`
Leider habe ich keine TFLite-Skript ohne diese Co-Prozessor-Abhängigkeit gefunden. Mit leider meine ich, dieser Coral-Google-Accelator beschleunigt zwar die Erkennung, aber er verdoppelt dabei ungefähr die Hardware-Kosten.

Nun meine Frage an die Python-Profis, welche sich mit dieser Materie auskennen: Wie kann dieses Skript (classify_image.py) modifiziert werden, dass es auch ohne dem Coral-Accelator funktioniert?

Code: Alles auswählen

 
# Lint as: python3
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
r"""Example using TF Lite to classify a given image using an Edge TPU.
   To run this code, you must attach an Edge TPU attached to the host and
   install the Edge TPU runtime (`libedgetpu.so`) and `tflite_runtime`. For
   device setup instructions, see g.co/coral/setup.
   Example usage (use `install_requirements.sh` to get these files):
   ```
   python3 classify_image.py \
     --model models/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite  \
     --labels models/inat_bird_labels.txt \
     --input images/parrot.jpg
   ```
"""

import argparse
import time

from PIL import Image

import classify
import tflite_runtime.interpreter as tflite
import platform

EDGETPU_SHARED_LIB = {
  'Linux': 'libedgetpu.so.1',
  'Darwin': 'libedgetpu.1.dylib',
  'Windows': 'edgetpu.dll'
}[platform.system()]


def load_labels(path, encoding='utf-8'):
  """Loads labels from file (with or without index numbers).
  Args:
    path: path to label file.
    encoding: label file encoding.
  Returns:
    Dictionary mapping indices to labels.
  """
  with open(path, 'r', encoding=encoding) as f:
    lines = f.readlines()
    if not lines:
      return {}

    if lines[0].split(' ', maxsplit=1)[0].isdigit():
      pairs = [line.split(' ', maxsplit=1) for line in lines]
      return {int(index): label.strip() for index, label in pairs}
    else:
      return {index: line.strip() for index, line in enumerate(lines)}


def make_interpreter(model_file):
  model_file, *device = model_file.split('@')
  return tflite.Interpreter(
      model_path=model_file,
      experimental_delegates=[
          tflite.load_delegate(EDGETPU_SHARED_LIB,
                               {'device': device[0]} if device else {})
      ])


def main():
  parser = argparse.ArgumentParser(
      formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  parser.add_argument(
      '-m', '--model', required=True, help='File path of .tflite file.')
  parser.add_argument(
      '-i', '--input', required=True, help='Image to be classified.')
  parser.add_argument(
      '-l', '--labels', help='File path of labels file.')
  parser.add_argument(
      '-k', '--top_k', type=int, default=1,
      help='Max number of classification results')
  parser.add_argument(
      '-t', '--threshold', type=float, default=0.0,
      help='Classification score threshold')
  parser.add_argument(
      '-c', '--count', type=int, default=5,
      help='Number of times to run inference')
  args = parser.parse_args()

  labels = load_labels(args.labels) if args.labels else {}

  interpreter = make_interpreter(args.model)
  interpreter.allocate_tensors()

  size = classify.input_size(interpreter)
  image = Image.open(args.input).convert('RGB').resize(size, Image.ANTIALIAS)
  classify.set_input(interpreter, image)

  print('----INFERENCE TIME----')
  print('Note: The first inference on Edge TPU is slow because it includes',
        'loading the model into Edge TPU memory.')
  for _ in range(args.count):
    start = time.perf_counter()
    interpreter.invoke()
    inference_time = time.perf_counter() - start
    classes = classify.get_output(interpreter, args.top_k, args.threshold)
    print('%.1fms' % (inference_time * 1000))

  print('-------RESULTS--------')
  for klass in classes:
    print('%s: %.5f' % (labels.get(klass.id, klass.id), klass.score))


if __name__ == '__main__':
  main()

In diesem Skript kommt noch eine Abhängigkeit von einem anderen Skript (classify.py), aber ich glaube dort gibt ews keinen Bezug zum Co-Prozessor:

Code: Alles auswählen


# Lint as: python3
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Functions to work with classification models."""

import collections
import operator
import numpy as np

Class = collections.namedtuple('Class', ['id', 'score'])


def input_details(interpreter, key):
  """Returns input details by specified key."""
  return interpreter.get_input_details()[0][key]


def input_size(interpreter):
  """Returns input image size as (width, height) tuple."""
  _, height, width, _ = input_details(interpreter, 'shape')
  return width, height


def input_tensor(interpreter):
  """Returns input tensor view as numpy array of shape (height, width, 3)."""
  tensor_index = input_details(interpreter, 'index')
  return interpreter.tensor(tensor_index)()[0]


def output_tensor(interpreter, dequantize=True):
  """Returns output tensor of classification model.
  Integer output tensor is dequantized by default.
  Args:
    interpreter: tflite.Interpreter;
    dequantize: bool; whether to dequantize integer output tensor.
  Returns:
    Output tensor as numpy array.
  """
  output_details = interpreter.get_output_details()[0]
  output_data = np.squeeze(interpreter.tensor(output_details['index'])())

  if dequantize and np.issubdtype(output_details['dtype'], np.integer):
    scale, zero_point = output_details['quantization']
    return scale * (output_data - zero_point)

  return output_data


def set_input(interpreter, data):
  """Copies data to input tensor."""
  input_tensor(interpreter)[:, :] = data


def get_output(interpreter, top_k=1, score_threshold=0.0):
  """Returns no more than top_k classes with score >= score_threshold."""
  scores = output_tensor(interpreter)
  classes = [
      Class(i, scores[i])
      for i in np.argpartition(scores, -top_k)[-top_k:]
      if scores[i] >= score_threshold
  ]
  return sorted(classes, key=operator.itemgetter(1), reverse=True)

Vielen Dank für Eure Aufmerksamkeit :-)
Grúße Jörn
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@joernius: Braucht das denn wirklich zwingend eine die extra Hardware? Ansonsten musst Du eben ganz normal Tensorflow verwenden.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
joernius
User
Beiträge: 31
Registriert: Donnerstag 11. Juni 2020, 13:47
Wohnort: Dresden
Kontaktdaten:

Das Projekt sollte mit einem Raspberry Pi funktionieren.

Angefangen hatte ich mit Tensorflow. Auf meinem PC mit NVidia GA dauerte eine Erkennung ca. 6 Sekunden, auf einen Raspberry so 50 Sekunden. Das ist aber zu lange.

Dann die Idee, die Bilder auf eine externe 1blu-Server laufen zu lassen war mit 15 Sekunden auch nicht überwältigend.
Mit Tensorflow Lite und dem Coral bin ich bei 5 Sekunden pro Bildauswertung.

Ich schätze mal aufgrund eines Tests mit Objekterkennung, dass der Accelator den Vorgang zwischen Faktor 2 bis 3 beschleunigt.
Ich möchte nun die Bilderkennung auf dem Raspberry Pi ohne dem Co-Prozessor testen. Aber leider kein Skript dafür gefunden.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@joernius: Ich dachte das hast Du bereits gemacht und das hat 50 Sekunden gedauert‽
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
joernius
User
Beiträge: 31
Registriert: Donnerstag 11. Juni 2020, 13:47
Wohnort: Dresden
Kontaktdaten:

Die Erkennung mit Tensorflow dauerte 50 Sekunden auf dem Raspberry Pi V3.
Für Tensorflow Lite suche ich das Skript. Das ist leider nicht kompatibel. Genau wie Bilderkennung und Objekterkennung.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@joernius: Bei „mit Tensorflow“ meinte ich natürlich mit dem Lite aus dem Tensorflow-Package statt dem Lite aus diesem Modul das die Extrahardware braucht.

Also statt ``import tflite_runtime.interpreter as tflite`` das `tflite`-Modul vom normalen Tensorflow. Und dann ohne die `experimental_delegates` beim erstellen des `Interpreter`-Objekts. Falls da nicht noch andere Abhängigkeiten sind, sollte das doch ausreichen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was bringt es denn, 3-mal schneller zu sein? 15 statt 50 Sekunden heißt immer noch “Taube rein, Taube raus”. Oder Katze.

Das TF lite so substantiell schneller auf der generischen PI Hardware ist, ist auch eher nicht zu erwarten. Siehe https://www.hackster.io/news/benchmarki ... f51b796796
Benutzeravatar
joernius
User
Beiträge: 31
Registriert: Donnerstag 11. Juni 2020, 13:47
Wohnort: Dresden
Kontaktdaten:

Danke für die Antwort. Hatte ich versucht zu probieren, war aber, wahrscheinlich wegen Syntaxfehler bei mir nie erfolgreich.
Hast Du Zeit, mir die austauchbaren Zeilen so darzustellen, dass ein Nichtprogrammierer damit zurecht kommt?
Benutzeravatar
joernius
User
Beiträge: 31
Registriert: Donnerstag 11. Juni 2020, 13:47
Wohnort: Dresden
Kontaktdaten:

@ Das TF lite so substantiell schneller auf der generischen PI Hardware ist, ist auch eher nicht zu erwarten. Siehe..

Ich hatte bei der Objekterkennung beim puren PI ein Ergebnis von 2 ..3 FPS, mit Coral 8..9 FPS.
Bei der Bilderkennung mit Coral ca. 5 Sekunden pro Bild. Warum sollte ich annehmen, dass das Verhältnis anders ist?

Update
Die Info in dem Link zeigt schon ein Verhältnis TF/TFLite vom 1: 1,7. Allerdings PI 4. Weiß aber nicht, ob dieser Benchmark genau die Umstände dieser Bilderkennung abdeckt. Dann würde der Coprozessor bei Bilderkennung und Objekterkennung unterschiedliche Leistungsgewinne bringen.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weil Coral spezialisierte Hardware ist, über die der PI nicht verfügt. Und wenn es jetzt 50 Sekunden dauert, und dann 15 - was ist dann faktisch gewonnen? Jenseits eines benchmarks? Sind die Tauben altersschwach?
Benutzeravatar
joernius
User
Beiträge: 31
Registriert: Donnerstag 11. Juni 2020, 13:47
Wohnort: Dresden
Kontaktdaten:

Meine Motivation ist, das Programm in einer Zeit unter 20 Sekunden ohne Coprozessor laufen zu lassen.

Es geht also nicht um die Fitness der Tauben, sondern wie ich die Definition

Code: Alles auswählen

def make_interpreter(model_file):
  model_file, *device = model_file.split('@')
  return tflite.Interpreter(
      model_path=model_file,
      experimental_delegates=[
          tflite.load_delegate(EDGETPU_SHARED_LIB,
                               {'device': device[0]} if device else {})
      ])
ohne Fehler substituiere, so dass keine TPU benötigt wird.

So in der Art wie folgender Schnipsel, welchen ich bei
fand

Code: Alles auswählen

def __init__(self):
        edge_tpu_delegate = None
        try:
            edge_tpu_delegate = load_delegate('libedgetpu.so.1.0')
        except ValueError:
            print("No EdgeTPU detected. Falling back to CPU.")
        
        if edge_tpu_delegate is None:
            self.interpreter = tflite.Interpreter(
                model_path='/cpu_model.tflite')
        else:
            self.interpreter = tflite.Interpreter(
                model_path='/edgetpu_model.tflite',
                experimental_delegates=[edge_tpu_delegate])
        
        self.interpreter.allocate_tensors()

        self.tensor_input_details = self.interpreter.get_input_details()
        self.tensor_output_details = self.interpreter.get_output_details()  
mal sehen, ob ich es hinbekomme, dieses anzupassenn ohne dass es Fehlermeldungen hagelt.

Für syntaktische Anpassungsvorschläge bin ich natürlich dankbar.
Benutzeravatar
joernius
User
Beiträge: 31
Registriert: Donnerstag 11. Juni 2020, 13:47
Wohnort: Dresden
Kontaktdaten:

Dank der Antwort von _blackjack_ aus localhost ist dieser Thread gelöst.

Bisher hatte ich noch nie Glück, wenn ich etwas in einem Python-Skript editierte, mir unbegreifliche Fehlermeldungen waren da immer im Angebot.
Aber das Auskommentieren "experimental_delegates"-Definitionen erlaubten ein normales tflite-model.

Nun aber wieder mit einem Warum: Eine Änderung der Geschwindigkeit kann ich nicht feststellen!

Der Coral-Accelator hat hier keinen spürbaren Einfluss auf die Geschwindigkeit der Bildauswertung, der Unterschied von Tensorflow zu Tensorflow Lite ist wie 10:1.
Antworten