Microsoft Machine Learning Server 使用调研
Machine Learning Server 主要功能
Micorosft Machine Learning Server 前身就是 Microsoft R Server ,加入了 Python 支持后更名。主要用于数据分析模型的商业化使用,并提供分布式、并行等计算功能。
支持以下平台:
- Windows
- Hadoop
- Linux
Machine Learning Server 主要提供以下功能:
功能 | R | Python |
---|---|---|
在 Machine Learning Server 中运行 R 代码 | o | |
使用 RevoScalePy 创建 Python 代码 | o | |
使用 MicrosoftML 进行二分分类 | o | |
将模型作为 Web 服务发布 | o | o |
Machine Learning Server 的特性:
- 无论您的数据存在于何处,都可以获得高性能的机器学习
- 微软和开源的最佳人工智能创新
- 简单,安全,高规模的操作和管理
- 深入的生态系统参与,以最佳的总体拥有成本实现客户成功
Machine Learning Server 的使用是与 Microsoft R Client 结合进行的。Microsoft R Client 相当于一个 R 的发行版,内置了一些专用的函数,可以进行远程运行代码以及发布 Web 服务。
RevoScaleR 库
提供了一系列 rx
开头的函数,这些函数可以与 Machine Learning Server 结合运行。
数据处理
rxImport
从文本文件、 SAS 、 SPSS 、 SQL Server 、 Teradata 或 ODBC 连接导入数据。原生的数据类型是 XDF 格式。
1 | inDataFile <- file.path(rxGetOption("sampleDataDir"), "mortDefaultSmall2000.csv") |
关于 Machine Learning Server中的数据存储
在 Machine Learning Server 中,您可以将内存数据用作数据框,或将其作为 XDF 文件保存到磁盘。如上所述,
rxImport
可以使用或不使用 .xdf 文件创建数据源对象。如果省略outFile
参数或将其设置为NULL
,则返回对象是包含数据的数据框。数据框是 R 中的基本数据结构,在机器学习服务器中完全支持。它是表格,由行和列组成,其中列包含变量,第一行(称为标题)存储列名。后续行为与单个观察相关联的每个变量提供数据值。数据框是在加载某些数据时创建的临时数据结构。它仅在会话期间存在。
.xdf 文件是 Machine Learning Server 本机的二进制文件格式,用于在磁盘上保存数据。 .xdf 文件的组织是基于列的,每个变量一列,这对于统计和预测分析中使用的数据的可变方向是最佳的。使用 .xdf ,您可以加载数据的子集以进行目标分析。此外, .xdf 文件包括可立即使用的预先计算的元数据,无需额外处理。
不需要创建 .xdf ,但是当数据集很大或很复杂时, .xdf 文件可以通过压缩数据和将数据分配到可以独立读取和刷新的块来提供帮助。此外,在像 Hadoop 的 HDFS 这样的分布式文件系统上, XDF 文件可以将数据存储在多个物理文件中以容纳非常大的数据集。
rxGetInfo
一次快速获取有关数据集及其变量的信息,包括有关变量类型和范围的更多信息。
1 | rxGetInfo(mortData, getVarInfo = TRUE, numRows=3) |
rxDataStep
为大多数数据操作任务提供了一个框架。 它允许行选择(rowSelection参数),变量选择(varsToKeep或varsToDrop参数),以及从现有变量创建新变量(变换参数)。
1 | outFile2 <- NULL |
数据分析
rxSummary
计算变量的表属性统计信息
1 | rxSummary(~ ArrDelay, data = airXdfData) |
1 | rxSummary(formula = ~ArrDelay + CRSDepTime + DayOfWeek, data = airDS) |
1 | rxSummary(~ArrDelay:DayOfWeek, data=airXdfData) |
rxLinMod
线性回归
1 | arrDelayLm2 <- rxLinMod(ArrDelay ~ DayOfWeek, data = airXdfData, |
rxCrossTabs
数据交叉表
1 | myTab <- rxCrossTabs(ArrDelay~DayOfWeek, data = airLateDS) |
rxLogit
Logistic 回归
1 | logitObj <- rxLogit(Late~DepHour + Night, data = airExtraDS) |
rxPredict
预测
1 | predictDS <- rxPredict(modelObject = logitObj, data = airExtraDS, |
数据可视化
R 中常用的可视化函数都有对应的 rx 版本。
rxHistogram
绘制直方图
1 | rxHistogram(~ArrDelay|DayOfWeek, data = airXdfData) |
rxLinePlot
绘制折线图
1 | rxLinePlot(ArrDelay~DayOfWeek, data = countsDF, |
1 | rxLinePlot(ArrDelay~CRSDepTime|DayOfWeek, data = arrDelayDT, |
在 Machine Learning Server 中运行 R 代码
计算上下文
在 Machine Learning Server 中,计算上下文是指处理给定工作负载的计算引擎的物理位置。 默认为本地。 但是,如果您有多台计算机,则可以从本地切换到远程,将以数据为中心的RevoScaleR(R),revoscalepy(Python),MicrosoftML(R)和microsoftml(Python)函数的执行推送到另一个系统上的计算引擎。 例如,在R Client中本地运行的脚本可以将执行转移到Spark集群中的远程机器学习服务器以在那里处理数据。
上下文 | 说明 |
---|---|
local | 所有平台上的所有产品(包括R Client)均支持默认值。 脚本使用本地计算机资源在本地解释器上执行。 |
remote | 专门针对选定数据平台上的机器学习服务器:Spark over Hadoop分布式文件系统(HDFS)和SQL Server。 客户端或以客户端身份运行的服务器可以启动远程计算上下文,但目标远程计算机本身必须是Machine Learning Server安装。 |
RevoScaleR 的上下文包括:
上下文 | 别名 | 用法 |
---|---|---|
RxLocalSeq | local | 所有服务器和客户端配置都支持本地计算上下文。 |
RxSpark | spark | 远程计算上下文。 目标是Hadoop上的Spark集群。 |
RxInSqlServer | sqlserver | 远程计算上下文。 目标服务器是单个数据库会话(SQL Server 2016 R服务或SQL Server 2017机器学习服务)。 计算是平行的,但不是分布式的。 |
RxLocalParallel | localpar | 计算上下文通常用于依靠您提供的指令而不是Hadoop上的内置调度程序来启用受控的分布式计算。 您可以将计算上下文用于手动分布式计算。 |
RxForeachDoPar | dopar | 用于手动分布式计算。 |
上下文支持的数据格式
Data Source | RxLocalSeq | RxSpark | RxInSqlServer |
---|---|---|---|
RxTextData | X | X | |
RxXdfData | X | X | |
RxHiveData | X | X | |
RxParquetData | X | X | |
RxOrcData | X | X | |
RxOdbcData | X | ||
RxSqlServerData | X | X | |
RxSasData | X | ||
RxSpssData | X |
当数据本身发生变化时,适用于切换上下文。计算应该都是在本地进行的,只是获取数据的上下文发生了改变。
远程执行 R 代码
远程执行是从机器学习服务器(或R服务器)或R客户端向另一个机器学习服务器实例上运行的远程会话发出R命令的能力。 您可以使用远程执行来卸载服务器上的繁重处理并测试您的工作。 在开发和测试分析时,它尤其有用。
远程执行支持以下几种方式:
- 在控制台应用程序中从命令行执行
- 在 R 脚本中通过调用 mrsdeply 包的函数执行
- 通过调用 API 的代码执行
远程执行可以实现的功能:
- 登陆和登出 Machine Learning Server
- 生成本地和远程环境的差异报告,并协调任何差异
- 远程执行 R 脚本或代码
- 远程使用 R 对象或文件工作
- 创建和管理远程环境的快照以供重用
远程执行的函数:
remoteExecute
用于在远程R会话中执行R代码块或R脚本的基本功能。remoteScript
一个简单的包装函数,用于执行远程R脚本。diffLocalRemote
在本地和远程之间生成“差异”报告。
创建远程会话
使用 mrsdeploy 包的登录函数 remoteLogin()
或 remoteLoginAAD()
在 Machine Learning Server 上进行验证。设置 session = TRUE
创建远程会话,并设置 commandline = TRUE
进入远程控制台。
1 | remoteLogin("http://localhost:12800", |
参数说明:
参数 | 描述 |
---|---|
endpoint | Machine Learning Server HTTP / HTTPS端点,包括端口号。 启动管理实用程序时,可以在第一个屏幕上找到此项。 |
session | 如果为 TRUE ,则创建远程会话。 如果省略,则创建远程会话。 |
diff | 如果为 TRUE ,则创建一个“差异”报告,显示本地会话和远程会话之间的差异。 参数仅在会话参数为TRUE时有效。 |
commandline | 如果为 TRUE ,则在R控制台中创建“REMOTE”命令行。参数仅在会话参数为 TRUE 时有效。如果省略,则与 = TRUE 相同。 |
prompt | 用于远程会话的命令提示符。 默认情况下,使用 REMOTE> 。 |
username | 如果为 NULL ,则提示用户输入您的AD或本地计算机学习服务器用户名。 |
password | 如果为 NULL ,则提示用户输入密码。 |
remoteLoginAAD()
函数用于 Azure 云的登录。
在会话间切换或退出
使用三个函数进行远程会话和本地会话切换,以及退出:
pause()
从远程会话切换到本地会话resume()
从本地会话切换到远程会话remoteLogout()
登出 Machine Learning Server
使用参数 session = TRUE
登录到远程R服务器后,将创建一个远程 R 会话。 您可以直接从命令行在远程 R 会话和本地 R 会话之间切换。 远程命令行允许您直接与另一台计算机上的 R Server 9.x 实例进行交互。
当R控制台中显示 REMOTE>
命令提示符时,输入的任何R命令都在远程R会话上执行。
使用以下函数在本地命令行和远程命令行之间切换:pause()
和 resume()
。 要切换回本地 R 会话,请键入“pause()
”。 如果已切换到本地R会话,则可以通过键入“ resume()
”返回远程 R 会话。
要终止远程R会话,请在REMOTE>提示符下键入“exit
”。 此外,要从本地R会话终止远程会话,请键入“remoteLogout()
”。
1 | #EXAMPLE: SESSION SWITCHING |
远程执行 R 脚本
如果本地计算机上有R脚本,则可以使用 remoteScript()
函数远程执行它们。 此函数采用远程执行R脚本的路径。 您还可以选择保存或显示脚本执行期间可能生成的任何图。 该函数返回一个列表,其中包含执行状态(成功/失败),生成的控制台输出以及创建的文件列表。
如果您的R脚本具有R包依赖项,则必须在 Microsoft R Server 上安装这些包。 您的管理员可以在服务器上全局安装它们,也可以使用 install.packages()
函数在远程会话期间自行安装它们。 将 lib
参数留空。
远程上下文的限制:
- 某些功能在执行时被屏蔽,例如“
help
”,“browser
”,“q
”和“quit
”。 - 在远程上下文中,您无法在命令行提示符下显示晕影或获取帮助。
- 在大多数情况下,“
system
”命令有效。 但是,写入stdout/stderr的系统命令可能不会显示其输出,也不会等到整个系统命令完成后才显示输出。install.packages
是我们在远程上下文中显式处理 stdout 和 stderr 的唯一例外。
要在远程脚本执行期间继续在开发环境中工作,可以异步执行 R 脚本。 当您运行具有较长执行时间的脚本时,异步脚本执行非常有用。要异步执行 R 脚本,请将 remoteScript()
的 async
参数设置为 TRUE
。 执行 remoteScript()
时,脚本将在新的远程 R 控制台窗口中异步运行。 所有 R 控制台输出和来自该执行的任何图都返回到同一窗口。
1 | #EXAMPLE: REMOTE SCRIPT EXECUTION |
远程使用R对象和文件
远程执行R代码后,您可能希望检索某些R对象并将其加载到本地R会话中。 例如,如果您有一个创建线性模型 m <-lm(x~y)
的R脚本,请使用函数 getRemoteObject()
来检索本地R会话中的对象 m
。
相反,如果您希望远程 R 会话可以使用本地 R 对象,则可以使用函数 putLocalObject()
。 如果要同步本地和远程工作空间,可以使用 putLocalWorkspace()
和 getRemoteWorkspace()
函数。
类似的功能可用于需要在本地和远程 R 会话之间移动的文件。以下函数可用于处理文件: putLocalFile()
、 getRemoteFile()
、 listRemoteFiles()
和 deleteRemoteFile()
。
1 | #EXAMPLE: REMOTE R OBJECTS AND FILES |
绘图的注意事项
远程绘制时,默认绘图大小为400 x 400像素。 如果您需要更高分辨率的输出,则必须告诉远程会话要创建的绘图大小。
在本地会话中,您可以更改宽度和高度,如下所示:
1 | > png(filename="myplot.png", width=1440, height=900) |
在处理REMOTE命令行时,您需要将这三个语句组合在一起:
1 | REMOTE> png(filename="myplot.png", width=1440, height=900);ggplot(aes(x=value, group=am, colour=factor(am)), data=mtcarsmelt) + geom_density() + facet_wrap(~variable, scales="free");dev.off() |
作为替代方法,您可以使用 remoteScript()
函数,如下所示:
1 | #Open a new script window in your IDE |
将模型作为 Web 服务发布
mrsdeploy
库提供了一些函数,使 R 模型可以作为 Web 服务发布。
主要流程
- 本地编写模型
- 将模型作为 Web 服务发布
- 在 R 中使用服务进行测试
- 获取基于 Swagger 的 JSON 文件
- 基于 Swagger 文件与 Web 服务集成
Swagger
大部分 Web 应用程序都支持 RESTful API,但不同于 SOAP API——REST API 依赖于 HTTP 方法,缺少与 Web 服务描述语言(Web Services Description Language,WSDL)类似的语言来定义使用者与提供者之间的请求和响应结构。由于没有充分的合同服务,许多 REST API 提供者使用 Microsoft Word 文档或维基页面来记录 API 用法。这些格式使协作和文档版本控制变得很困难,尤其对于有许多 API 或资源的应用程序,或者在 API 采用迭代式开发方式时。这些文档类型在集成到自动化测试应用程序中时变得更难。
开源 Swagger 框架帮助 API 使用者和开发人员纠正了这些问题。该框架为创建 JSON 或 YAML(JSON 的一个人性化的超集)格式的 RESTful API 文档提供了 OpenAPI 规范(以前称为 Swagger 规范)。Swagger 文档可由各种编程语言处理,可在软件开发周期中签入源代码控制系统中,以便进行版本管理。
发布服务
服务主要包括模型、代码两部分,模型即指一些模型对象,如 glm
函数的结果;代码是指调用模型的过程,主要对传输参数进行一些处理。
1 | # For R Server 9.0, load mrsdeploy package on R Server |
服务支持的参数的类型和返回值类型均为以下几种:
- numeric
- integer
- logical
- character
- vector
- matrix
- data.frame
如果 code
是函数,只有一个值可以返回。
代码和模型
区别
官方文档没有明确指出 Code 和 Model 的区别。但是从代码和性能分析的角度,可以发现 Code 和 Model 有以下区别:
- Model 部分的代码是发布服务的时候执行的, Code 部分则是在接收网络请求的时候执行的。因为 Model 部分只包含一个模型,不可能在每次网络请求中都执行,否则求解模型的时间会很长。在网络请求中, Model 部分会被加载到 Code 部分。
- Model 部分不接收网络请求的参数(即发布服务时指定的
inputs
),也不提供返回参数(即发布服务时指定的outputs
)。接收参数和返回参数的提供是在 Code 部分中进行的。 - Model 部分一般是 R 对象, Code 部分一般是可执行体。
由于有这样的区别,因此使用动态模型只能在 Code 中进行,而且最好将接口设计为异步接口。
类型
来源 | |
---|---|
Code | 指向 R 脚本的文件路径 |
字符串形式的 R 代码片段 | |
R 函数 | |
Model | 指向 .RData 文件的路径 |
指向 R 脚本的文件路径,用于加载环境 | |
模型对象,如 model = am.glm |
与 Web 服务集成
发布的 R 服务可以与 Web 服务集成。利用服务提供的 swagger.json 文件,可以使用 Swagger 自动生成 API 接口代码以及文档。主要流程为:
- 获取 Swagger 工具和文件
- 使用 Swagger 生成 API 库
- 添加认证逻辑
- 通过库与 API 交互或使用服务
以 mtService 与 ASP.NET 为例,首先创建 ASP.NET Web API 工程。
ASP.NET MVC 框架
MVC 是三个 ASP.NET 开发模型之一。
MVC 是用于构建 web 应用程序的一种框架,使用 MVC (Model View Controller) 设计:
- Model(模型)表示应用程序核心(比如数据库记录列表)。是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象在数据库中存取数据。
- View(视图)对数据(数据库记录)进行显示。是应用程序中处理数据显示的部分。通常从模型数据中创建视图。
- Controller(控制器)处理输入(写入数据库记录)。是应用程序中处理用户交互的部分。通常控制器从视图读取数据、控制用户输入,并向模型发送数据数据。
MVC 的这种拆分有助于我们管理复杂的应用程序,因为您能够在同一时间关注一个方面。例如,您可以在不依赖业务逻辑的情况下对视图进行设计。同时对应用程序的设计也更加容易。MVC 的这种拆分同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。
然后使用 AutoRest 或 Swagger Codegen 生成 C# 代码:
1 | AutoRest.exe -CodeGenerator CSharp -Modeler Swagger -Input swagger.json -Namespace Transmission |
会在 swagger.json 所在文件夹下创建一个 Generate 文件夹,里面保存了生成的代码,文件结构如下:
- Models
- AccessTokenResponse.cs
- BatchWebServiceResult.cs
- Error.cs
- ErrorException.cs
- InputParameters.cs
- LoginRequest.cs
- OutputParameters.cs
- RenewTokenRequest.cs
- RenewTokenRequest.cs
- StartBatchExecutionResponse.cs
- WebServiceResult.cs
- IMtService1556106844.cs
- MtService1556106844.cs
- MtService1556106844Extensions.cs
每个文件都包含一个类,这些类都声明在 Transmission
命名空间中,结合 C# 命名空间取值的特点,建议将这些文件放在 ASP.NET 工程根目录的 Transmission 目录下。
另外一种方式,是将命名空间声明为 RService.Transmission ,可以将 R 服务都放置在工程根目录的 RService 目录下(如将这个服务放置在工程根目录的 RService/Transmission 目录下),便于多个接口的管理。
然后 Controllers 文件夹下,创建一个 Web API 控制器类,命名为 MtServiceController
。即可生成一个 Controller 的基本代码。
基本代码如下:
1 | using System; |
该基本代码提供了 GET 、 POST 、 PUT 、 DELETE 四种 HTTP 请求类型的支持。现在只需要对这些进行修改。即可。
对带参数的 GET 方法进行修改的方法
将参数修改为两个:
hp
和wt
。直接修改public string Get(int id)
的声明:1
2- public string Get(int id)
+ public double? Get(double hp, double wt)即对 GET 方法添加了两个参数,都是
double
类型。创建 R 服务对象,指明服务基地址。
1
2
3
4public double? Get(double hp, double wt)
{
MtService1556106844 client = new MtService1556106844(new Uri("http://192.168.41.49:12800"));
}在有 SSL 证书时可以使用 HTTPS 协议。
添加服务的认证:在 Get 方法中使用 Transmission 库自带的
LoginRequest
类进行认证。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public double? Get(double hp, double wt)
{
MtService1556106844 client = new MtService1556106844(new Uri("http://192.168.41.49:12800"));
// --- AUTHENTICATE WITH ACTIVE DIRECTORY -----------------------------------------
// Note - Update these with your appropriate values
// Once authenticated, user won't provide credentials again until token is invalid.
// You can now begin to interact with the operationalization APIs
// --------------------------------------------------------------------------------
var loginRequest = new LoginRequest("admin", "GWmodel-Lab2018");
var loginResponse = client.Login(loginRequest);
//
// SET AUTHORIZATION HEADER WITH BEARER ACCESS TOKEN FOR FUTURE CALLS
//
var headers = client.HttpClient.DefaultRequestHeaders;
var accessToken = loginResponse.AccessToken;
headers.Remove("Authorization");
headers.Add("Authorization", $"Bearer {accessToken}");
}这里的用户名
admin
和密码GWmodel-Lab2018
是 Machine Learning Server 在启动的时候,设置的用户名和密码。调用 R 服务并返回结果:在 Get 方法中使用 Transmission 库调用 R 服务。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public double? Get(double hp, double wt)
{
MtService1556106844 client = new MtService1556106844(new Uri("http://192.168.41.49:12800"));
// --- AUTHENTICATE WITH ACTIVE DIRECTORY -----------------------------------------
// Note - Update these with your appropriate values
// Once authenticated, user won't provide credentials again until token is invalid.
// You can now begin to interact with the operationalization APIs
// --------------------------------------------------------------------------------
var loginRequest = new LoginRequest("admin", "GWmodel-Lab2018");
var loginResponse = client.Login(loginRequest);
//
// SET AUTHORIZATION HEADER WITH BEARER ACCESS TOKEN FOR FUTURE CALLS
//
var headers = client.HttpClient.DefaultRequestHeaders;
var accessToken = loginResponse.AccessToken;
headers.Remove("Authorization");
headers.Add("Authorization", $"Bearer {accessToken}");
InputParameters inputs = new InputParameters() { Hp = hp, Wt = wt };
var serviceResult = client.ManualTransmission(inputs);
return serviceResult.OutputParameters.Answer;
}
POST 方法、 PUT 方法的编写本质上和 GET 方法的编写没有什么区别。不同的地方在于, POST 方法中的参数通过请求体进行,而不是请求地址。参数类型可以直接声明为 InputParameters
类型,因为这个类型支持 JSON 反序列化。
1 | namespace Transmission.Models |
当请求体是如下的 HTTP 请求时,程序可以自动获取到这些参数:
1 | POST http://localhost:64620/api/MtService HTTP/1.1 |
另外,在 GET 等方法的返回值中,如果 R 服务的返回值类型是 vector 、 matrix 或 data.frame ,那么不能直接以 XML 返回,需要调用 ToString()
函数返回。但是可以直接以 JSON 返回。方法是:
1 | public double? Get(double hp, double wt) |
连接池
当您提前创建会话和加载依赖项时,可以快速连接到Web服务。 会话在专用于特定Web服务的池中可用,其中每个会话包括R解释器的实例和Web服务所需的依赖关系的副本。 例如,如果您为使用Matplotlib,dplyr,cluster,RevoScaleR,MicrosoftML和mrsdeploy的Web服务提前创建了10个会话,则每个会话都将拥有自己的R解释器实例以及内存中加载的每个库的副本。
具有专用会话池的Web服务从不请求来自通用会话池共享资源的连接,即使在达到最大会话时也是如此。 通用会话池仅为那些没有专用资源的Web服务提供服务。
mrsdeploy
提供以下三个函数来创建和管理会话:
- configureServicePool
- getPoolStatus
- deleteServicePool
创建连接池:
1 | # load mrsdeploy and print the function list |
删除连接池:
1 | # Return a list of web services to get the service and version information |
获取连接池信息:
1 | # Deletes the dedicated session pool and releases resources |