Android全栈开发中的机器学习模型集成方案

Android全栈开发中的机器学习模型集成方案

关键词:Android全栈开发、机器学习模型集成、模型优化、端侧推理、TFLite、ONNX Runtime、边缘计算

摘要:随着移动应用智能化需求激增,如何高效地将机器学习模型集成到Android应用中成为开发者的关键挑战。本文从Android全栈开发视角出发,结合模型优化、部署框架、端侧推理等核心环节,通过生活类比、代码示例和实战案例,系统讲解模型集成的完整流程与关键技术,帮助开发者解决模型体积大、推理延迟高、设备兼容性差等问题。


背景介绍

目的和范围

在“万物智能”的时代,Android应用不再局限于传统功能交互,而是逐渐融入图像识别(如美图的AI滤镜)、语音交互(如讯飞输入法的语音转文字)、个性化推荐(如抖音的内容推荐)等机器学习能力。但直接将服务器端的大模型移植到手机端会遇到三大难题

模型体积大:手机存储有限,100MB以上的模型可能导致安装包超限;
推理延迟高:CPU/GPU算力有限,复杂模型可能导致界面卡顿;
设备兼容性差:不同Android设备的芯片(骁龙/天玑/麒麟)、系统版本(Android 8.0~14.0)差异大,模型运行表现不稳定。

本文将覆盖从模型优化到Android端集成的全流程,重点解决上述问题,适用于需要为应用添加AI能力的Android开发者、机器学习工程师。

预期读者

有一定Android开发经验(熟悉Kotlin/Java、Android组件)的开发者;
了解基础机器学习概念(如模型训练、推理),但对端侧部署不熟悉的工程师;
希望为应用添加AI功能的全栈开发者。

文档结构概述

本文将按照“概念→原理→实战→应用”的逻辑展开:

用“快递运输”类比模型集成,解释核心概念;
拆解模型优化(剪枝/量化)、部署框架(TFLite)、端侧推理的技术原理;
通过“宠物识别App”实战,演示从模型训练到Android集成的完整流程;
总结不同场景下的集成策略,并展望未来趋势。

术语表

核心术语定义

端侧推理:在手机、平板等终端设备上直接运行模型,无需联网调用云端API;
模型量化:将模型参数从32位浮点数(float32)转换为8位整数(int8),减小体积并加速计算;
TFLite:Google推出的轻量级端侧推理框架,专为移动/嵌入式设备优化;
模型剪枝:删除模型中冗余的神经元或连接,保留核心结构。

相关概念解释

边缘计算:与“云端计算”相对,指在终端设备上完成数据处理,降低网络依赖;
模型蒸馏:用小模型(学生模型)学习大模型(教师模型)的知识,实现“以小博大”。

缩略词列表

TFLite:TensorFlow Lite
ONNX:Open Neural Network Exchange(开放神经网络交换格式)
FPS:Frames Per Second(每秒处理帧数,衡量实时性)


核心概念与联系

故事引入:用“快递运输”理解模型集成

假设你要开一家“智能奶茶店”,需要把中央厨房(服务器)的“奶茶配方”(机器学习模型)送到各个分店(Android设备),让顾客(用户)快速喝到定制奶茶(AI功能)。但运输过程中会遇到问题:

配方太复杂(模型太大):货车装不下,分店存不下;
配送太慢(推理延迟高):顾客等得不耐烦;
分店设备不同(芯片/系统差异):有的用燃气灶(CPU),有的用电磁炉(GPU),配方可能“水土不服”。

解决这些问题的过程,就是模型集成:优化配方(模型瘦身)、选择合适的运输工具(部署框架)、适配分店设备(端侧推理优化)。

核心概念解释(像给小学生讲故事一样)

核心概念一:模型优化——给配方“瘦身”

模型优化就像给奶茶配方“瘦身”:原本需要10种原料(32位浮点参数),但实际90%的原料对味道(模型精度)影响很小,删掉冗余原料(剪枝),再把剩下的原料用更小的包装(量化成8位整数),配方手册(模型文件)就能从100页(100MB)变成10页(10MB),既省空间又方便运输。

核心概念二:部署框架——选择“运输工具”

部署框架是专门为运输配方设计的“货车”。比如TFLite就像一辆“轻卡”,体积小、油耗低(内存占用少),能灵活穿过小路(适配低端手机);ONNX Runtime像“多用途货车”,支持多种车型(CPU/GPU/TPU),适合需要高性能的场景。

核心概念三:端侧推理——分店“做奶茶”

端侧推理是分店根据瘦身后的配方(优化模型)现场做奶茶。顾客点单(输入数据,如图像/文本)后,店员(Android应用)把点单信息(输入张量)交给厨房(推理框架),厨房按配方(模型结构)快速处理,最后把奶茶(输出结果)端给顾客。

核心概念之间的关系(用小学生能理解的比喻)

模型优化与部署框架的关系:瘦身的配方(优化模型)需要适配运输工具(部署框架)。比如用TFLite货车,需要把配方写成TFLite能识别的“简版说明书”(模型转换);
部署框架与端侧推理的关系:货车(部署框架)决定了分店厨房(设备芯片)的操作方式。TFLite货车支持用燃气灶(CPU)或电磁炉(GPU),而ONNX货车可能支持更高级的烤箱(TPU);
模型优化与端侧推理的关系:配方越瘦身(模型越小),厨房做奶茶越快(推理延迟越低),但瘦身过度可能导致奶茶不好喝(精度下降),需要平衡“瘦身程度”和“味道”(精度与速度)。

核心概念原理和架构的文本示意图

模型训练(Python/PyTorch) → 模型优化(剪枝/量化) → 模型转换(TFLite格式) → Android集成(加载/推理) → 用户交互(图像/语音输入)

Mermaid 流程图


核心算法原理 & 具体操作步骤

模型优化的三大“瘦身术”

1. 剪枝(Pruning)

原理:模型训练完成后,很多神经元的权重接近0,对输出影响极小,删除这些“冗余神经元”,保留核心连接。
类比:修剪盆栽的多余枝叶,只保留主干和主要分支,不影响植物生长。
操作步骤(以PyTorch为例):

import torch
from torch import nn

# 加载训练好的模型
model = torch.load("original_model.pth")

# 对全连接层进行剪枝(删除20%权重)
pruned_model = torch.nn.utils.prune.l1_unstructured(
    model.fc,  # 目标层(全连接层)
    name="weight",  # 剪枝参数(权重)
    amount=0.2  # 剪枝比例(20%)
)
2. 量化(Quantization)

原理:将32位浮点数(float32)参数转换为8位整数(int8),减少存储和计算量。数学公式:
q = round ( x − x min x max − x min × ( q max − q min ) + q min ) q = ext{round}left( frac{x – x_{ ext{min}}}{x_{ ext{max}} – x_{ ext{min}}} imes (q_{ ext{max}} – q_{ ext{min}}) + q_{ ext{min}}
ight) q=round(xmax​−xmin​x−xmin​​×(qmax​−qmin​)+qmin​)
其中, x x x是原始浮点值, q q q是量化后的整数值, x min / x max x_{ ext{min}}/x_{ ext{max}} xmin​/xmax​是浮点值的最小/最大值, q min / q max q_{ ext{min}}/q_{ ext{max}} qmin​/qmax​是整数的最小/最大值(如int8的-128~127)。

类比:把连续的温度值(0.0℃30.0℃)用整数刻度(030)表示,虽然精度略有损失,但更易存储和计算。

操作步骤(TensorFlow模型转TFLite量化模型):

import tensorflow as tf

# 加载原始SavedModel
converter = tf.lite.TFLiteConverter.from_saved_model("original_model")

# 配置全整数量化(需要校准数据)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
calibration_data = load_calibration_images()  # 加载校准数据集(100~1000张代表性图片)
def representative_dataset():
    for image in calibration_data:
        yield [image.astype(tf.float32)]  # 输入数据需与模型输入格式一致
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # 输入量化为int8
converter.inference_output_type = tf.int8  # 输出量化为int8

# 转换并保存量化模型
tflite_quant_model = converter.convert()
with open("quantized_model.tflite", "wb") as f:
    f.write(tflite_quant_model)
3. 蒸馏(Knowledge Distillation)

原理:用大模型(教师模型)的输出(软标签)训练小模型(学生模型),让小模型学习大模型的“知识”,在体积更小的同时保持接近的精度。
类比:小学生(学生模型)向老师(大模型)学习,老师不仅告诉答案(硬标签),还讲解解题思路(软标签),帮助学生更高效地掌握知识。

操作步骤(简化版):

# 教师模型(大模型,如ResNet50)
teacher_model = ResNet50(pretrained=True)
# 学生模型(小模型,如MobileNetV3)
student_model = MobileNetV3()

# 定义蒸馏损失(结合学生模型与教师模型的输出)
def distillation_loss(student_output, teacher_output, labels, temperature=2.0):
    # 教师输出的软标签(经过温度缩放)
    soft_teacher = nn.functional.softmax(teacher_output / temperature, dim=1)
    # 学生输出的软预测
    soft_student = nn.functional.softmax(student_output / temperature, dim=1)
    # 蒸馏损失(KL散度) + 交叉熵损失(硬标签)
    loss = nn.KLDivLoss()(soft_student, soft_teacher) * (temperature**2) + nn.CrossEntropyLoss()(student_output, labels)
    return loss

# 训练学生模型
optimizer = torch.optim.Adam(student_model.parameters())
for images, labels in train_loader:
    teacher_output = teacher_model(images)
    student_output = student_model(images)
    loss = distillation_loss(student_output, teacher_output, labels)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

数学模型和公式 & 详细讲解 & 举例说明

以量化的线性公式为例:
假设一个浮点参数的取值范围是 x min = − 2.0 x_{ ext{min}}=-2.0 xmin​=−2.0, x max = 2.0 x_{ ext{max}}=2.0 xmax​=2.0,量化为int8( q min = − 128 q_{ ext{min}}=-128 qmin​=−128, q max = 127 q_{ ext{max}}=127 qmax​=127)。对于浮点值 x = 1.5 x=1.5 x=1.5,量化后的整数值 q q q计算如下:
q = round ( 1.5 − ( − 2.0 ) 2.0 − ( − 2.0 ) × ( 127 − ( − 128 ) ) + ( − 128 ) ) q = ext{round}left( frac{1.5 – (-2.0)}{2.0 – (-2.0)} imes (127 – (-128)) + (-128)
ight) q=round(2.0−(−2.0)1.5−(−2.0)​×(127−(−128))+(−128))
= round ( 3.5 4.0 × 255 − 128 ) = ext{round}left( frac{3.5}{4.0} imes 255 – 128
ight) =round(4.03.5​×255−128)
= round ( 223.125 − 128 ) = round ( 95.125 ) = 95 = ext{round}(223.125 – 128) = ext{round}(95.125) = 95 =round(223.125−128)=round(95.125)=95

反过来,推理时需要将量化值还原为浮点值(反量化):
x = q − q min q max − q min × ( x max − x min ) + x min x = frac{q – q_{ ext{min}}}{q_{ ext{max}} – q_{ ext{min}}} imes (x_{ ext{max}} – x_{ ext{min}}) + x_{ ext{min}} x=qmax​−qmin​q−qmin​​×(xmax​−xmin​)+xmin​
例如, q = 95 q=95 q=95时:
x = 95 − ( − 128 ) 127 − ( − 128 ) × ( 2.0 − ( − 2.0 ) ) + ( − 2.0 ) x = frac{95 – (-128)}{127 – (-128)} imes (2.0 – (-2.0)) + (-2.0) x=127−(−128)95−(−128)​×(2.0−(−2.0))+(−2.0)
= 223 255 × 4.0 − 2.0 ≈ 3.5 − 2.0 = 1.5 = frac{223}{255} imes 4.0 – 2.0 approx 3.5 – 2.0 = 1.5 =255223​×4.0−2.0≈3.5−2.0=1.5

通过这种方式,模型参数体积可缩小4倍(32位→8位),计算速度提升3~4倍(整数运算比浮点运算快)。


项目实战:宠物识别App的模型集成

开发环境搭建

模型训练环境:Python 3.9、TensorFlow 2.15、CUDA 11.7(GPU加速训练);
Android开发环境:Android Studio Flamingo | 2022.2.1、Kotlin 1.9.0、Android SDK 34;
依赖库:TFLite Support Library(2.13.0)、Glide(4.16.0,图片加载)。

源代码详细实现和代码解读

步骤1:训练并转换TFLite模型(Python端)

我们使用TensorFlow的MobileNetV2作为基础模型,在宠物数据集(猫/狗/兔子)上微调,然后转换为量化TFLite模型。

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# 加载并预处理数据
train_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
    'pet_dataset/train',
    target_size=(224, 224),  # MobileNetV2输入尺寸
    batch_size=32,
    class_mode='categorical'  # 多分类
)

# 构建模型(基于MobileNetV2)
base_model = tf.keras.applications.MobileNetV2(
    input_shape=(224, 224, 3),
    include_top=False,  # 去掉原分类层
    weights='imagenet'  # 使用预训练权重
)
base_model.trainable = False  # 冻结基础层

model = tf.keras.Sequential([
    base_model,
    tf.keras.layers.GlobalAveragePooling2D(),  # 全局平均池化
    tf.keras.layers.Dense(3, activation='softmax')  # 3分类(猫/狗/兔子)
])

model.compile(
    optimizer=tf.keras.optimizers.Adam(0.001),
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# 训练模型(假设训练10轮)
model.fit(train_generator, epochs=10)

# 转换为量化TFLite模型(全整数量化)
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
# 校准数据(使用验证集前100张图)
calibration_images = load_calibration_data('pet_dataset/val', num_samples=100)
def representative_dataset():
    for image in calibration_images:
        yield [image.reshape(1, 224, 224, 3)]  # 调整为模型输入形状(批量大小1)
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8  # 输入量化为uint8(0~255)
converter.inference_output_type = tf.uint8  # 输出量化为uint8
tflite_model = converter.convert()
with open('pet_model_quant.tflite', 'wb') as f:
    f.write(tflite_model)
步骤2:Android端集成模型(Kotlin)

在Android项目中加载TFLite模型,处理输入图像,执行推理,并展示结果。

1. 添加依赖(build.gradle)

dependencies {
            
    implementation 'org.tensorflow:tensorflow-lite:2.15.0'  // TFLite核心库
    implementation 'org.tensorflow:tensorflow-lite-support:2.15.0'  // 支持库(图像/文本处理)
    implementation 'com.github.bumptech.glide:glide:4.16.0'  // 图片加载
}

2. 模型文件放入assets目录
pet_model_quant.tflite复制到app/src/main/assets目录下。

3. 模型推理工具类(TFLiteClassifier.kt)

import org.tensorflow.lite.Interpreter
import org.tensorflow.lite.support.common.FileUtil
import org.tensorflow.lite.support.image.TensorImage
import org.tensorflow.lite.support.image.ops.ResizeOp
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer

class TFLiteClassifier(context: Context) {
            
    private val interpreter: Interpreter
    private val inputShape: IntArray  // 模型输入形状(如[1, 224, 224, 3])
    private val outputShape: IntArray  // 模型输出形状(如[1, 3])

    init {
            
        // 从assets加载模型文件
        val modelFile = FileUtil.loadMappedFile(context, "pet_model_quant.tflite")
        interpreter = Interpreter(modelFile)
        // 获取输入/输出张量信息
        val inputTensor = interpreter.getInputTensor(0)
        inputShape = inputTensor.shape()
        val outputTensor = interpreter.getOutputTensor(0)
        outputShape = outputTensor.shape()
    }

    fun classify(bitmap: Bitmap): String {
            
        // 步骤1:预处理输入图像(缩放到模型输入尺寸224x224)
        val tensorImage = TensorImage(inputTensor.dataType())
        tensorImage.load(bitmap)
        val resizeOp = ResizeOp(
            inputShape[1],  // 目标高度224
            inputShape[2],  // 目标宽度224
            ResizeOp.ResizeMethod.BILINEAR  // 双线性插值
        )
        val resizedImage = resizeOp.apply(tensorImage)

        // 步骤2:创建输入/输出缓冲区
        val inputBuffer = TensorBuffer.createFixedSize(inputShape, inputTensor.dataType())
        inputBuffer.loadBuffer(resizedImage.buffer)  // 加载预处理后的图像数据

        val outputBuffer = TensorBuffer.createFixedSize(outputShape, outputTensor.dataType())

        // 步骤3:执行推理
        interpreter.run(inputBuffer.buffer, outputBuffer.buffer)

        // 步骤4:解析输出结果(获取概率最高的类别)
        val probabilities = outputBuffer.floatArray  // 反量化后的浮点概率
        val classNames = arrayOf("猫", "狗", "兔子")
        val maxIndex = probabilities.indices.maxByOrNull {
             probabilities[it] } ?: 0
        return "${
            classNames[maxIndex]}(置信度:${
            probabilities[maxIndex].let {
             "%.2f%%".format(it * 100) }})"
    }

    fun close() {
            
        interpreter.close()
    }
}

4. 界面交互(MainActivity.kt)

class MainActivity : AppCompatActivity() {
            
    private lateinit var classifier: TFLiteClassifier
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
            
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        classifier = TFLiteClassifier(this)

        // 点击图片触发识别
        binding.ivPet.setOnClickListener {
            
            val intent = Intent(Intent.ACTION_PICK).apply {
            
                type = "image/*"
            }
            startActivityForResult(intent, REQUEST_IMAGE_PICK)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_IMAGE_PICK && resultCode == RESULT_OK) {
            data?.data?.let { uri ->
                // 加载图片并显示
                Glide.with(this).load(uri).into(binding.ivPet)
                // 解码Bitmap并识别
                val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(uri))
                val result = classifier.classify(bitmap)
                binding.tvResult.text = result
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        classifier.close()  // 释放模型资源
    }

    companion object {
        private const val REQUEST_IMAGE_PICK = 1001
    }
}

代码解读与分析

模型加载:通过FileUtil.loadMappedFile加载assets中的TFLite模型,利用内存映射减少IO耗时;
图像预处理:使用TFLite Support Library的ResizeOp完成图像缩放,避免手动处理复杂的像素操作;
推理执行Interpreter.run()方法将输入数据传入模型,输出结果存储在outputBuffer中;
资源释放onDestroy()中调用interpreter.close()释放模型占用的内存,防止内存泄漏。


实际应用场景

1. 实时图像识别(如相机类App)

需求:拍摄宠物照片后立即显示品种,要求推理延迟<100ms;
集成策略:使用量化模型(int8)+ GPU加速(TFLite的GpuDelegate),确保在中端手机(如Redmi Note 12)上达到30FPS;
优化点:限制输入分辨率(如224×224),减少计算量。

2. 文本预测(如输入法)

需求:根据用户输入的前几个字预测下一个词,要求响应时间<50ms;
集成策略:使用LSTM/Transformer的轻量级变体(如T5-small),通过模型蒸馏进一步缩小体积;
优化点:缓存最近输入的文本,避免重复预处理。

3. 健康监测(如运动App)

需求:通过手机加速度计数据识别用户运动状态(跑步/走路/静止);
集成策略:使用时间序列模型(如CNN-LSTM),输入为加速度计的历史数据(1秒内50个采样点);
优化点:采用动态输入长度(仅处理新采样点),减少计算量。


工具和资源推荐

模型优化工具

TensorFlow Lite Converter:官方工具,支持Keras/ SavedModel转TFLite,内置量化/剪枝选项;
PyTorch Mobile:PyTorch官方端侧部署方案,支持模型量化和优化;
NNI(Neural Network Intelligence):微软开源的自动模型压缩工具,支持剪枝/量化/蒸馏。

部署框架

TFLite:Google官方,生态完善,支持Android/iOS/嵌入式设备;
ONNX Runtime:微软开源,支持多硬件(CPU/GPU/TPU),适合需要高性能的场景;
MNN:阿里开源,专为端侧优化,支持模型加密(防篡改)。

调试工具

TFLite Model Analyzer:查看模型结构、输入输出形状、操作类型;
Android Profiler:监控模型推理时的CPU/GPU占用、内存使用;
Adb Logcat:捕获推理时的异常日志(如输入格式不匹配)。


未来发展趋势与挑战

趋势1:边缘计算与端云协同

未来的模型集成将不再局限于“纯端侧”或“纯云端”,而是根据场景动态选择:

简单任务(如基础图像分类)在端侧完成,保证实时性;
复杂任务(如高精度目标检测)调用云端大模型,保证准确性。

趋势2:联邦学习(Federated Learning)

通过联邦学习,手机在本地训练模型(仅上传梯度,不上传原始数据),既保护用户隐私,又能利用大量设备数据提升模型性能。例如,输入法的个性化词库可以通过联邦学习优化。

趋势3:模型自适应性(Adaptive Model)

模型根据设备性能(如CPU算力、内存大小)自动调整复杂度。例如,高端手机运行完整模型,低端手机运行蒸馏后的小模型,保证不同设备的用户体验一致。

挑战1:设备异构性

Android设备的芯片(骁龙/天玑/麒麟)、GPU(Adreno/Mali/Valhall)差异大,模型在不同设备上的推理速度可能相差数倍。需要框架(如TFLite)提供更智能的硬件适配(自动选择CPU/GPU/NNAPI)。

挑战2:实时性要求

视频类应用(如直播美颜)需要推理延迟<33ms(30FPS),对模型体积和计算量提出极高要求。未来可能需要更激进的模型压缩技术(如动态网络结构)。

挑战3:隐私保护

端侧推理虽然减少了数据上传,但模型本身可能泄露训练数据的隐私(如通过模型反演攻击)。需要结合差分隐私(Differential Privacy)等技术,在模型训练阶段添加噪声,保护用户数据。


总结:学到了什么?

核心概念回顾

模型优化:通过剪枝、量化、蒸馏让模型“瘦身”,减小体积并加速推理;
部署框架:TFLite/ONNX Runtime等框架负责将优化后的模型部署到Android设备;
端侧推理:在手机上直接运行模型,减少网络依赖,提升响应速度。

概念关系回顾

模型优化是“瘦身”,部署框架是“运输工具”,端侧推理是“现场执行”,三者协同解决模型体积大、延迟高、兼容性差的问题。


思考题:动动小脑筋

如果你要开发一个“智能美颜相机”,需要实时识别用户的面部特征(如眼睛/鼻子位置),你会选择哪种模型优化方法(剪枝/量化/蒸馏)?为什么?
假设你的Android应用需要集成一个大语言模型(如LLaMA-7B),但手机内存只有8GB,你会如何解决模型加载问题?(提示:可以查“模型分块加载”或“稀疏计算”)


附录:常见问题与解答

Q:模型转换为TFLite后精度下降严重,怎么办?
A:可能是量化过程中校准数据不足。确保校准数据集覆盖真实场景的多样性(如不同光照、角度的图片),或尝试“量化感知训练”(在训练阶段模拟量化过程,提升模型对量化的鲁棒性)。

Q:TFLite推理时CPU占用过高,导致手机发热,如何优化?
A:尝试启用GPU加速:

// 在Interpreter初始化时添加GpuDelegate
val options = Interpreter.Options()
val gpuDelegate = GpuDelegate()
options.addDelegate(gpuDelegate)
interpreter = Interpreter(modelFile, options)

Q:不同Android版本(如Android 8.0和14.0)对TFLite的支持有差异吗?
A:TFLite核心库兼容Android 5.0(API 21)及以上,但部分高级功能(如NNAPI加速)需要Android 8.1(API 27)及以上。建议在代码中检查设备API级别,动态选择推理方式。


扩展阅读 & 参考资料

TensorFlow Lite官方文档
《Android机器学习实战》(作者:谢海滨,机械工业出版社)
联邦学习论文:Communication-Efficient Learning of Deep Networks from Decentralized Data
PyTorch Mobile官方指南

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容