极限瘦身:将 Python AI 应用从 100MB 砍到 30MB
上一篇我们用“钞能力”(Chaquopy + Paddle)快速搞定了功能,但代价是惨痛的——APK 体积可能飙升到了 100MB+。这在用户眼里就是“毒瘤软件”。
今天,我们不仅要当“大厨”,还要当“外科医生”。我们将对这个 APK 进行一场精准的瘦身手术,目标是将体积压缩到 30MB 以内,同时保留 Python 的开发体验。
1. 诊断报告:为什么它这么“胖”?
在动刀之前,我们先得知道脂肪堆积在哪里。一个典型的 Chaquopy + Paddle APK 结构如下:
-
Android 基础代码:< 5MB(忽略不计)
-
Python 解释器 + 标准库:~10MB(这是基础开销)
-
Native 库 (.so 文件):~80MB+ (罪魁祸首) 🚨
-
PaddlePaddle 包含了完整的训练框架、反向传播逻辑、多种硬件驱动……但你在手机上只需要推理(Inference)。
-
手术方案:
-
切除多余肢体:只保留一种 CPU 架构。
-
更换核心引擎:用轻量级的 ONNX Runtime 替换笨重的 PaddlePaddle 库,但依然使用 Paddle 训练的模型。
2. 第一刀:ABI 架构过滤 (减重 50%)
Android 手机 CPU 有多种架构(x86, armeabi-v7a, arm64-v8a)。默认情况下,Gradle 会把所有架构的 .so 库都打包进去,就像你出门旅行带了春夏秋冬四季的衣服。
但在 2024 年,99% 的主流手机都是 arm64-v8a。
🛠 操作指南
修改 app/build.gradle:
android { defaultConfig { // ... ndk { // ✂️ 咔嚓!只保留 64位 ARM 架构 // 这会直接丢弃 x86 和 32位 ARM 的库文件 abiFilters "arm64-v8a" } } }
效果:如果你的 APK 里原本包含三套 .so 文件,这一步直接能让体积减少 2/3。
3. 第二刀:引擎置换手术 (减重核心)
这是最关键的一步。pip install paddlepaddle 安装的是一个通用型巨无霸。
核心思路:
-
训练时:在电脑上用 PaddlePaddle(功能全,体积大)。
-
部署时:在手机上用 ONNX Runtime(专注推理,体积极小)。
ONNX (Open Neural Network Exchange) 是 AI 界的“通用货币”。所有的模型(PyTorch, TensorFlow, Paddle)都可以转换成 ONNX 格式,然后用同一个轻量级引擎运行。
步骤 A:模型转换 (在电脑上操作)
首先,把你的 Paddle 模型转换成 .onnx 文件。百度贴心地提供了 paddle2onnx 工具。
# 1. 安装转换工具 pip install paddle2onnx # 2. 转换模型 (假设你的模型存放在 inference_model 文件夹) paddle2onnx --model_dir ./inference_model \ --model_filename model.pdmodel \ --params_filename model.pdiparams \ --save_file mobile_model.onnx \ --opset_version 11
现在你得到了一个通用的 mobile_model.onnx。
步骤 B:修改 Gradle 依赖 (Android端)
修改 app/build.gradle 的 Python 配置,把巨大的 paddle 换成小巧的 onnxruntime。
defaultConfig {
python {
pip {
// ❌ 移除这个巨无霸
// install "paddlepaddle==2.5.0"
// ✅ 换成这个轻量级选手 (约 5-8MB)
install "onnxruntime"
install "numpy"
}
}
}
步骤 C:重写 Python 推理代码
我们需要修改 ai_engine.py,把 Paddle 的调用换成 ONNX Runtime 的调用。逻辑几乎一样,只是 API 变了。
# src/main/python/ai_engine.py import numpy as np import onnxruntime as ort from os.path import dirname, join class AIModel: def __init__(self): # 获取模型路径 (假设你把 onnx 文件放在了 src/main/python 目录下) model_path = join(dirname(__file__), "mobile_model.onnx") # 初始化 ONNX 推理会话 #这是最耗时的步骤,建议在后台线程做 self.session = ort.InferenceSession(model_path) # 获取输入层名称 (就像知道插座的形状) self.input_name = self.session.get_inputs()[0].name def predict(self, input_data): # 1. 数据预处理 (和之前一样,转为 numpy) # 注意:ONNX 对数据类型要求很严,必须匹配模型定义 (通常是 float32) data = np.array([[float(input_data)]], dtype=np.float32) # 2. 执行推理 # run(输出节点名列表, 输入字典) result = self.session.run(None, {self.input_name: data}) # 3. 解析结果 # result 是一个列表,取出第一个输出 raw_val = result[0][0][0] return f"ONNX 极速推理结果: {raw_val:.2f}"
4. 进阶深潜:压榨最后 1MB
如果你对体积有极致的强迫症,这里还有两个“黑魔法”:
技巧 1:移除 Python 标准库中的废物
Chaquopy 默认会打包完整的 Python 标准库(包括你根本用不到的 email, html, multiprocessing 等模块)。
在 build.gradle 中可以配置剔除:
python { // ... pyc { // 编译成 pyc 字节码,加载更快,体积更小 src false } // 剔除不需要的标准库模块 extractPackages "json", "os", "sys" // 仅举例,慎用 }
注意:通过 buildPython 自定义 Python 构建来剔除标准库比较复杂,通常对于新手,开启 .pyc 编译已经能节省不少空间。
技巧 2:动态加载模型
不要把 .onnx 模型文件打包在 APK 的 assets 或 python 目录里。
-
做法:APK 里只放代码。用户第一次打开 App 时,从你的服务器下载模型文件到手机本地目录。
-
收益:APK 体积瞬间减少 5MB - 50MB(取决于模型大小)。
📊 瘦身成果对比
| 优化阶段 | 包含组件 | 预估 APK 大小 | 备注 |
| 原始版 | PaddlePaddle + 全架构 .so | 120MB+ | 用户看到会被吓跑 |
| 阶段一 | abiFilters "arm64-v8a" | 60MB | 砍掉了一半,但还是大 |
| 阶段二 | ONNX Runtime 替换 Paddle | 25MB | 达成目标! 🎯 |
| 阶段三 | 开启 pyc 编译 + 移除冗余库 | 18MB | 极致轻量 |
🏁 总结
要让 Python AI 应用在 Android 上兼顾开发效率和落地体验,核心逻辑是:
“Python 写逻辑,ONNX 做引擎,Gradle 砍架构。”
-
ABI Filter 是必须的。
-
Paddle/PyTorch/TF 只是训练工具,不要把它们带进 APK。
-
ONNX Runtime 是端侧部署的最佳伴侣。
🚀 Next Step
现在你的 App 既聪明又轻盈。但还有一个问题:安全性。
你的 Python 代码和模型文件在 APK 里几乎是“裸奔”的,黑客解压 APK 就能拿到你的核心算法。
浙公网安备 33010602011771号