亚马逊AWS官方博客
使用 DJL (Deep Java Library) 和 Spring Boot 在您的微服务中采用机器学习
很多 AWS 客户(包括初创公司和大型企业)都正在其现有应用程序中采用机器学习和深度学习。行业的创新速度促使各企业采用机器学习,其涉及的业务使用案例从客户服务(包括从图像和视频流进行对象检测、情绪分析)到欺诈检测与协作不等。然而,直到最近,采用学习曲线仍然相当陡峭,需要用新的编程语言(例如 Python)和框架开发内部技术专业知识,从而对从编写代码到构建、测试和部署的整个软件开发声明周期产生级联效应。本博客文章中所述的方法可使企业利用现有的才能和资源(框架、管道和部署)来集成机器学习功能。
简介
Spring Boot 是用于微服务开发的最常用且使用最广泛的开源框架,对分布式系统的实施进行了简化。
尽管此框架具有广泛的吸引力,但将它在本机与 Machine Learning (ML) 轻松集成的选项很少。现有解决方案(例如库存 API)通常不满足定制的应用程序要求,且开发定制解决方案很耗时,且不具有成本效益。
开发人员采用多种方式将机器学习功能集成到现有的应用程序中。以推理为例,当前选项从使用库存 API 到将使用远程调用 API 包装基于 Python 或 C++ 的应用程序用不等。库存 API 虽然基于稳健的模型,但可能不太适合您的域或行业,从而导致在生产中发现问题,且解决这些问题的选项很少。在其他情况下,当大规模运行推理(例如,在流式传输应用程序或延迟敏感型微服务中)时,出于性能原因,进行远程调用可能不是可行选项。
认识到这一挑战后,AWS 创建了几个开源项目,以促进 Java 和微服务采用 ML,从而最终帮助我们的客户、合作伙伴以及整个开源社区。这些计划与 AWS 目标紧密契合,利用历来成本高昂且难以被许多组织采用的技术,并使这些技术能被更加广泛的受众使用。
在本博客文章中,我们将演示 Java 用户如何使用适用于 Deep Java Library (DJL) 的 Spring Boot Starter 将 ML 集成到他们的 Spring 应用程序中。我们将回顾如何实际应用这些框架及如何将 ML 功能集成到微服务中,从而演示深度学习在对象检测和分类中的常见使用案例。
DJL 概述
Deep Java Library (DJL) 是一个适用于深度学习的开源、高级别、无框架无关的 Java API。它容易入门,并且对于 Java 开发人员来说使用非常简单。DJL 提供本机 Java 开发体验和功能,就像其他常规 Java 库一样。
DJL 提供方便的抽象层来使用最常见的 AI/ML 框架,例如 Apache MXNet、PyTorch 和 TensorFlow。然而,它不仅是在现有库(其中一些提供 Java API / 绑定)上使用方便。使用 DJL API,您将获得均匀一致的层,它可以与上述所有框架进行交互,从而使您能够交换您选择的框架,而不对客户端代码造成任何影响。
这一独特的功能结合相对丰富的模型园存储库(带有预训练模型的存储库)使 ML 工程师能够为手边的任务查找最佳模型,无论底层模型实施如何。
有关 DJL 的更多信息,请参阅 DJL GitHub 存储库和常见问题。
DJL Spring Boot Starter
Spring Boot Starter 是为您的项目所需的所有 Spring 和相关技术提供的一站式服务,使您不必再搜寻示例代码并对依赖性描述符进行复制粘贴操作。请参阅 Spring Boot 正式文档了解有关入门版的更多信息。
按照此定义,DJL Spring Boot Starter 将在 Spring 中开始使用 DJL 所需的所有依赖项提供为一个构件。除了依赖项管理之外,该入门版还包括自动配置功能,通过该功能,可以基于用户提供的配置文件自动连接依赖项,并使它们成为 Spring 应用程序上下文中的内容。
依赖项管理
DJL 库的特定于平台的,但它提供基于目标操作系统自动查找正确依赖项的方式。DJL 还可以配置不同的底层引擎(例如 MXNet、PyTorch 或 TensorFlow);用户应该在使用入门版之前进行此选择。然而,即使进行了此选择后,也可以通过修改 Maven(或 Gradle)依赖项来更改底层引擎和目标操作系统架构,而不对您的代码造成任何影响。
入门版依赖项管理的组织方式可为用户提供最大的灵活性。
对于 MXNet 入门版,支持以下操作系统分类器:适用于 Mac OS X 的 osx-x86_64
、适用于通用 Linux 的 linux-x86_64
、适用于 Windows 发行版的 win-x86_64
,以及适用于自动检测目标操作系统的 auto
。最后一个选项需要在运行时连接到外部构件存储库(例如 Maven Central),这对于安全限制严格且传入受限的系统来说可能是个问题。
下面是适用于 Linux 架构的 MXNet 依赖项的示例,针对容器工作负载进行了优化:
将在运行时下载正确构件的 Auto
依赖项:
将 PyTorch
用作底层引擎时,入门版依赖项为:
Gradle 依赖项看起来类似。重要的是,在 gradle.properties
内将 JNA 版本设置为“jna.version=5.3.0
”,因为 Spring Boot 的父级 POM 使用旧版 JNA,它不能与 DJL 入门版一起工作。下面是 Gradle 构建文件 build.gradle.kts
的 示例(在本示例中,使用 Kotlin DSL),前提是假设已注册 Spring Boot 插件:
Spring 自动配置
在您的 Spring Boot 应用程序中正确配置依赖项后,下一步是配置内容并适当连接它们以进行注入。配置与 DJL 相关的内容并将它们提供在 Spring 应用程序上下文中很容易,但它需要库的内部知识以及适当确定范围的各个类的特性,例如,有些内容具有线程安全性,有些则应按照请求/线程确定范围。为帮助进行此配置,DJL Spring Boot 入门版提供了自动配置。
此组件与依赖项组件是分开的,需要显式依赖项。我们这样做有几个原因:
- 有些开发人员更喜欢完全控制配置选项,且可能不希望 Spring 施展“自动魔力”。在此情况下,入门版将仅支持基本依赖项集,并且使开发人员显式连接组件。
- 自动配置组件对于所有类型的 DJL 配置都是通用的:无论底层目标操作系统或实际引擎如何,自动配置组件都保持相同。因此,使用相同的自动配置,开发人员可以将底层依赖项作为单步操作进行交换,而对代码不产生任何影响。
在 Maven 中声明自动配置的依赖项:
或者在 Gradle build.gradle.kts
中:
声明依赖项后,Spring Boot 框架将自动查找配置并连接所需的组件。当前,为了进行推理,它将从模型园存储库中查找模型,并创建一个可随时用于运行推理的预测工具。
用户应该提供标准的 Spring 配置(application.yml
或 application.properties
)模型来使用受支持的应用程序类型之一:
例如,为了在图像中运行对象检测,用户可以将应用程序类型设置为 OBJECT_DETECTION
。与 DJL 相关的配置应在 djl
根下提供命名空间,例如,如果使用 application.properties
,则为 djl.application-type=OBJECT_DETECTION
。
下面是 DJL 自动配置的 yaml
配置示例: