安卓机器学习框架学习:Android Neural Networks API (NNAPI)
Android Neural Networks API (NNAPI)
简介:
1、Android Neural Networks API (NNAPI) 是一个 Android C API,在 Android 设备上实现机器学习;
2、NNAPI 旨在为更高层级的机器学习框架(如 TensorFlow Lite 和 Caffe2)提供一个基本功能层,用来建立和训练神经网络;
3、搭载 Android 8.1(API 级别 27)或更高版本的所有 Android 设备上都提供该 API。
4、NNAPI 支持通过将 Android 设备中的数据应用到先前训练的开发者定义的模型来进行推断。
在设备上进行推断具备诸多优势:
- 延迟:您不需要通过网络连接发送请求并等待响应。例如,这对处理从相机传入的连续帧的视频应用至关重要。
- 可用性:即使在网络覆盖范围之外,应用也能运行。
- 速度:专用于神经网络处理的新硬件提供的计算速度明显快于单纯的通用 CPU。
- 隐私:数据不会离开 Android 设备。
- 费用:所有计算都在 Android 设备上执行,不需要服务器。
开发者还应在以下几个方面做出权衡取舍:
- 系统利用率:评估神经网络涉及大量的计算,而这可能会增加电池电量消耗。如果您担心自己的应用耗电量会增加(尤其是对于长时间运行的计算),应考虑监控电池运行状况。
- 应用大小:应注意模型的大小。模型可能会占用数 MB 的空间。如果在您的 APK 中绑定较大的模型会对用户造成过度影响,那么您可能需要考虑在应用安装后下载模型、使用较小的模型或在云端运行计算。NNAPI 未提供在云端运行模型的功能。
NNAPI 使用四个主要抽象概念:
-
模型:由数学运算和通过训练过程学习到的常量值构成的计算图。这些运算特定于神经网络。它们包括二维 (2D) 卷积、逻辑 (sigmoid) 激活函数、修正线性 (ReLU) 激活函数等。创建模型是一项同步操作。成功创建后,便可在线程和编译之间重用模型。在 NNAPI 中,模型表示为
ANeuralNetworksModel
实例。 -
编译:表示用于将 NNAPI 模型编译到更低级别代码中的配置。创建编译是一项同步操作。成功创建后,便可在线程和执行之间重用编译。在 NNAPI 中,每个编译都表示为一个
ANeuralNetworksCompilation
实例。 -
内存:表示共享内存、内存映射文件和类似内存缓冲区。使用内存缓冲区可让 NNAPI 运行时更高效地将数据传输到驱动程序。应用一般会创建一个共享内存缓冲区,其中包含定义模型所需的每个张量。您还可以使用内存缓冲区来存储执行实例的输入和输出。在 NNAPI 中,每个内存缓冲区均表示为一个
ANeuralNetworksMemory
实例。 -
执行:用于将 NNAPI 模型应用到一组输入并收集结果的接口。执行可以同步执行,也可以异步执行。
对于异步执行,多个线程可以等待同一执行。此执行完成后,所有线程都被释放。在 NNAPI 中,每次执行均表示为一个
ANeuralNetworksExecution
实例。
运行时:
1、**NNAPI 应由机器学习库、框架和工具调用,这样可让开发者在设备外训练他们的模型,并将其部署在 Android 设备上。2、应用一般不会直接使用 NNAPI,而会使用更高层级的机器学习框架。**这些框架进可以使用 NNAPI 在受支持的设备上执行硬件加速的推断运算。
根据应用的要求和 Android 设备的硬件功能,Android 的神经网络运行时可以在可用的**设备上处理器(包括专用的神经网络硬件、图形处理单元 (GPU) 和数字信号处理器 (DSP))**之间高效地分配计算工作负载。对于缺少专用供应商驱动程序的 Android 设备,NNAPI 运行时将在 CPU 上执行请求。
所示为 NNAPI 的简要系统架构。
编程模型:
若要使用 NNAPI 执行计算:
1、先构造一张有向图来定义要执行的计算。
2、此计算图与输入数据(例如,从机器学习框架传递过来的权重和偏差)相结合,构成 NNAPI 运行时求值的模型。
编程示例:
实现这样的计算图:
1、内存基础:
为 NNAPI 运行时提供对此类数据的高效访问途径,调用 ANeuralNetworksMemory_createFromFd()
函数并传入已打开的数据文件的文件描述符来创建 ANeuralNetworksMemory
。训练权重和偏差数据可能存储在一个文件中。
// Create a memory buffer from the file that contains the trained data
ANeuralNetworksMemory* mem1 = NULL;
int fd = open("training_data", O_RDONLY);
ANeuralNetworksMemory_createFromFd(file_size, PROT_READ, fd, 0, &mem1);
使用原生硬件缓冲区,可以将原生硬件缓冲区用于模型输入、输出和常量运算数值。在某些情况下,NNAPI 加速器可以访问 AHardwareBuffer
对象,而无需驱动程序复制数据。
// Configure and create AHardwareBuffer object
AHardwareBuffer_Desc desc = ...
AHardwareBuffer* ahwb = nullptr;
AHardwareBuffer_allocate(&desc, &ahwb);// Create ANeuralNetworksMemory from AHardwareBuffer
ANeuralNetworksMemory* mem2 = NULL;
ANeuralNetworksMemory_createFromAHardwareBuffer(ahwb, &mem2);//free
ANeuralNetworksMemory_free(mem2);
2、模型创建、编译、执行;
运算数规范:
-
添加运算数的顺序无关紧要。例如,模型输出运算数可能是添加的第一个运算数。重要的是在引用运算数时使用正确的索引值。
-
运算数具有类型。这些类型在运算数添加到模型时指定;
-
一个运算数不能同时用作模型的输入和输出;
-
每个运算数必须是一项运算的模型输入、常量或输出运算数;
运算规范:
运算指定要执行的计算。每项运算都由下面这些元素组成:
- 运算类型(例如,加法、乘法、卷积);
- 运算用于输入的运算数索引列表;
- 运算用于输出的运算数索引列表;
基本步骤:注意中间还可以进行很多配置
1、创建模型:
2、运算数添加到模型:
3、设置权重和偏差值;
4、添加运算;
5、设置输入和输出;
6、完成模型定义;
7、编译模型;
8、设置执行的设备和编译缓存;
9、执行模型;
10、最后一步,清理内存等资源;
//1、创建模型:
ANeuralNetworksModel* model = NULL;
ANeuralNetworksModel_create(&model);//2、运算数添加到模型:
// In our example, all our tensors are matrices of dimension [3][4]
ANeuralNetworksOperandType tensor3x4Type;
tensor3x4Type.type = ANEURALNETWORKS_TENSOR_FLOAT32;
tensor3x4Type.scale = 0.f; // These fields are used for quantized tensors
tensor3x4Type.zeroPoint = 0; // These fields are used for quantized tensors
tensor3x4Type.dimensionCount = 2;
uint32_t dims[2] = {3, 4};
tensor3x4Type.dimensions = dims;// We also specify operands that are activation function specifiers
ANeuralNetworksOperandType activationType;
activationType.type = ANEURALNETWORKS_INT32;
activationType.scale = 0.f;
activationType.zeroPoint = 0;
activationType.dimensionCount = 0;
activationType.dimensions = NULL;// 添加7个运算数
ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 0
ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 1
ANeuralNetworksModel_addOperand(model, &activationType); // operand 2
ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 3
ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 4
ANeuralNetworksModel_addOperand(model, &activationType); // operand 5
ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 6//3、设置权重和偏差值
// In our example, operands 1 and 3 are constant tensors whose values were
// established during the training process
const int sizeOfTensor = 3 * 4 * 4; // The formula for size calculation is dim0 * dim1 * elementSize
ANeuralNetworksModel_setOperandValueFromMemory(model, 1, mem1, 0, sizeOfTensor);
ANeuralNetworksModel_setOperandValueFromMemory(model, 3, mem1, sizeOfTensor, sizeOfTensor);// We set the values of the activation operands, in our example operands 2 and 5
int32_t noneValue = ANEURALNETWORKS_FUSED_NONE;
ANeuralNetworksModel_setOperandValue(model, 2, &noneValue, sizeof(noneValue));
ANeuralNetworksModel_setOperandValue(model, 5, &noneValue, sizeof(noneValue));//4、添加运算
// 两种运算,和以及乘
// The first consumes operands 1, 0, 2, and produces operand 4
uint32_t addInputIndexes[3] = {1, 0, 2};
uint32_t addOutputIndexes[1] = {4};
ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_ADD, 3, addInputIndexes, 1, addOutputIndexes);// The second consumes operands 3, 4, 5, and produces operand 6
uint32_t multInputIndexes[3] = {3, 4, 5};
uint32_t multOutputIndexes[1] = {6};
ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_MUL, 3, multInputIndexes, 1, multOutputIndexes);//5、设置输入和输出
// 输入: (0) 和 输出: (6)
uint32_t modelInputIndexes[1] = {0};
uint32_t modelOutputIndexes[1] = {6};
ANeuralNetworksModel_identifyInputsAndOutputs(model, 1, modelInputIndexes, 1 modelOutputIndexes);//6、完成模型定义
ANeuralNetworksModel_finish(model);//7、编译模型
ANeuralNetworksCompilation* compilation;
ANeuralNetworksCompilation_create(model, &compilation);//8、设置执行的设备和编译缓存
//优化低功耗
ANeuralNetworksCompilation_setPreference(compilation, ANEURALNETWORKS_PREFER_LOW_POWER);
//设置编译缓存
ANeuralNetworksCompilation_setCaching(compilation, cacheDir, token);
//完成编译
ANeuralNetworksCompilation_finish(compilation);//9、执行模型
// Run the compiled model against a set of inputs
ANeuralNetworksExecution* run1 = NULL;
ANeuralNetworksExecution_create(compilation, &run1);//指定读取输入值,可以是用户缓冲区或已分配的内存空间读取输入值。
// Set the single input to our sample model. Since it is small, we won't use a memory buffer
float32 myInput[3][4] = { ...the data... };
ANeuralNetworksExecution_setInput(run1, 0, NULL, myInput, sizeof(myInput));//设置写入输出值,写入用户缓冲区或已分配的内存空间。
float32 myOutput[3][4];
ANeuralNetworksExecution_setOutput(run1, 0, NULL, myOutput, sizeof(myOutput));//开始执行,等待可以在不同于开始执行的线程上完成。
// For our example, we have no other work to do and will just wait for the completion
ANeuralNetworksEvent_wait(run1_end);
ANeuralNetworksEvent_free(run1_end);
ANeuralNetworksExecution_free(run1);//可以选择通过使用同一编译实例将不同的输入集应用于已编译的模型,从而创建新的 ANeuralNetworksExecution 实例。//10、最后一步,清理内存等资源
// Cleanup
ANeuralNetworksCompilation_free(compilation);
ANeuralNetworksModel_free(model);
ANeuralNetworksMemory_free(mem1);
参考:
1、Neural Networks API | Android NDK | Android Developers (google.cn)
2、ndk-samples/nn-samples at main · android/ndk-samples (github.com)
相关文章:

安卓机器学习框架学习:Android Neural Networks API (NNAPI)
Android Neural Networks API (NNAPI) 简介: 1、Android Neural Networks API (NNAPI) 是一个 Android C API,在 Android 设备上实现机器学习; 2、NNAPI 旨在为更高层级的机器学习框架(如 TensorFlow Lite 和 Caffe2)…...

阿里云GPU服务器收费标准、学生价格及一个小时费用大全
阿里云GPU租用费用价格表,GPU计算卡包括NVIDIA V100计算卡、T4计算卡、A10计算卡和A100计算卡,GPU云服务器gn6i可享受3折优惠,阿里云百科分享阿里云GPU服务器学生优惠价格、GPU服务器收费价格表、GPU服务器多少钱一个小时等费用明细表&#x…...

Asp.net core 依赖注入 (带案例以及注释理解)
1.很多朋友不知道什么是依赖注入,接下来我用比较通俗易懂的话语 来帮助大家理解 依赖注入(Dependency Injection,简称DI)是一种设计模式,用于减少组件之间的耦合度。它的核心思想是,将组件之间的依赖关系从…...

【微信小程序】-- uni-app 项目-- 购物车 -- 首页 - 轮播图效果(五十二)
💌 所属专栏:【微信小程序开发教程】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &…...
GO实现Redis:GO实现Redis集群(5)
采用一致性hash算法将key分散到不同的节点,客户端可以连接到集群中任意一个节点https://github.com/csgopher/go-redis本文涉及以下文件: consistenthash:实现添加和选择节点方法 standalone_database:单机database client&#x…...

高阶数据结构之 B树 B+树 B*树
文章目录B树B树节点的设计插入key的过程B树的验证B树的性能分析B树和B*树B树B*树总结B树、B树、B*树B树的应用做索引MySQL索引MyISAMInnoDBB树 在前面几章中我们介绍了AVL树和红黑树,简单复习一下,我们说到原本的二叉搜索树会存在缺陷(不能保…...
CSS3之动画属性
系列文章目录 前端系列文章——传送门 CSS系列文章——传送门 文章目录系列文章目录CSS3 中的动画第一步:定义一个动画第二步:执行这个动画第三步:暂停或启动这个动画过渡和动画的区别CSS3 中的动画 CSS3 动画是使元素从一种样式逐渐变化为…...

python --Matplotlib详解
安装 pip install matplotlib导包 import matplotlib.pyplot as plt绘制散点图 如果输入的是两个列表,一个表示 x 轴的值,一个表示 y 轴的值,那么就可以在直角坐标系中划出很多个点,然后将这些点用指定的线段连接起来就得到了散…...

手机(Android)刷NetHunter安装指南,无需ssh执行kali命令, NetHunter支持的无线网卡列表!
一、安装NetHunter 前提:确保手机已经root,已装上magisk。如果没有root,可用尝试magisk root 后执行此文 1、下载Nethunter:Get Kali | Kali Linux 然后push 到sdcard 里, 2、打开magisk,选择刚刚下好的…...

教育行业ChatGPT的新挑战
随着科技不断发展,AI的水平越来越高,尤其是最近火出圈的ChatGPT不仅仅可以与人类对话,而且还可以为人们提供关于各种信息帮助。 作为一个先进的“聊天”AI,无论是正苦恼,还是只是需要一些关于如何更有效地管理时间的建…...

内存泄漏 定位方法
目录 内存概念 物理内存 虚拟内存 内存泄漏 定位方法和手段 1.MemInFo MemTotal MemFree MemAvailable Cached 2 vmalloc info 3.Kmemleak 算法原理 使用方法 参考文献与链接: 如果你点进这篇文章,那么要么你是一个C\C程序员,…...

es-head插件插入查询以及条件查询(五)
es-head插件插入查询以及条件查询 1.es-head插件页面介绍 页面详细介绍 2.es-head查询语句 2.1.查询索引中的全部数据 curl命令交互,采用GET请求 语法格式: curl -XGET es地址:9200/索引名/_search?pretty [rootelaticsearch ~]# curl -XGET 192…...

安装python教程并解决Python安装完没有Scripts文件夹问题
安装python教程 并解决Python安装完没有Scripts文件夹问题 ** 一背景 **首先要了解这个出现的原因是下载安装的版本问题 系統是32 bit 的版本还是 64bit 的 web-based: 透过网络安装的,就是执行安装后才透过网络下载python executable: 可執行文件的ÿ…...

postman的断言、关联、参数化、使用newman生成测试报告
Potman 断言 Postman 断言简介 让 Postman工具 代替 人工 自动判断 预期结果 和 实际结果 是否一致断言代码 书写在 Tests 标签页中。 查看断言结果 Test Results 标签页 Postman 常用断言 1. 断言响应状态码 Status code:Code is 200 // 断言响应状态码为 200…...

春招大盘点:找工作除了招聘网站还有哪些渠道?
又是一年毕业季,估计同学们都正在写论文、找工作两头忙,很多同学和小C“诉苦”说现在找实习的渠道太少了,招聘网站都刷完了,也没看到很合适的岗位。那找工作除了招聘网站还有什么渠道呢?其实是有的,今天就为…...

eNSP 构建基本WLAN
配置项配置参数AP组 名称:hcia-group 应用模板:域管理模板hcia-domain、VAP模板hcia-vap 域管理模板 名称:hcia-domain 国家码:cn SSID模板 名称:hcia-ssid SSID名称:hcia-wlan 安全模板 名称:h…...

Python是不是被严重高估了?
Python起源一种shell的脚本语言 ,而现在已经发展成最通用的语言之一了,TIOBE指数的数据显示,Python是目前世界上最受欢迎的编程语言。 Python之所以这么受欢迎有很多原因。从Web开发到物联网编程再到AI等各个方面都能用到它。另外Python代码…...
给你一个购物车模块,你会如何设计测试用例?【测试用例设计】
测试购物车 从使用场景上,把自己想象成一个使用购物车的人,模拟流程,可以主要从两个方面进行考虑: 涉及操作:增(添加商品)删(删除商品)改(编辑、跳转商品&a…...

【wps】【毕业论文】三线表的绘制
目录 一、三线表 二、制作步骤 (1)点击“插入”——点击“表格”创建一个表格 (2)选中整个表格——鼠标右键选择“边框和底纹”,“表格属性”再点击“边框和底纹”——点击“自定义”——选择表格的边的宽度——如图…...

Spring Cloud Alibaba 多租户saas企业开发架构技术选型和设计方案
基于Spring Cloud Alibaba 分布式微服务高并发数据平台化(中台)思想多租户saas设计的企业开发架构,支持源码二次开发、支持其他业务系统集成、集中式应用权限管理、支持拓展其他任意子项目。 一、架构技术选型 核心框架 Spring Boot SOA Spring Cloud …...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...