当前位置: 首页 > news >正文

安卓机器学习框架学习: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&#xff09…...

阿里云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: 可執行文件的&#xff…...

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 …...

Unity IL2CPP 游戏分析入门

一、目标 很多时候App加密本身并不难,难得是他用了一套新玩意,天生自带加密光环。例如PC时代的VB,直接ida的话,汇编代码能把你看懵。 但是要是搞明白了他的玩法,VB Decompiler一上,那妥妥的就是源码。 U…...

Python的23种设计模式(完整版带源码实例)

作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 Python的23种设计模式 一 什么是设计模式 设计模式是面对各种问题进行提炼和抽象而形成的解决方案。这些设计方案是前人不断试验&…...

OAuth2协议

OAuth2协议流程图协议角色和流程授权所需信息授权方式授权码模式(authorization code)参数简化模式密码模式客户端模式授权方式小结流程图 协议角色和流程 user-agent:浏览器或者手机App平台 资源所有者(resourc owner&#xff0…...

LeetCode-115. 不同的子序列

目录动态规划题目来源 115. 不同的子序列 动态规划 1.确定dp数组(dp table)以及下标的含义 dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。 2.确定递推公式 这一类问题,基本是要分析两种情况 t[i - 1…...

kubernetes scheduler 源码解析及自定义资源调度算法实践

kubernetes scheduler 浅析 什么是kubernetes scheduler? 小到运行着几十个工作负载的 kubernetes 集群,大到运行成千上万个工作负载 kubernetes 集群,每个工作负载到底应该在哪里运行,这需要一个聪明的大脑进行指挥&#xff0c…...

MySQL插入数据

目录 一、怎么样插入数据 二、通过命令提示窗口插入数据 三、使用PHP脚本插入数据 一、怎么样插入数据 在MySQL 表中可以使用 INSERT INTO SQL语句来插入数据。 可以通过 mysql> 命令提示窗口中向数据表中插入数据,或者通过PHP脚本来插入数据。 下面是向MyS…...

从GPT-4、文心一言再到Copilot,AIGC卷出新赛道?

业内人都知道,上一周是戏剧性的,每一天,都是颠覆各个行业,不断 AI 化的新闻。 OpenAI发布GPT-4、百度发布文心一言、微软发布Microsoft 365 Copilot 三重buff叠加,打工人的命运可以说是跌宕起伏,命途多舛了…...

1.2 从0开始学Unity游戏开发--运行原理

在我开始学习游戏开发的时候,有了好多年的客户端开发经验,并且刚毕业那会还使用cocos2dx做过一点小的2d横版过关游戏,因此对我来说做游戏开发到底是做什么还是比较清晰的,但是如果从来没做过游戏开发,甚至连客户端开发也没怎么做过的人可能没那么好理解游戏到底是怎么运作…...

【微信小程序】如何获得自己当前的定位呢?本文利用逆地址解析、uni-app带你实现

目录 前言 效果展示 一、在腾讯定位服务配置微信小程序JavaScript SDK 二、使用uni-app获取定位的经纬度 三、 逆地址解析,获取精确定位 四、小提示 前言 效果展示 一、在腾讯定位服务配置微信小程序JavaScript SDK 在浏览器搜索腾讯定位服务,找…...

92年程序员发帖晒薪资称自己很迷茫,网友:老弟你可以了

当下,是一个“向钱看,向厚赚”的社会。快节奏的生活下,家庭、工作各方面压力很容易使年轻人陷入迷茫和焦虑。 与其他行业相比,程序员的高薪让人羡慕。那么,对于那些真正达到这么多收入的人来说,他们是怎么…...

个人引擎网站什么做/北京百度快速优化排名

题目链接:http://codeforces.com/problemset/problem/1166/E 说明 LCM(一个集合) 为这个集合中所有元素的最小公倍数。如果$A \subseteq B,LCM(A) \leq LCM(B)$。 题目大意 给定由 n 个整数组成的集合 A 。现给定 m 组集合,每个集合 Si 都是 …...

域名到期与网站打不开/杭州seo网站推广

1. 使用Value注解读取 读取properties配置文件时,默认读取的是application.properties。 Value("${port}")private String port; 2、使用Environment读取 Autowiredprivate Environment environment;public void test(){String portenvironment.getProper…...

太原网站建设乛薇/广告策划案优秀案例

机械传动装置通常是指将动力机产生的机械能或运动以机械的方式传送到工作机上去的中间装置。在机械工程中,由于大多数的机器都有机械传动装置,因此其量多、面广,并且种类繁杂,生产规模也是相当可观。正是因为这样所以导致很多设计…...

有名的seo外包公司/seo整站优化服务

文章目录1 Thread.sleep(0)1.1 问题引入1.2 探索1.3 实践1.4 附加1 Thread.sleep(0) 1.1 问题引入 先看看一个来自RocketMQ(org.apache.rocketmq.store.logfile.DefaultMappedFile#warmMappedFile)代码里面的for循环,在循环里面&#xff0c…...

商洛 网站建设/长沙官网seo分析

微信小程序里如果使用了 async await,会报这个错误 原因:asyncawait是 ES7 的一个特性,如果微信小程序IDE里开启了ES6转ES5,则会报这个错误。 解决方案: 第一种方法:微信小程序IDE里,详情->…...

德国著名的外贸公司地址/福州百度网站排名优化

参考链接: 1、http://www.talkwithtrend.com/Question/123541?orderasc 解决方法: Doucker 提示:Your kernel does not support swap limit capabilities 这个默认官方给予解决方法了,地址是https://docs.docker.com/installat…...