为图像提供预设建议:构建 VSCO 中的“照片专用”功能
特邀作者 / VSCO 工程团队
在 VSCO (https://vsco.co/) 中,我们为您构建了个性化的创意工具、多种功能空间以及社交网络的链接。除了公开点赞、发表评论及查看粉丝数量等功能外,我们的应用还为用户提供图像视频的创建和编辑、发掘新技巧和新创意,并能够接入充满活力的全球社区。
我们使用机器学习来提供个性化定制,并为每位用户的创意流程提供指导。VSCO 为调整图片效果而提供了一系列多达 160 种预设,甚至还支持胶片相机的模拟图像。
未应用任何滤镜的建筑物照片。Sarah Hollander 所摄图像(左)。应用 AU5 预设后的建筑物照片(右)。
但在我们的研究中发现,这一系列的预设会让用户感到手足无措。因为太多的选择往往会导致用户坚持使用自己所熟悉和偏爱的少数预设,而不会去尝试新的预设。
解决方案
我们的挑战是需要为用户在编辑图片进行创作留有余地的同时,同时给用户提供可靠的建议并且鼓励他们去自行探索。我们的图像团队为了满足不同种类的图形而精心提供了多个预设,这让我们能够为每张照片分别提供个性化的建议。
为解决上述问题,我们决定借助设备端机器的学习和采用深度卷积神经网络 (CNN) 模型来为图像提供预设建议。因为这些模型能够理解图像中的众多细微差别,所以在分类上,相较于传统的计算机视觉算法更为便捷和快速。
基于这种思路,我们开发出了“照片专用(For This Photo)”功能。该功能使用设备端的机器学习来识别所编辑的照片类型进而在策划列表中提供相关的预设建议。“相片专用” 功能深受用户喜爱,现已成为仅次于“All(用于显示所有预设)”的第二大常用功能类。
“相片专用” 功能应用视频
为了让用户了解该功能运作流程,我们将会逐一介绍相关步骤。用户在使用“照片专用” 功能进行视图编辑,当加载图像时,模型会立即启动推理作业,并为该图像返回一个类别。随后,模型会将类别 ID 与缓存目录中的 ID 进行匹配,并会返回一个与该类别相符的预设列表。之后在“照片专用”部分中将显示六个预设选项供用户参考,这些预设由免费预设和 VSCO 会员专属预设组成。通过免费和付费预设的对比,为用户提供实用参考。非会员用户在预览 VSCO 会员专属预设之后,便能了解 VSCO 会员服务的价值所在。而会员所能享受的优势在于,他们能够通过会员服务了解可采用会员专属预设的图像类型。
设备端机器学习有助确保可访问性、实现快速编辑并保护隐私
研究伊始,我们便已了解基于服务器的机器学习不适用于此功能。我们希望此功能使用设备端机器学习主要基于三大原因:设备端机器学习支持离线编辑、可实现快速编辑并能保护隐私。
首先,我们并不希望仅在会员在线时才提供此功能,因为这会限制他们的创造力。灵感可以随处迸发:人们可能会在网络连接受限的情况下拍摄和编辑照片,例如沙漠中央或是高山之巅。我们的用户群中有许多人都身处美国境外,因此并非人人都能随时访问高速网络。
其次,我们希望确保实现快速编辑。若我们采用云端机器学习模型并以此提供“相片专用” 功能,需要上传用户图像并进行分类(这会耗费大量时间、带宽和流量),而用户亦需下载预设;即便网络连接状态良好,整个过程亦十分缓慢,如果网络不佳,甚至都无法完成。若在设备端运行机器学习,则表示全部流程都发生在本地,运行速度快且无需网络连接。这对于确保用户捕捉精彩瞬间并保持创意至关重要。
第三,编辑过程不用公开。服务器端解决方案需要我们让用户上传仍在编辑且未发布的照片。设备端机器学习有助于用户在创作期间保护他们的隐私。
为什么选择 TensorFlow
既然我们希望使用自定义模型来开展设备端机器学习,那么 TensorFlow Lite 显然就是最佳之选。因为该框架能够轻松提取基于服务器训练的模型,并能使用 TFLiteConverter 将该模型转换为可与手机兼容的格式(.tflite 格式)。
注:TFLiteConverter 链接
https://www.tensorflow.org/api_docs/python/tf/lite/TFLiteConverter
此外,我们已在服务器端机器学习生产系统中进行验证:TensorFlow 与 TensorFlow Serving 均可成功运行。TensorFlow 库的设计是以在生产环境中运行机器学习为首要重点,因此我们认为 TensorFlow Lite 也不例外。
我们使用 ML Kit (https://developers.google.com/ml-kit) 直接在 TensorFlow Lite 模型上运行推理,并将其无缝整合至我们的应用中。借此,我们便可将原型中的功能快速引入预生产环境。ML Kit 能够为初始化和加载模型及对图像运行推理提供更高级别的 API,这让我们无需直接处理更低级别的 TensorFlow Lite C++ 库,从而能够大幅加快整个开发流程,并能为我们训练模型腾出更多时间。
VSCO 机器学习堆栈概览
在机器学习堆栈方面,我们使用 TensorFlow 来对图像进行深度学习,并使用 Apache Spark 对行为数据进行浅层学习。
注:Apache Spark 链接
https://spark.apache.org/
在生产环境中,我们有一个基于云端并使用 TensorFlow Serving 的实时推理流水线,该流水线负责处理每一张通过各类卷积神经网络实时上传至 VSCO 的图像。之后,这些模型的推理结果会用于产品中其他功能,如“相关图像”、“搜索”、“为您定制”和“发现” 功能等的其他选项卡。对于设备端的机器学习,我们使用 TensorFlow 生态系统中适于移动端的组件(即 ML Kit 和 TensorFlow Lite)。
相关图像
为您定制
搜索
用户建议
我们还拥有一个基于 Spark 的推荐引擎,该引擎可使用数据存储中不同来源的大型数据集来训练模型,而这些来源包括图像元数据、行为事件和关系数据。之后,我们使用这些模型的结果来服务于各种形式的个性化推荐,如用户建议。
为支撑机器学习流水线的其他环节,我们还使用 Elasticsearch 实现搜索和相关功能,使用 Apache Kafka 处理基于日志的分布式数据流(此数据流亦作为所有机器学习模型的输入),并使用 Kubernetes 部署所有微服务。我们使用的语言包括 Python、C++、Go、Scala;在对设备端进行集成时,我们则使用 Java/Kotlin 和 Swift/Object-C。
注:Elasticsearch 链接
https://www.elastic.co/products/elasticsearch
Apache Kafka 链接
https://kafka.apache.org/
Kubernetes 链接
https://kubernetes.io/
设备端机器学习:“照片专用”工作原理
第一步:对图像进行分类
为构建能够提供“照片专用” 功能的模型,我们首先需为图像分配一个类别,然后为该类别推荐相应的预设。下图描绘了图像分类过程:
对图像进行分类
我们从公司内部专业人士所标记的图像数据开始入手。这些专业人士均为摄影专家,能够掌握用户行为的第一手资料,因此他们比任何人都更加了解现今分享的内容类型以及未来的发展趋势。他们帮助工程团队构想出了适用于模型的多种图像类别,其中包括艺术、肖像、活力、海岸、自然、建筑、光影、黑白等。俗话说,机器学习 90% 的工作都是在清理数据。这些步骤有助于确保我们拥有基于稳定可靠的数据来训练模型。
在 TensorFlow 中,我们使用与专业人士一同创建的分类数据集,并基于 SqueezeNet (https://arxiv.org/abs/1602.07360) 架构训练了一个 CNN 模型。选择此架构是因为其尺寸更小,且准确率更高。通过使用 TFLiteConverter,我们已将训练后的模型从 TensorFlow Saved Model 格式转换为 TensorFlow Lite (.tflite) 格式,以便在 Android 上使用。此阶段中发生了基本错误,其中一个原因在于,我们所使用的 TFLiteConverter 版本与 ML Kit 通过 Maven 引用的 TensorFlow Lite 库版本不相符。ML Kit 团队帮助我们解决了以上问题,并在我们研究期间发挥了巨大作用。
注:TFLiteConverter 链接
https://www.tensorflow.org/api_docs/python/tf/lite/TFLiteConverter
1graph_def_file = “model_name.pb”
2input_arrays = [“input_tensor_name”] # this array can have more than one input name if the model requires multiple inputs
3output_arrays = [“output_tensor_name”] # this array can have more than one input name if the model has multiple outputs
4
5
6converter = lite.TFLiteConverter.from_frozen_graph(
7 graph_def_file, input_arrays, output_arrays)
8tflite_model = converter.convert()
9open("converted_model.tflite", "wb").write(tflite_model)
在构建出可为图像分配类别的模型后,我们就可以将该模型捆绑至应用中,然后搭配使用 ML Kit 对图像运行xn。由于我们使用的是自定义训练模型,因此我们采用了 ML Kit 中的 Custom Model API。为获得更高准确率,我们决定放弃模型转换中的量化步骤,转而使用 ML Kit 中的浮点模型。这其中存在一些挑战,因为 ML Kit 会默认采用量化模型。不过,我们轻而易举就成功更改了模型初始化中的一些步骤,从而令其支持浮点模型。
注:Custom Model API 链接
https://firebase.google.com/docs/ml-kit/use-custom-models
1// create a model interpreter for local model (bundled with app)
2FirebaseModelOptions modelOptions = new FirebaseModelOptions.Builder()
3 .setLocalModelName(“model_name”)
4 .build();
5modelInterpreter = FirebaseModelInterpreter.getInstance(modelOptions);
6
7// specify input output details for the model
8// SqueezeNet architecture uses 227 x 227 image as input
9modelInputOutputOptions = new FirebaseModelInputOutputOptions.Builder()
10 .setInputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 227, 227, 3})
11 .setOutputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, numLabels})
12 .build();
13
14// create input data
15FirebaseModelInputs input = new FirebaseModelInputs.Builder().add(imgDataArray).build(); // imgDataArray is a float[][][][] array of (1, 227, 227, 3)
16
17// run inference
18modelInterpreter.run(input, modelInputOutputOptions);
19view raw
第二步:推荐预设
下一项挑战是基于图像类别提供预设建议。我们与创建预设的内部图像团队进行合作,共同构想出与各类别图像相契合的预设列表。此过程包括对分属各类别的众多图像分辨进行了严格测试,以便我们能够分析出每个预设对不同颜色的影响。此外,我们还拥有一个策划目录,其中包含了与各类别相对应的预设。
为图像提供预设建议
随着我们在会员服务中不断添加新预设,这些策划目录亦将逐步更新。为了便于我们随时更新这些列表,并让用户免于更新应用,我们已将这些目录存储在服务器上,并使用 API 对用户提供服务。
该 API 是由 Go 语言编写的微服务,支持移动客户端定期检查更新,从而确保拥有最新版目录。移动客户端可缓存此目录,并仅在新版目录推出时才开始获取。然而,对于在首次尝试此功能之前尚未连接互联网的用户,此方法会为其带来“冷启动”问题,即应用无法接入 API 并下载这些目录。我们决定在发布应用时随附以上目录的默认版来解决这个问题。借此,所有用户便能在任何网络连接状态下使用该功能,而这也与该功能的初始目标相契合。
结果与结论
通过“照片专用” 功能,现在可以顺利地使用预设进行编辑。我们认为,若会员无法从所获的新预设中发掘价值,他们的创意实现亦将遭遇阻碍。我们不仅希望帮助更多用户发掘新预设,还希望他们关注与所编辑的图像最相配的预设。
我们将持续优化“照片专用” 功能,根据其他图像特征和用户的社区行为(如关注、收藏和转发)来提供推荐。此外,我们也希望为此类推荐提供更实用的背景信息,同时鼓励我们的社区创作者互相能够积极发掘与激励。
在畅想此功能未来愿景的同时,我们也在反思。我们意识到,若没有 TensorFlow Lite 与 ML Kit,此功能以及 VSCO 的设备端机器学习能力都将无法实现。我们乐于未来在此领域继续投入更多的人力和物力,并利用该技术创造更多的功能。
更多案例: