TinyML。ニューラルネットワークの圧縮

今、プログラマーは難しい課題に直面しています-たとえば、ブレスレットにニューラルネットワークのような面倒な構造を実装する方法は?モデルの消費電力を最適化する方法は?そのような最適化の代償は何ですか、そしてモデルを小さなデバイスに導入することがどれほど正当化されるか、そしてなぜそれなしでは実行できないのか。





そして、用途は何ですか?

高価な産業用センサー(毎秒1000回の測定、温度センサー、振動測定、10 kmを超えるデータ送信、強力なプロセッサー)を想像してみましょう。毎秒2,000万回の操作です。その仕事は、機器の故障を防ぐために、温度、振動、および他のパラメーターの値に関するデータをサーバーに送信することです。しかし、ここに不運があります-彼によって送信されたデータの99%は役に立たない、それから-電気の純損失。そして、そのようなセンサーは何十、何百も生産されている可能性があります。 





, -   ? ? , ?     , " " " !"  TinyML.





真ん中に非常に奇妙なピークが見えますか? 楽器の読みを見ている人でも気づきにくいのですが、MLモデルなら簡単に対応でき、その瞬間を「逃さない」
? , , " "

, , . "" : , , , , ..





クラウドとは対照的に、組み込みAIはデバイス自体で実行されます
, embedded ("") AI

- - . , , WiFi, Bluetooth .





- - . - , " ".





- - . , . , , ... . , ( - TinyML).





- - . - , , .





- - , int , float - .





Quantization

, . - , . , 32 . , 8 ? , .





- 1 . . , .





? . .





この場合の行列の乗算は「少し」異なって見えます
""

, , . , .





#     
x_values = np.random.uniform(
    low=0, high=2*math.pi, size=1000).astype(np.float32)

# 
np.random.shuffle(x_values)

y_values = np.sin(x_values).astype(np.float32)

#  ,   "   "
y_values += 0.1 * np.random.randn(*y_values.shape)

plt.plot(x_values, y_values, 'b.')
plt.show()
      
      



. , ( , ).





!





#   
model = tf.keras.Sequential()

model.add(keras.layers.Dense(16, activation='relu', input_shape=(1,)))

model.add(keras.layers.Dense(16, activation='relu'))

model.add(keras.layers.Dense(1))

model.compile(optimizer='adam', loss="mse", metrics=["mae"])

#  
history = model.fit(x_train, y_train, epochs=500, batch_size=64,
                    validation_data=(x_validate, y_validate))

# 
model.save(MODEL_TF)
      
      



, :





結果として得られる品質は、私たちの実験にとっては問題ありません。

, . "" . TFLiteConverter, .





#      TensorFlow Lite   
converter = tf.lite.TFLiteConverter.from_saved_model(MODEL_TF)
model_no_quant_tflite = converter.convert()

# 
open(MODEL_NO_QUANT_TFLITE, "wb").write(model_no_quant_tflite)

#      TensorFlow Lite  
def representative_dataset():
  for i in range(500):
    yield([x_train[i].reshape(1, 1)])

converter.optimizations = [tf.lite.Optimize.DEFAULT]

#  ,         int
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8

#    ,    
converter.representative_dataset = representative_dataset
model_tflite = converter.convert()

open(MODEL_TFLITE, "wb").write(model_tflite)
      
      



: , TensorFlow Lite , TensorFlow Lite . , .





pd.DataFrame.from_records(
    [["TensorFlow", f"{size_tf} bytes", ""],
     ["TensorFlow Lite", f"{size_no_quant_tflite} bytes ", f"(reduced by {size_tf - size_no_quant_tflite} bytes)"],
     ["TensorFlow Lite Quantized", f"{size_tflite} bytes", f"(reduced by {size_no_quant_tflite - size_tflite} bytes)"]],
     columns = ["Model", "Size", ""], index="Model")
      
      



, , TensorFlow Lite 32% , 40% ! , , ?





, . , , !





Python , , , ? , . ! Ubuntu, Windows - .





#  xxd
!apt-get update && apt-get -qq install xxd
#   
!xxd -i {MODEL_TFLITE} > {MODEL_TFLITE_MICRO}
#   
REPLACE_TEXT = MODEL_TFLITE.replace('/', '_').replace('.', '_')
!sed -i 's/'{REPLACE_TEXT}'/g_model/g' {MODEL_TFLITE_MICRO}
#  ,       C  
!cat {MODEL_TFLITE_MICRO}
      
      



, 400.





, , , , . ( ) . , , - .






//   ,     

  float x = 0.0f;
  float y_true = sin(x);

  // 
  tflite::MicroErrorReporter micro_error_reporter;

  //    
  const tflite::Model* model = ::tflite::GetModel(g_model);
      
      



. ? , : , . - , . , .





, :





  x = 5.f;
  y_true = sin(x);
  input->data.int8[0] = x / input_scale + input_zero_point;
  interpreter.Invoke();
  y_pred = (output->data.int8[0] - output_zero_point) * output_scale;
  TF_LITE_MICRO_EXPECT_NEAR(y_true, y_pred, epsilon);
      
      



Edge Impulse

Edge Impulse , TinyML.





, , . , , , - .





- TinyML . ( , ..) . 20% , , .





, NoML Community - https://t.me/noml_community.








All Articles