[PYTHON] Temperaturvorhersagemodell läuft auf Edgetpu (Koralle)

Einführung

Ich habe ein Temperaturvorhersagemodell für Tensorflow Lite erstellt, das auf Edgetpu (Koralle) läuft, das mit Raspberry pi4 verbunden ist. Die Tensorflow-Version ist 2.3.1, die Edgetpu-Compiler-Version ist 15.0.340273435 und die Edgetpu-Laufzeitversion ist 2.14.1.

Hauptstrom

  1. Erstellen und trainieren Sie ein eindimensionales CNN-basiertes Modell mit Keras von Tensorflow in Google Colab

  2. Quantisieren Sie das Modell nach dem Training und konvertieren Sie es in ein Tensorflowlite-Modell

  3. Kompilieren Sie mit dem edgetpu-Compiler, um mit edgetpu zu arbeiten

  4. Vorhersage anhand von Testdaten für Raspberry pi4 und Vorhersage der CPU-Temperatur von Raspberry pi4

1. Modellerstellung / Lernen

Datensatzvorbereitung

Auf der Website der Meteorological Agency können Sie vergangene Wetterdaten an einem Ort für einen Tag durchsuchen Wir haben Daten zur Durchschnittstemperatur seit etwa 20 Jahren gesammelt.

Modell erstellen

Unter Verwendung der funktionalen API von Keras wurde ein eindimensionales CNN-basiertes Modell erstellt, das die Durchschnittstemperatur von 30 Tagen als Eingabe verwendet und die Durchschnittstemperatur des nächsten Tages vorhersagt. ..

inputs = tf.keras.Input(shape=(30,1))
cnn1 = tf.keras.layers.Conv1D(filters=1,kernel_size=10,strides=1,activation='relu',input_shape=(30,1))
cnn2 = tf.keras.layers.Conv1D(filters=1,kernel_size=5,strides=1,activation='relu')
cnn3 = tf.keras.layers.Conv1D(filters=1,kernel_size=3,strides=1,activation='relu')
dense1 = tf.keras.layers.Dense(units=8,activation='relu')
dense2 = tf.keras.layers.Dense(units=1)
x = cnn1(inputs)
x = cnn2(x)
x = cnn3(x)
x = tf.keras.layers.Flatten()(x)
x = dense1(x)
outputs = dense2(x)
model = tf.keras.Model(inputs=inputs,outputs=outputs)
model.compile(optimizer="Adam",loss="mean_squared_error",
                               metrics="binary_accuracy")
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_14 (InputLayer)        [(None, 30, 1)]           0         
_________________________________________________________________
conv1d_31 (Conv1D)           (None, 21, 1)             11        
_________________________________________________________________
conv1d_32 (Conv1D)           (None, 17, 1)             6         
_________________________________________________________________
conv1d_33 (Conv1D)           (None, 15, 1)             4         
_________________________________________________________________
flatten_5 (Flatten)          (None, 15)                0         
_________________________________________________________________
dense_24 (Dense)             (None, 8)                 128       
_________________________________________________________________
dense_25 (Dense)             (None, 1)                 9         
=================================================================
Total params: 158
Trainable params: 158
Non-trainable params: 0
_________________________________________________________________
"""

Modelllernen

Ich habe mit einer Losgröße von 50 und einer Epochenzahl von 30 trainiert.

model.fit(x=in_temp,y=out_temp,batch_size=50,epochs=30)

2. Modellquantisierung

Es muss in eine 8-Bit-Ganzzahl quantisiert werden, um auf edgetpu ausgeführt zu werden. Da die Eingabegröße für die Quantisierung festgelegt werden muss, geben Sie "sigantures" an und speichern Sie das Modell einmal. Hier wird die Eingabegröße auf 1x30x1 eingestellt.

opt = tf.function(lambda x:model(x))
BACTH_SIZE = 1
STEPS = 30
INPUT_SIZE = 1
concrete_func = opt.get_concrete_function(tf.TensorSpec([BACTH_SIZE,STEPS,INPUT_SIZE],
                                                        model.inputs[0].dtype,name="inputs")
)
model.save('/content/weather',save_format="tf",signatures=concrete_func)

Dann quantisieren Sie das Modell. Weitere Informationen finden Sie in der Dokumentation von Tensorflow (https://www.tensorflow.org/lite/performance/post_training_integer_quant). in_tempWird das numpy nd-Array beim Training des Modells eingegeben?

conv_data = in_temp[0]
conv_data = conv_data.reshape(1,30,1)

def representative_dataset_gen():
  for i in range(len(conv_data)):
    yield [conv_data[i]]

converter_edgetpu = tf.lite.TFLiteConverter.from_saved_model("/content/weather")
converter_edgetpu.optimizations = [tf.lite.Optimize.DEFAULT]
converter_edgetpu.representative_dataset = representative_dataset_gen
converter_edgetpu.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter_edgetpu.inference_input_type = tf.uint8
converter_edgetpu.inference_output_type = tf.uint8
converter_edgetpu.experimental_new_converter = True
tflite = converter_edgetpu.convert()

Speichern Sie schließlich das Modell.

open("cnn_weather_lite_quantized.tflite","wb").write(tflite)

Kompilieren Sie mit dem edgetpu-Compiler

Installieren Sie den edgetpu-Compiler

Installieren Sie den edgetpu-Compiler in Google Colab. Einzelheiten zur Installationsmethode finden Sie unter Dokumentation.

Direkt, weil die CPU-Architektur x86-64 erfordert, wie in Dokumentation gezeigt, und die CPU-Architektur von Raspberry pi4B ARMv8 ist. Ich glaube nicht, dass es auf Raspberry pi 4 installiert werden kann. (CPU-Architektur von Raspberry pi: https://nw-electric.way-nifty.com/blog/2020/02/post-6c09ad.html)

!curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
!echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
!sudo apt -y update
!sudo apt-get install edgetpu-compiler

Kompilieren Sie mit dem edgetpu-Compiler

Referenz: https://coral.ai/docs/edgetpu/compiler/#usage

!edgetpu_compiler /content/cnn_weather_lite_quantized.tflite

Prognose

Vorausgesagt durch Testdaten

Auf der Website der Meteorological Agency haben wir erneut 30 Tage durchschnittliche tägliche Temperaturdaten erstellt. Dann habe ich den folgenden Code (bei Verwendung von Edgetpu) auf dem Raspberry Pi ausgeführt, um die Temperatur für den nächsten Tag vorherzusagen. Wir haben auch die Ausführungszeit gemessen und die Zeit mit der CPU-Auslastung verglichen. Der Inferenzcode basierte auf dem Abschnitt "Modell in Python laden und ausführen" der Tensorflow-Site. Es wird automatisch ins Japanische übersetzt. Wenn die Übersetzung falsch ist, empfehlen wir, sie auf Englisch zu lesen.

import numpy as np
import pandas as pd
import tflite_runtime.interpreter as tflite
import time

def main(args):
    interpreter = tflite.Interpreter('/home/pi/cnn_weather/cnn_weather_lite_quantized_edgetpu.tflite',
    experimental_delegates=[tflite.load_delegate('libedgetpu.so.1')])
    
    data = pd.read_csv('/home/pi/cnn_weather/test.csv')
    test_data = np.asarray(data.loc[:len(data),"Durchschnittstemperatur"],dtype=np.uint8)
    test_data = test_data.reshape(1,30,1)
    
    start = time.perf_counter()
    
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()
    input_shape = input_details[0]['shape']
    interpreter.set_tensor(input_details[0]['index'],test_data)
    
    interpreter.invoke()
    
    output_data = interpreter.get_tensor(output_details[0]['index'])
    
    end = time.perf_counter()
    
    print("The next day's temperature is " + str(output_data[0,0]) + " degrees Celsius.")
    print("It took " + str((end-start)*1000) + " ms.")
    
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Das Ergebnis wird angezeigt. Die Oberseite ist das Ergebnis der Ausführung mit edgetpu, die Mitte ist das Ergebnis der Ausführung des nicht quantisierten Modells auf der CPU und die Unterseite ist das Ergebnis der Ausführung des quantisierten Modells auf der CPU. Quantifizierung macht es schneller, aber die Verwendung von Edgetpu führt zu langsameren ... Da die Ausführungszeit 2 ms beträgt, kann es länger dauern, edgetpu usw. mit edgetpu aufzurufen. Übrigens können Sie sehen, dass die Genauigkeit bei der Quantisierung erheblich abnimmt. (Die Testdaten stammen von Ende September bis Ende Oktober, und da sie bei etwa 22 ° C beginnen und bei etwa 18 ° C enden, sind 24 ° C und 26 ° C meiner Meinung nach ziemlich falsch.)

pi@raspberrypi:~$ python3 /home/pi/cnn_weather/edgetpu_time.py
The next day's temperature is 24 degrees Celsius.
It took 2.218683000137389 ms.

pi@raspberrypi:~$ python3 /home/pi/cnn_weather/cpu_time.py
The next day's temperature is 17.671713 degrees Celsius.
It took 3.6856149999948684 ms.

pi@raspberrypi:~$ python3 /home/pi/cnn_weather/cpu_quantized_time.py
The next day's temperature is 26 degrees Celsius.
It took 1.4244879994294024 ms.

Vorhersage der CPU-Temperatur

Ich verwende es auf einem kleinen Gerät namens Raspberry pi, also wollte ich so etwas wie eine Echtzeitvorhersage ausprobieren. Ich wollte es anhand der Außentemperatur vorhersagen, aber es scheint schwierig, es selbst zu machen, da es keinen Sensor gibt. Deshalb habe ich versucht, es anhand der CPU-Temperatur vorherzusagen. Ich nahm die CPU-Temperatur jede Sekunde mit $ cat / sys / class / thermic / thermic_zone0 / temp``` und sagte die Temperatur nach 1 Sekunde voraus, wenn 30 Sekunden erfasst wurden. Außerdem gibt `$ cat / sys / class / Thermal / Thermal_zone0 / temp``` den Wert der CPU-Temperatur multipliziert mit 1000 zurück, daher habe ich das Ausgabeergebnis geteilt durch 1000 verwendet.

Unten ist der Code, den ich auf dem Raspberry Pi ausgeführt habe. (Nur der Code bei Verwendung von edgetpu wird angezeigt.)

import numpy as np
import tflite_runtime.interpreter as tflite
import time
import subprocess

def main(args):
    start = time.perf_counter()
    interpreter = tflite.Interpreter('/home/pi/cnn_weather/cnn_weather_lite_quantized_edgetpu.tflite',
    experimental_delegates=[tflite.load_delegate('libedgetpu.so.1')])
    
    data = list()
    for i in range(30):
        res = subprocess.run(['cat', '/sys/class/thermal/thermal_zone0/temp'],
        stdout=subprocess.PIPE)
        get_start = time.perf_counter()
        result = res.stdout.decode('utf-8')
        result = int(result)/1000
        data.append(result)
        print(result,end='℃ ')
        if (i+1)%10 == 0:
            print()
        get_end = time.perf_counter()
        get_time = get_end-get_start
        
        if get_time < 1:
            time.sleep(1-get_time)
        else:
            print("Took " + str(get_time) + " s to get " +  str(i) + "'s temp.")
    
    pre_start = time.perf_counter()
    np_data = np.asarray(data,dtype=np.uint8).reshape(1,30,1)
    
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()
    input_shape = input_details[0]['shape']
    interpreter.set_tensor(input_details[0]['index'],np_data)
    interpreter.invoke()
    
    pred = interpreter.get_tensor(output_details[0]['index'])
    
    pre_end = time.perf_counter()
    pre_time = pre_end - pre_start
    if pre_time < 1:
        print("The cpu's temp will be " + str(pred[0,0]) + "℃ in " + 
        str(1-pre_time) + " s.")
        
        time.sleep(1-pre_time)
        res = subprocess.run(['cat', '/sys/class/thermal/thermal_zone0/temp'],
        stdout=subprocess.PIPE)
        result = res.stdout.decode('utf-8')
        result = int(result)/1000
        print("The cpu's temp is " + str(result) + "℃.")
    else:
        print("The cpu's temp must have been " + str(pred[0,0]) + "℃ " + 
        str(1-pre_time) + " s ago.")
    
    end = time.perf_counter()
    print("Took " + str(end-start) + " s to run this code.")
    
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Das Ergebnis wird angezeigt. Die Oberseite ist bei Verwendung von Edgetpu, die Mitte bei Verwendung eines nicht quantifizierten Modells und die Unterseite bei Verwendung eines quantisierten Modells. Die aufgeführten Temperaturen sind die für die Vorhersage verwendeten CPU-Temperaturdaten. Immerhin hat das quantisierte Modell eine irrelevante Leistung von mehr als 100 ° C. Außerdem dauert die Verwendung von edgetpu nach wie vor einige Zeit. Dieses Mal habe ich die Zeit nicht nur für Inferenz gemessen, sondern auch für den Aufruf von `` `tf.lite.Interpreter```, so dass dieser Teil auch mit edgetpu Zeit in Anspruch nehmen kann.

pi@raspberrypi:~$ python3 /home/pi/cnn_weather/predict_edgetpu.py
63.783℃ 64.757℃ 63.783℃ 63.783℃ 63.296℃ 62.809℃ 63.296℃ 63.296℃ 62.809℃ 62.809℃ 
62.809℃ 63.296℃ 62.322℃ 62.809℃ 63.783℃ 62.809℃ 63.783℃ 63.783℃ 62.322℃ 62.809℃ 
62.322℃ 63.783℃ 62.809℃ 62.322℃ 62.322℃ 62.322℃ 62.322℃ 62.322℃ 62.322℃ 63.296℃ 
The cpu's temp will be 105℃ in 0.9969898569997895 s.
The cpu's temp is 61.835℃.
Took 34.21252226499928 s to run this code.

pi@raspberrypi:~$ python3 /home/pi/cnn_weather/predict_cpu.py
63.783℃ 63.783℃ 63.296℃ 62.809℃ 63.783℃ 63.296℃ 62.809℃ 63.296℃ 62.809℃ 62.322℃ 
62.322℃ 62.322℃ 62.809℃ 62.322℃ 61.835℃ 62.322℃ 62.322℃ 61.348℃ 62.322℃ 62.322℃ 
63.296℃ 61.835℃ 62.322℃ 61.835℃ 61.348℃ 61.348℃ 61.835℃ 62.322℃ 62.809℃ 62.322℃ 
The cpu's temp will be 62.17556℃ in 0.9969654129999981 s.
The cpu's temp is 62.322℃.
Took 31.404364756001087 s to run this code.

pi@raspberrypi:~$ python3 /home/pi/cnn_weather/predict_cpu_quantized.py
63.296℃ 63.296℃ 62.809℃ 62.322℃ 62.322℃ 61.835℃ 61.835℃ 62.322℃ 61.835℃ 62.322℃ 
62.809℃ 62.322℃ 62.809℃ 62.322℃ 60.861℃ 62.322℃ 61.835℃ 61.835℃ 62.322℃ 61.835℃ 
61.835℃ 61.835℃ 61.348℃ 62.322℃ 60.861℃ 61.348℃ 62.322℃ 61.348℃ 61.835℃ 61.348℃ 
The cpu's temp will be 101℃ in 0.9984136980001495 s.
The cpu's temp is 61.835℃.
Took 31.43542323499969 s to run this code.

Schließlich

Ich habe ein Temperaturvorhersagemodell für Tensorflowlite erstellt und ausgeführt, das auf Edgetpu (Koralle) ausgeführt wird, das mit Raspberry pi4 verbunden ist. Die Quantifizierung reduzierte die Genauigkeit erheblich (vielmehr wurde es zu einem Modell, das fast bedeutungslos war), und das Ergebnis war, dass die Ausführungszeit bei Verwendung von edgetpu länger war als bei Verwendung der CPU. Dieses Mal war es vorerst das Ziel, ein Modell mit Edgetpu zu erstellen, anstatt ein Modell mit guter Genauigkeit zu erstellen. Deshalb werde ich vorerst hier enden. Alle diesmal verwendeten Daten-, Code- und Tensorflowlite-Modelle finden Sie unter github.

Vielen Dank für das bisherige Anschauen. Dies ist mein erster Artikel. Wenn Sie Bedenken oder Vorschläge haben, können Sie dies gerne kommentieren.

Beiseite

Ich habe versucht, dasselbe mit LSTM zu tun, bevor ich 1D CNN verwendet habe, aber ich habe einen Fehler wie den in [hier] erhalten (https://github.com/tensorflow/tensorflow/issues/44091). Ich blieb stecken und entschied mich für ein eindimensionales CNN. In Anbetracht des damit verbundenen Problems scheint es derzeit unmöglich zu sein, RNN-basierte Modelle wie LSTM zu quantifizieren. (Die verknüpfte Tensorflow-Version ist 2.2.0, diesmal habe ich 2.3.1 verwendet)

Obwohl es sich nicht um dieselbe Fehleranweisung handelt, scheinen RNN-Systeme wie LSTM die Quantisierung selbst in [Fehler, die in Beziehung zu stehen scheinen] nicht zu unterstützen (https://github.com/tensorflow/tensorflow/issues/35194). Ich wurde gefragt, ob es einen gibt. Außerdem konnte ich es in ein Tensorflow-Lite-Modell konvertieren und mit Raspberry pi im nicht quantisierten Zustand ausführen.

Recommended Posts

Temperaturvorhersagemodell läuft auf Edgetpu (Koralle)
Vorhersagemodellkonstruktion ①