用Arduino玩人工智能,TensorFlow真香!

经常玩电子的朋友都知道Arduino是一个内存只有几十K的单片机,刚开始的时候我也觉得用Arduino来玩TensorFlow简直是天方夜谭,但是真是不得不佩服谷歌的强大,竟然专门为移动设备和LOT设备提供了专项适配,下面就跟着波波来学习下如何利用Arduino玩转Tensorflow吧。

用Arduino玩转Tensorflow

文档地址:https://tensorflow.google.cn/lite/?hl=zh_cn

分享文档地址的作用是想学的朋友可以通过文档深入学习,毕竟本篇笔记波波只记录如何入门的过程,并不深入研究。

除了文档之外,TensorFlow的类库,谷歌已经为我们准备好了,大家可以打开编程工具找到【工具】->【管理库】如下图所示:

用Arduino玩转Tensorflow

搜索【tensorflow】点击安装即可。想手动安装的朋友也可以下载github上面的类库。

因为万能的特色防火墙,大家在访问这些资源的时候可能会速度较慢,习惯就好了,耐心等待......

一切准备就绪后,就开始我们今天的HelloWorld吧,这个示例主要用来预测闪烁LED,示例源码如下:

  1. #include <TensorFlowLite.h>
  2. #include "main_functions.h"
  3. #include "constants.h"
  4. #include "output_handler.h"
  5. #include "sine_model_data.h"
  6. #include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h"
  7. #include "tensorflow/lite/experimental/micro/micro_error_reporter.h"
  8. #include "tensorflow/lite/experimental/micro/micro_interpreter.h"
  9. #include "tensorflow/lite/schema/schema_generated.h"
  10. #include "tensorflow/lite/version.h"
  11. // Globals, used for compatibility with Arduino-style sketches.
  12. namespace {
  13. tflite::ErrorReporter* error_reporter = nullptr;
  14. const tflite::Model* model = nullptr;
  15. tflite::MicroInterpreter* interpreter = nullptr;
  16. TfLiteTensor* input = nullptr;
  17. TfLiteTensor* output = nullptr;
  18. int inference_count = 0;
  19. // Create an area of memory to use for input, output, and intermediate arrays.
  20. // Finding the minimum value for your model may require some trial and error.
  21. constexpr int kTensorArenaSize = 2 * 1024;
  22. uint8_t tensor_arena[kTensorArenaSize];
  23. }  // namespace
  24. // The name of this function is important for Arduino compatibility.
  25. void setup() {
  26.   // Set up logging. Google style is to avoid globals or statics because of
  27.   // lifetime uncertainty, but since this has a trivial destructor it's okay.
  28.   // NOLINTNEXTLINE(runtime-global-variables)
  29.   static tflite::MicroErrorReporter micro_error_reporter;
  30.   error_reporter = &micro_error_reporter;
  31.   // Map the model into a usable data structure. This doesn't involve any
  32.   // copying or parsing, it's a very lightweight operation.
  33.   model = tflite::GetModel(g_sine_model_data);
  34.   if (model->version() != TFLITE_SCHEMA_VERSION) {
  35.     error_reporter->Report(
  36.         "Model provided is schema version %d not equal "
  37.         "to supported version %d.",
  38.         model->version(), TFLITE_SCHEMA_VERSION);
  39.     return;
  40.   }
  41.   // This pulls in all the operation implementations we need.
  42.   // NOLINTNEXTLINE(runtime-global-variables)
  43.   static tflite::ops::micro::AllOpsResolver resolver;
  44.   // Build an interpreter to run the model with.
  45.   static tflite::MicroInterpreter static_interpreter(
  46.       model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
  47.   interpreter = &static_interpreter;
  48.   // Allocate memory from the tensor_arena for the model's tensors.
  49.   TfLiteStatus allocate_status = interpreter->AllocateTensors();
  50.   if (allocate_status != kTfLiteOk) {
  51.     error_reporter->Report("AllocateTensors() failed");
  52.     return;
  53.   }
  54.   // Obtain pointers to the model's input and output tensors.
  55.   input = interpreter->input(0);
  56.   output = interpreter->output(0);
  57.   // Keep track of how many inferences we have performed.
  58.   inference_count = 0;
  59. }
  60. // The name of this function is important for Arduino compatibility.
  61. void loop() {
  62.   // Calculate an x value to feed into the model. We compare the current
  63.   // inference_count to the number of inferences per cycle to determine
  64.   // our position within the range of possible x values the model was
  65.   // trained on, and use this to calculate a value.
  66.   float position = static_cast<float>(inference_count) /
  67.                    static_cast<float>(kInferencesPerCycle);
  68.   float x_val = position * kXrange;
  69.   // Place our calculated x value in the model's input tensor
  70.   input->data.f[0] = x_val;
  71.   // Run inference, and report any error
  72.   TfLiteStatus invoke_status = interpreter->Invoke();
  73.   if (invoke_status != kTfLiteOk) {
  74.     error_reporter->Report("Invoke failed on x_val: %f\n",
  75.                            static_cast<double>(x_val));
  76.     return;
  77.   }
  78.   // Read the predicted y value from the model's output tensor
  79.   float y_val = output->data.f[0];
  80.   // Output the results. A custom HandleOutput function can be implemented
  81.   // for each supported hardware target.
  82.   HandleOutput(error_reporter, x_val, y_val);
  83.   // Increment the inference_counter, and reset it if we have reached
  84.   // the total number per cycle
  85.   inference_count += 1;
  86.   if (inference_count >= kInferencesPerCycle) inference_count = 0;
  87. }

当然了由于一些限制,只能玩一些简单的语音、图像识别之类的,和其他基于数据模型的边缘计算。但是这已经很不容易了,可以为初级玩家打开一扇通往人工智能的大门。

更多精彩的创意,大家可以自由发挥,波波的分享先这么多,回头有时间了再分享我的DIY作品哈。

 

你想把广告放到这里吗?

发表评论

您必须 登录 才能发表留言!