作者:围城之上
编辑:夏歌
偶然间看到了 Second State 和腾讯云联合举办的 AI 推理函数活动,试了一下食物识别的模板函数,识别结果还是挺准确的。而且听说来了就有奖品,作为资深动手实践者(羊毛党)怎么能错过?这是第一次使用云函数部署 AI 模型,不用自己搭建服务器,还挺有意思的。正好利用周末时间,经过一番学习和摸索终于完成任务:做了一个通用物体识别的 Serverless AI 推理函数。我们的征途是星辰大海,可不能被美食所阻挡。
先让我们来看看效果图吧,第一位萌物嘉宾闪亮登场。
(Haru是Second State 台北办公室的团宠 ,Haru在日语里是春天的意思)
Haru 是混种猫,你能看出 Haru 是什么品种的猫吗?动物识别已经是老生常谈,但是可不可以识别出特定种类呢?首先来试一试这个 Serverless AI 推理函数可不可以识别出猫的特定种类。
(经过咨询 Haru 的主人,主人也不知道 Haru 是什么品种了,毕竟是混种猫,AI 说是埃及猫,那就是吧)
再来试试我的 Mac Book 吧,同时出镜的还有与我朝夕相处的搭档。你也可以在线体验一下,看看这个 TensorFlow 模型准不准。
甚至连火车都可以识别出来。
这个 Serverless AI 推理函数的想法源自于《全新开发体验!腾讯云 serverless 助力你的 AI 模型进入生产环境》这篇文章。
想直接看源码的朋友,点击这里。
在这里,我选用了 tensorflow 提供的 mobiletnet 中的量化模型 mobilenet_v1_1.0_224_quant,这个模型可以识别1000多种物品,除了我们身边常见的小动物和日用品,识别楼房飞机也不在话下。
但是毕竟是受模型精度所限,可能对某些细分种类做不到很高的覆盖,大家如果有兴趣,可以自己做迁移学习来训练地标建筑的模型,或者是找到其他具体种类的模型,来生成一个 Serverless AI 推理函数。比如 Second State 出的鸟类识别 Serverless 函数和昆虫类识别 Serverless 函数。
代码逻辑并不复杂,准备模型,上传图片 、运行TensorFlow 模型、返回结果都是由 Rust 实现的。
// 加载训练好的 TensorFlow lite 模型。
let model_data: &[u8] = include_bytes!("mobilenet_v1_1.0_224_quant.tflite");
// 上传图像的格式是 base64 编码,并通过腾讯云 API 网关封装在 JSON 对象中。
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer).expect("Error reading from STDIN");
let obj: FaasInput = serde_json::from_str(&buffer).unwrap();
let img_buf = base64::decode_config(&(obj.body), base64::STANDARD).unwrap();
// 加载上传图像并将其调整为224x224,这是这个 MobileNet 模型所需的尺寸,后面会介绍如何快速获得这个数据
let flat_img = ssvm_tensorflow_interface::load_jpg_image_to_rgb8(&img_buf, 224, 224);
// 用图像作为输入张量运行模型,并获取模型输出张量。
let mut session = ssvm_tensorflow_interface::Session::new(&model_data, ssvm_tensorflow_interface::ModelType::TensorFlowLite);
session.add_input("input", &flat_img, &[1, 224, 224, 3])
.run();
let res_vec: Vec = session.get_output("MobilenetV1/Predictions/Reshape_1");`
res_vec
向量包含图像中每个对象的概率列表(例如,该图像中蛋糕的概率为0.8)。 下面的 Rust 代码读取这些对象的标签,并从 Tensorflow 模型输出中以最高概率打印出对象标签。
let labels = include_str!("labels_mobilenet_quant_v1_224.txt");
let mut i = 0;
let mut max_index: i32 = -1;
let mut max_value: u8 = 0;
while i < res_vec.len() {
let cur = res_vec[i];
if cur > max_value {
max_value = cur;
max_index = i as i32;
}
i += 1;
}
let mut label_lines = labels.lines();
for _i in 0..max_index {
label_lines.next();
}
let class_name = label_lines.next().unwrap().to_string();
if max_index != 0 {
println!("上传的图片里面{} {}", confidence.to_string(), class_name, class_name);
} else {
println!("上传的图片里面没有检测到任何物体");
}
}`
这里的代码逻辑与模板函数基本一致,只是替换了模型与图像参数。整体来说,这个模板函数可以快速将 AI 推理带到可使用的状态,且腾讯云每月会给个人开发者一定额度,所以使用这个模板函数做一个自己的 side project ,可以说是既省心又省钱。
在这一部分,我来分享一些替换 TensorFlow 模型过程中的一些小建议,希望大家少走弯路,可以快速做出自己的 Serverless AI 推理函数。
Wasm 的库还不太完善,这一步可以先用 python 实现。
python model_test.py
然后会得到下面的信息,这里的信息对应了 main.rs 文件的重要参数,可以直接进行修改。否则 output 的 res_vec 一直都是 0。
Item | Value |
---|---|
input demension | [1, 224, 224, 3] |
input layer name | input |
output layer name | MobilenetV1/Predictions/Reshape_1 |
在部署过程中,文件 permission 发生了改变,变成了 Bootstrap not executable 。这个问题有 Serverless 社区的开发者提供了一种解决方案,我这里再提供一种解决方案。
在腾讯云 console 中,进入“函数服务” – “函数管理”,右键一个文件,选择 “在集成终端中打开”, 确保自己在文件目录下,然后执行下面的命令,让 bootstrap 文件有执行权限,最后 deploy 就好了。
chmod -R 777 .
不过,根据腾讯云 serverless 产品经理的最新说法,这个问题已经得到了解决,更新到最新版本的 cli 就可以啦。如果还出现了 Bootstrap not executable 的问题,可以用 sls deploy —force 部署。
在这个过程中还有环境搭建与本地测试的小建议,详细过程可以去 readme 文件阅读。
本文项目里使用的模型是很多人做移动端物体识别的“启蒙”模型。借助本次 Second State 的 Serverless AI 推理函数模板非常简单方便地就在云函数服务上部署了 AI 应用,同时在这个过程也看到了 Rust 编译成的 WASM 提供前端 JS 调用的高性能解决方案的广阔前景。
识别物体的源码
Serverless AI 推理函数模板
WebAssembly 虚拟机 SSVM