使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET机器学习模型

本文将使用ML.NET创建机器学习分类模型,通过ASP.NET Core Web API公开它,将其打包到Docker容器中,并通过Azure Container Instances将其部署到云中。

先决条件

本文假设您对Docker有一定的了解。构建和部署示例应用程序还需要以下软件/依赖项。重要的是要注意应用程序是在Ubuntu 16.04 PC上构建的,但所有软件都是跨平台的,应该适用于任何环境。

设置项目

我们要做的第一件事是为我们的解决方案创建一个文件夹。

mkdir mlnetacidemo

然后,我们想在新创建的文件夹中创建一个解决方案。

cd mlnetacidemo
dotnet new sln

建立模型

在我们的解决方案文件夹中,我们想要创建一个新的控制台应用程序,这是我们构建和测试我们的机器学习模型的地方。

设置模型项目

首先,我们要创建项目。从解决方案文件夹输入:

dotnet new console -o model

现在我们要将这个新项目添加到我们的解决方案中。

dotnet sln mlnetacidemo.sln add model/model.csproj

添加依赖项

由于我们将使用ML.NET框架,我们需要将其添加到我们的model项目中。

cd model
dotnet add package Microsoft.ML
dotnet restore

在我们开始训练模型之前,我们需要下载我们将用于训练的数据。我们通过创建一个名为data的目录并将数据文件下载到那里来实现。

mkdir data
curl -o data/iris.txt https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data

如果我们看一下数据文件,它看起来应该是这样的:

5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
5.4,3.9,1.7,0.4,Iris-setosa
4.6,3.4,1.4,0.3,Iris-setosa
5.0,3.4,1.5,0.2,Iris-setosa
4.4,2.9,1.4,0.2,Iris-setosa
4.9,3.1,1.5,0.1,Iris-setosa

训练模型

现在我们已经设置了所有依赖项,现在是构建模型的时候了。我利用了ML.NET入门网站上使用的演示。

定义数据结构

在我们model项目的根目录中,让我们创建两个被调用的类IrisDataIrisPrediction它们将分别定义我们的特性和预测属性。它们都将用于Microsoft.ML.Runtime.Api添加属性属性。

这是我们IrisData的样子:

using Microsoft.ML.Runtime.Api;

namespace model
{
public class IrisData
    {
        [Column("0")]
        public float SepalLength;

        [Column("1")]
        public float SepalWidth;

        [Column("2")]
        public float PetalLength;

        [Column("3")]
        public float PetalWidth;

        [Column("4")]
        [ColumnName("Label")]
        public string Label;
    }
}

同样,这是IrisPrediction

using Microsoft.ML.Runtime.Api;

namespace model
{
    public class IrisPrediction
    {
        [ColumnName("PredictedLabel")]
        public string PredictedLabels;
    }
}

构建LearningPipeLine

using Microsoft.ML.Data;
using Microsoft.ML;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Trainers;
using Microsoft.ML.Transforms;
using Microsoft.ML.Models;
using System;
using System.Threading.Tasks;

namespace model
{
    class Model
    {

        public static async Task<PredictionModel<IrisData,IrisPrediction>> Train(LearningPipeline pipeline, string dataPath, string modelPath)
        {
            // Load Data
            pipeline.Add(new TextLoader(dataPath).CreateFrom<IrisData>(separator:‘,‘)); 

            // Transform Data
            // Assign numeric values to text in the "Label" column, because
            // only numbers can be processed during model training
            pipeline.Add(new Dictionarizer("Label"));

            // Vectorize Features
            pipeline.Add(new ColumnConcatenator("Features", "SepalLength", "SepalWidth", "PetalLength", "PetalWidth"));

            // Add Learner
            pipeline.Add(new StochasticDualCoordinateAscentClassifier());

            // Convert Label back to text
            pipeline.Add(new PredictedLabelColumnOriginalValueConverter() {PredictedLabelColumn = "PredictedLabel"});

            // Train Model
            var model = pipeline.Train<IrisData,IrisPrediction>();

            // Persist Model
            await model.WriteAsync(modelPath);

            return model;
        }
    }
}

除了构建LearningPipLine并训练我们的机器学习模型之外,该模型还序列化并保存在名为model.zip的文件中以供将来使用。

测试我们的模型

现在是时候测试所有内容以确保它正常工作。

using System;
using Microsoft.ML;

namespace model
{
    class Program
    {
        static void Main(string[] args)
        {

            string dataPath = "model/data/iris.txt";

            string modelPath = "model/model.zip";

            var model = Model.Train(new LearningPipeline(),dataPath,modelPath).Result;

            // Test data for prediction
            var prediction = model.Predict(new IrisData()
            {
                SepalLength = 3.3f,
                SepalWidth = 1.6f,
                PetalLength = 0.2f,
                PetalWidth = 5.1f
            });

            Console.WriteLine($"Predicted flower type is: {prediction.PredictedLabels}");
        }
    }
}

全部设定运行。我们可以通过从解决方案目录输入以下命令来完成此操作:

dotnet run -p model/model.csproj

运行应用程序后,控制台上将显示以下输出。

Automatically adding a MinMax normalization transform, use ‘norm=Warn‘ or
‘norm=No‘ to turn this behavior off.Using 2 threads to train.
Automatically choosing a check frequency of 2.Auto-tuning parameters: maxIterations = 9998.
Auto-tuning parameters: L2 = 2.667734E-05.
Auto-tuning parameters: L1Threshold (L1/L2) = 0.Using best model from iteration 882.
Not training a calibrator because it is not needed.
Predicted flower type is: Iris-virginica

公开模型

此外,您会注意到在我们model项目的根目录中创建了一个名为model.zip的文件。这个持久化模型现在可以在我们的应用程序之外用于进行预测,我们接下来将通过API执行操作。

一旦构建了机器学习模型,您就希望部署它以便开始进行预测。一种方法是通过REST API。它的核心部分需要做的是接受来自客户端的数据输入并回复预测。为了帮助我们这样做,我们将使用ASP.NET Core API。

设置API项目

我们要做的第一件事是创建项目。

dotnet new webapi -o api

然后我们想将这个新项目添加到我们的解决方案中

dotnet sln mlnetacidemo.sln add api/api.csproj

添加依赖项

因为我们将加载我们的模型并通过我们的API进行预测,所以我们需要将ML.NET包添加到我们的api项目中。

cd api
dotnet add package Microsoft.ML
dotnet restore

引用模型

在我们构建机器学习模型的上一步中,它被保存到一个名为的文件中model.zip。这是我们将在API中引用的文件,以帮助我们进行预测。要在我们的API中引用它,只需将它从模型项目目录复制到我们的api项目目录中。

创建数据模型

我们的模型是使用数据结构构建的IrisDataIrisPrediction用于定义特征以及预测属性。因此,当我们的模型通过我们的API进行预测时,它也需要引用这些数据类型。因此,我们需要在项目内部定义IrisDataIrisPredictionapi。类的内容几乎与model项目中的内容相同,唯一的例外是我们的命名空间从更改modelapi

using Microsoft.ML.Runtime.Api;

namespace api
{
    public class IrisData
    {
        [Column("0")]
        public float SepalLength;

        [Column("1")]
        public float SepalWidth;

        [Column("2")]
        public float PetalLength;

        [Column("3")]
        public float PetalWidth;

        [Column("4")]
        [ColumnName("Label")]
        public string Label;
    }
}
using Microsoft.ML.Runtime.Api;

namespace api
{
    public class IrisPrediction
    {
        [ColumnName("PredictedLabel")]
        public string PredictedLabels;
    }
} 

构建控制器

现在我们的项目已经建立,是时候添加一个控制器来处理来自客户端的预测请求了。在Controllers我们api项目的目录中,我们可以创建一个PredictController使用单个POST端点调用的新类。该文件的内容应如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.ML;

namespace api.Controllers
{
    [Route("api/[controller]")]
    public class PredictController : Controller
    {
        // POST api/predict
        [HttpPost]
        public string Post([FromBody] IrisData instance)
        {
            var model = PredictionModel.ReadAsync<IrisData,IrisPrediction>("model.zip").Result;
            var prediction = model.Predict(instance);
            return prediction.PredictedLabels;
        }
    }
}

测试API

当我们的predict控制器完成编码,就可以来测试它了。从我们mlnetacidemo解决方案的根目录中,输入以下命令。

dotnet run -p api/api.csproj

我们的请求的正文应该类似于下面的代码段:在POSTMAN或Insomnia等客户端中,向端点发送HHTP POST请求http://localhost:5000/api/predict

{
    "SepalLength": 3.3,
    "SepalWidth": 1.6,
    "PetalLength": 0.2,
    "PetalWidth": 5.1,
}

打包应用程序

如果成功,返回的输出应该Iris-virginica与我们的控制台应用程序相同。大!现在我们的应用程序已在本地成功运行,现在是时候将它打包到Docker容器中并将其推送到Docker Hub。

创建Dockerfile

在我们的mlnetacidemo解决方案目录中,使用以下内容创建一个Dockerfile:

FROM microsoft/dotnet:2.0-sdk AS build
WORKDIR /app

# copy csproj and restore as distinct layers
COPY *.sln .
COPY api/*.csproj ./api/
RUN dotnet restore

# copy everything else and build app
COPY api/. ./api/
WORKDIR /app/api
RUN dotnet publish -c release -o out

FROM microsoft/aspnetcore:2.0 AS runtime
WORKDIR /app
COPY api/model.zip .
COPY --from=build /app/api/out ./
ENTRYPOINT ["dotnet", "api.dll"]

构建镜像

我们需要在命令提示符中输入以下命令。这需要一段时间,因为它需要下载.NET Core SDK和ASP.NET Core运行时Docker镜像。

docker build -t <DOCKERUSERNAME>/<IMAGENAME>:latest .

本地测试镜像

我们需要在本地测试我们的镜像,以确保它可以在云上运行。为此,我们可以使用该docker run命令。

docker run -d -p 5000:80 <DOCKERUSERNAME>/<IMAGENAME>:latest

要停止容器,请使用Ctrl + C。虽然API暴露了端口80,但我们将其绑定到本地端口5000只是为了保持我们先前的API请求不变。向http://localhost:5000/api/predict适当的主体发送POST请求时,应该再次响应同样的结果Iris-virginica。

推送到Docker Hub

现在Docker镜像在本地成功运行,是时候推送到Docker Hub了。同样,我们使用Docker CLI来执行此操作。

docker login
docker push <DOCKERUSERNAME>/<IMAGENAME>:latest

部署到云

现在,最后一步是向全世界部署和展示我们的机器学习模型和API。我们的部署将通过Azure容器实例进行,因为它几乎不需要配置或管理服务器。

准备部署清单

尽管可以在命令行中执行部署,但通常最好将所有配置放在文件中以备文档,并节省时间,而不必每次都输入参数。使用Azure,我们可以通过JSON文件来实现。

{
  "$schema":
    "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "containerGroupName": {
      "type": "string",
      "defaultValue": "mlnetacicontainergroup",
      "metadata": {
        "description": "Container Group name."
      }
    }
  },
  "variables": {
    "containername": "mlnetacidemo",
    "containerimage": "<DOCKERUSERNAME>/<IMAGENAME>:latest"
  },
  "resources": [
    {
      "name": "[parameters(‘containerGroupName‘)]",
      "type": "Microsoft.ContainerInstance/containerGroups",
      "apiVersion": "2018-04-01",
      "location": "[resourceGroup().location]",
      "properties": {
        "containers": [
          {
            "name": "[variables(‘containername‘)]",
            "properties": {
              "image": "[variables(‘containerimage‘)]",
              "resources": {
                "requests": {
                  "cpu": 1,
                  "memoryInGb": 1.5
                }
              },
              "ports": [
                {
                  "port": 80
                }
              ]
            }
          }
        ],
        "osType": "Linux",
        "ipAddress": {
          "type": "Public",
          "ports": [
            {
              "protocol": "tcp",
              "port": "80"
            }
          ]
        }
      }
    }
  ],
  "outputs": {
    "containerIPv4Address": {
      "type": "string",
      "value":
        "[reference(resourceId(‘Microsoft.ContainerInstance/containerGroups/‘, parameters(‘containerGroupName‘))).ipAddress.ip]"
    }
  }
}

现在我们可以使用这个模板并将其保存到我们mlnetacidemo解决方案根目录下的文件azuredeploy.json中。唯一需要改变的是containerimage的配置,将其替换为您的Docker Hub用户名和刚刚推送到Docker Hub的镜像的名称。

部署

为了部署我们的应用程序,我们需要确保登录我们的Azure帐户。要通过Azure CLI执行此操作,请在命令提示符下键入:

az login

按照提示登录。登录后,是时候为容器创建资源组了。

az group create --name mlnetacidemogroup --location eastus

成功创建组后,就可以部署我们的应用程序了。

az group deployment create --resource-group mlnetacidemogroup --template-file azuredeploy.json

完成后,可以使用以下命令清理资源:

az group delete --name mlnetacidemogroup

为部署初始化需要消耗几分钟的时间。如果部署成功,您应该在命令行上看到一些输出。寻找ContainerIPv4Address主机,这是可以访问容器的IP地址,更换URL后再次做一个POST请求到http://<ContainerIPv4Address>/api/predict,ContainerIPv4Address是在部署后命令行中找到的值。如果成功,响应内容应该像以前的请求一样返回Iris-virginica

小结

在本文中,我们构建了一个分类机器学习模型,使用ML.NET该模型预测鸢尾花的分类,给出了四种分类的预测功能,通过ASP.NET Core REST API公开它,将其打包到容器中并使用Azure Container Instances将其部署到云中。虽然随着模型的变化,这些操作变得更加复杂,但是目前介绍的内容已经足够标准化,扩展此示例仅需要进行很少量的修改即可。

原文地址:https://www.cnblogs.com/BeanHsiang/p/10056414.html

时间: 2024-11-08 05:44:37

使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET机器学习模型的相关文章

ASP.NET Core在Azure Kubernetes Service中的部署和管理

目录 ASP.NET Core在Azure Kubernetes Service中的部署和管理 目标 准备工作 注册 Azure 账户 AKS文档 进入Azure门户(控制台) 安装 Azure Cli 安装 Docker 进入正题 资源组 创建资源组 删除资源组 容器注册表 Azure Container Register (ACR) 创建 ACR 登录 ACR 服务主体 service principle 创建服务主体 给服务主体配置 ACR 的pull权限 K8s服务集群 Azure Ku

Asp.Net Core使用System.Drawing.Common部署到docker报错问题

原文:Asp.Net Core使用System.Drawing.Common部署到docker报错问题 Asp.Net Core 2.1发布后,正式支持System.Drawing.Common绘图了,可以用来做一些图片验证码之类的功能.但是把网站部署到docker容器里运行会遇到很多问题,也是非常闹心的,本文记录这些问题,希望帮到有需要的人. 创建网站 前提条件:安装最新版VS2017和Net Core SDK 2.1. 首先新建网站,选择Asp.Net Core 2.1 Web应用程序(模型

ASP.NET Core使用Docker-Swarm集群部署实现负载均衡实战演练

一.需求背景 人生苦短,我用.NET Core!阿笨对Docker是这样评价的:Docker在手,环境我有!Docker出手,集群我有!前面的Doc基础课程我们学习了如何使用Docker来部署搭建单机容器应用.当一台服务器的处理能力.存储空间不足时,不要企图去换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求.实践中会发现,生产环境中使用单个 Docker 节点是远远不够的,搭建 Docker 集群势在必行.然而,面对 Kubernetes, Mesos等众

[ASP.NET Core 3框架揭秘] 配置[3]:配置模型总体设计

原文:[ASP.NET Core 3框架揭秘] 配置[3]:配置模型总体设计 在<读取配置数据>([上篇],[下篇])上面一节中,我们通过实例的方式演示了几种典型的配置读取方式,接下来我们从设计的维度来重写认识配置模型.配置的编程模型涉及到三个核心对象,分别通过三个对应的接口(IConfiguration.IConfigurationSource和IConfigurationBuilder)来表示.如果从设计层面来审视背后的配置模型,还缺少另一个名通过IConfigurationProvide

Ubuntu-Docker[1]安装Docker,通过Docker部署net core代码,需要结合[.NET Core 18]发布、ASP.NET Core Docker部署

1)通过系统自带包安装 通过自带包安装,可能Docker版本较旧 $ sudo apt-get update Reading package lists... Done $ sudo apt-get install -y docker.io {{{-y表示同意.没有-y也可执行,系统会问是否安装,输入y回车即可 apt-get -y install这个指令则是跳过系统提示,直接安装.}}} Adding group `docker' (GID 121) ... Done. docker star

详解ASP.NET Core Docker部署

前言 在前面文章中,介绍了 ASP.NET Core在 macOS,Linux 上基于Nginx和Jexus的发布和部署,本篇文章主要是如何在Docker容器中运行ASP.NET Core应用程序. ASP.NET Nginx 发布和部署 :http://www.cnblogs.com/savorboard/p/dotnet-core-publish-nginx.html. Asp.Net Jexus 发布和部署:http://www.cnblogs.com/savorboard/p/dot-n

ASP.NET Core + Docker +Jenkins 实现持续集成

1.新建一个ASP.NET Core MVC应用程序: 2.将其上传到git: 3.建立Jenkins任务 (1)选择"新建任务",输入任务名称,选择"自由风格项目",然后点击确定: (2)选择"源代码管理",填入我们的git地址 输入H/2 * * * *设置两分钟拉取一次 (3)构建环境 勾上 Delete workspace before build start 是设置构建前删除工作区 勾上 Abort the build if it's

Asp.net Core 初探(发布和部署Linux)

前言 俗话说三天不学习,赶不上刘少奇.Asp.net Core更新这么长时间一直观望,周末帝都小雨,宅在家看了下Core Web App,顺便搭建了个HelloWorld环境来尝尝鲜,第一次看到.Net Web运行在Linux上还是有点小激动(只可惜微软走这一步路走的太晚,要不然屌丝们也不会每每遇见Java VS .Net就想辩论个你死我活). 开发环境和部署环境 Windows 10.VS2015 Update3.安装.Net Core SDK.DotNetCore.1.0.1-VS2015T

asp.net core在linux上的部署调试

双十一买了阿里云的LINUX服务器三年¥720 把自己的niunan.net一系列网站都部署上去 用jexus来部署,部署时发现头一个网站没问题,但是后一个网站部署就有问题..输入域名打不开,但JEXUS的文件基本都是一样的 后来学会怎么在LINUX下看错误的: 1.开二个XSHELL连接上LINUX服务器.2. 停止jexus服务3. 到有问题的core网站目录下dotnet xxx.dll4. 在另一个窗口中curl http://127.0.0.1:5002 搞掂 ,慢慢排错吧,结果最后是