IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> TensorFlow Lite for Microcontrollers -> 正文阅读

[人工智能]TensorFlow Lite for Microcontrollers

使用方法

参考tensorflow/lite/micro/examples/xxx 目录下的使用方法, 以hello_world为例,

文件hello_world_test.cc

1. 创建MicroErrorReporter object

tflite::MicroErrorReporter micro_error_reporter;

2.? 有tflite model文件得到 tflite::Modle 结构体

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

3. 创建OpsResolver对象

这里是创建包含所有算子的对象

tflite::AllOpsResolver resolver;

如果是根据实际使用的算子创建OpsResolver, 使用

? ? static tflite::MicroMutableOpResolver<5> micro_op_resolver;?
? ? micro_op_resolver.AddConv2D();
? ? micro_op_resolver.AddDepthwiseConv2D();
? ? micro_op_resolver.AddFullyConnected();
? ? micro_op_resolver.AddMaxPool2D();
? ? micro_op_resolver.AddSoftmax();
?

4. 提供一段连续的内存,用于model的内存(placement new)

uint8_t tensor_arena[tensor_arena_size];

5. 创建MicroInterpreter对象

? MicroInterpreter(const Model* model, const MicroOpResolver& op_resolver,
? ? ? ? ? ? ? ? ? ?uint8_t* tensor_arena, size_t tensor_arena_size,
? ? ? ? ? ? ? ? ? ?ErrorReporter* error_reporter,
? ? ? ? ? ? ? ? ? ?tflite::Profiler* profiler = nullptr);
构造函数的参数类型是基类,而创建对象的参数是派生类的引用或指针,实现了多态性

tflite::MicroInterpreter interpreter(
? ? ? ? model, resolver, tensor_arena, tensor_arena_size, &micro_error_reporter);

6. 为所有的Tensor/ScratchBuffer分配内存,为所有支撑的变量分配内存等

interpreter.AllocateTensors();

//因内存的大小是个超参数常量,可以通过使用情况调整下,如参考arena_used_bytes()

interpreter.arena_used_bytes();

7. 得到输入对应的Tensor

TfLiteTensor* input = interpreter.input(0);

检测input tensor的一些属性

TF_LITE_MICRO_EXPECT_EQ(2, input->dims->size);
// The value of each element gives the length of the corresponding tensor.
// We should expect two single element tensors (one is contained within the

// other).
TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[0]);
TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[1]);
// The input is a 32 bit floating point value
TF_LITE_MICRO_EXPECT_EQ(kTfLiteFloat32, input->type);

8. Provide an input value赋值input tensor


input->data.f[0] = 0.;

9. 进行推断

interpreter.Invoke();

10. 得到推断结果

// Obtain a pointer to the output tensor and make sure it has the
// properties we expect. It should be the same as the input tensor.
TfLiteTensor* output = interpreter.output(0);

//检测推断结果的属性
TF_LITE_MICRO_EXPECT_EQ(2, output->dims->size);
TF_LITE_MICRO_EXPECT_EQ(1, output->dims->data[0]);
TF_LITE_MICRO_EXPECT_EQ(1, output->dims->data[1]);
TF_LITE_MICRO_EXPECT_EQ(kTfLiteFloat32, output->type);
?
// Obtain the output value from the tensor
float value = output->data.f[0];

按上面的步骤,分析下代码实现, 尽量明白一个 AIEngine reference的实现。

ErrorReporter

ErrorReport class 是用来输出log, 各个平台如PC/ 串口打印log的具体实现不同,使用虚函数继承是合理的,接口类Class ErrorReporter:lite/core/api/error_report.h

虚函数是virtual int Report(const char*, va_list args), 普通成员函数调用虚函数也得到了跨平台的接口。

对外的接口是个宏: 其中... 表示所有输入

#define TF_LITE_REPORT_ERROR(reporter, ...)? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
? do {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
? ? static_cast<tflite::ErrorReporter*>(reporter)->Report(__VA_ARGS__); \
? } while (false)

TF_LITE_REPORT_ERROR(error_reporter_,
? ? ? ? ? ? ? ? ? ? ? ? ?"Tensor index %d", index);

展开为:

static_cast<tflite::ErrorReporter*>(reporter)->Report(Tensor index %d", index); 强制类型转换

static_cast<tflite::ErrorReporter*>(reporter) 把reporter转换为基类,调用函数Report(const char* format, ...) 而Report的实现又调用虚函数得到log的具体实现。

tflite::Model

Model文件包含的数据包括: subgraphs(子图) 每个子图中包括输入、输出的tensor索引号和tensors

model的buffer里保存的是tensor相关的数据,model的operator_codes里包括了每个算子的具体信息如op_code(操作码),算子的input/oupt(tensor的索引号),算子的custom/builtin data.

模型的量化信息,

?OpResolver

算子决议,根据opcode找到具体的实现

?算子的决议实现方法是 调用AddBuiltin把opcode和对应的TfLiteRegistration, BuiltinParseFunction注册到数组中,最后通过GetRegistrationFromOpCode得到对应的TfLiteRegistration。

tf:Model中的算子在代码里表示NodeAndRegistration 或者说是算子的输入和算子的执行体

MicroInterpreter构造函数

MicroInterpreter::MicroInterpreter(const Model* model,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const MicroOpResolver& op_resolver,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?uint8_t* tensor_arena,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?size_t tensor_arena_size,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ErrorReporter* error_reporter,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tflite::Profiler* profiler)
? ? : model_(model),
? ? ? op_resolver_(op_resolver),
? ? ? error_reporter_(error_reporter),
? ? ? allocator_(*MicroAllocator::Create(tensor_arena, tensor_arena_size,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?error_reporter)),
? ? ? tensors_allocated_(false),
? ? ? initialization_status_(kTfLiteError),
? ? ? eval_tensors_(nullptr),
? ? ? context_helper_(error_reporter_, &allocator_, model),
? ? ? input_tensor_(nullptr),
? ? ? output_tensor_(nullptr) {
? Init(profiler);
}
初始化列表中创建了类:?MicroAllocator,?ContextHelper

MicroAllocator

MicroAllocator的作用是从arena中分配内存,具体实现是成员变量?class SimpleMemoryAllocator

这是代码最复杂的部分,下面会详述

ContextHelper

ContextHelper是为to encapsulate the implementation of APIs in Context.

TfLiteContext包含了不少函数指针,ContextHelper封装这些函数的实现,或者说提供了这些函数的实现。

context_.AllocatePersistentBuffer = context_helper_.AllocatePersistentBuffer;

context_.RequestScratchBufferInArena = context_helper_.RequestScratchBufferInArena;

context_.GetScratchBuffer = context_helper_.GetScratchBuffer;

MicroInterpreter::AllocateTensors()

?AllocateTensors之所以这么复杂,是为了内存的复用,如算子1:tensor占用的内存,到算子3时如果不用了,这块内存就可以复用,怎样知道那些可以复用也就是内存 planner 的实现GreedyMemoryAllocator 贪婪算法。

引入TfLiteEvalTensor

为了减少Memory的使用引入了TfLiteEvalTensor 保留了op必须使用的成员

?SimpleMemoryAllocator

?SimpleMemoryAllocator 管理一个线性数组(memory arena)

memory 分为3部分:

head(scratch buffer: GreedyMemoryPlanner策略的内存),

tail(persistent 部分,内容的生命周期 persistent),

temp(head, tail间的内存,使用后马上释放部分)

online/offline

memory 怎么plann是怎么得到?一种方法是offline 也就是 model文件的meta data里已经提供memory plann, 而online是 MicroInterpreter根据model 文件的内容 online进行计算得到memory planner

Tensors are allocated differently depending on the type of tensor.

Weight tensors are located in the flatbuffer, which is allocated by the application that calls TensorFlow Lite Micro.

EvalTensors are allocated in the tensor arena, either offline planned as specified in the flatbuffers metadata, or allocated during runtime by the?memory planner?(online planned). The tensor arena is allocated by MicroAllocator in TensorFlow Lite Micro, and the model buffer (represented by a .tflite-file) is allocated by the application using TensorFlow Lite Micro.

?

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-10-28 12:23:44  更:2021-10-28 12:25:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 8:34:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码