热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在BlazorWebAssembly静态网站中部署ML.NET机器学习模型

介绍目前世面上有许多方法来部署机器学习模型。最常见的方法是通过API或serverlessfunctions将模型公开为Web服务。将模型部署为Web服务时,其中一个注意事项是延迟

介绍

目前世面上有许多方法来部署机器学习模型。最常见的方法是通过 API 或 serverless functions 将模型公开为 Web 服务。将模型部署为 Web 服务时,其中一个注意事项是延迟和性能。使用模型基于 HTTP 进行预测的过程包括接受用户输入、从文件中加载模型的序列化版本、使用模型进行预测以及将预测返回给用户。由于模型通常只是静态文件,因此部署模型的另一种方法是作为 Web 上的静态资产,就像任何其他 HTML、CSS 或 Javascript 文件一样。此部署方法与 TensorFlow.js 类似。以这种方式进行部署有几个优点。一是不再有 Web 服务只是为了为模型提供服务,从而使其更具成本效益。另一个是一旦模型下载到用户的 PC 上,此时使用的资源是用户 PC 的资源,而不是模型本来会托管的服务器。最后,由于模型是静态文件,因此可以通过 CDN 进行分发。

其中一个挑战是机器学习模型通常使用 Javascript 以外的语言构建。这使得使用相同的代码/库构建模型变得困难或几乎不可能。WebAssembly 允许 Rust、C++、C# 和其他语言在浏览器中本机运行,从而改变了这一点。有了这种能力,加载模型和进行预测的代码/逻辑就更容易,几乎与本机平台的代码/逻辑相当。Blazor WebAssembly 为用户提供了在 C# 中完全创建基于组件的现代 Web 应用程序的能力。此外,Blazor WebAssembly 还允许用户以简单且经济高效的方式发布和部署其应用程序作为静态网站。ML.NET是一个开源的跨平台框架,允许开发人员使用 .NET 创建机器学习模型。在这篇文章中,我将演示如何训练一个多分类机器学习模型,预测鸢尾花种类。然后,我将采用该模型并将其与 Blazor WebAssembly 静态网站一起部署到 Azure 。此应用程序的完整代码可以在GitHub 上的 MLNETBlazorWASMSample 存储库中找到。

先决条件

这个项目是在Windows PC上构建的,但应该在Mac或Linux上执行以体现跨平台特性。

  • .NET 核心 SDK 3.1
  • Blazor WebAssembly模板
  • Azure 订阅
  • Azure 存储资源管理器

设置解决方案

本文中构建的解决方案包含三个项目:

  • SchemaLibrary:C# .NET 标准 2.0 类库,其中包含用于训练模型的数据的架构定义类以及模型生成的预测输出。
  • TrainingConsole:用于训练机器学习模型的 C# .NET Core 3.1 控制台应用程序。
  • BlazorWebApp:Blazor WebAssembly Web 应用程序,使用由TrainingConsole应用程序训练的机器学习模型进行预测。

安装Blazor WebAssembly模板

使用 .NET CLI 在命令提示符中运行以下命令:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.2.0-preview1.20073.1

创建解决方案

给命名MLNETBlazorWASMSample的解决方案创建新目录。

mkdir MLNETBlazorWASMSample

导航到新创建的解决方案目录并创建解决方案:

cd MLNETBlazorWASMSample
dotnet new sln

创建schema类库

模型输入和输出的数据架构在训练期间和进行预测时共享。要共享资源,请创建ConsoleTraining 和 BlazorWebApp 项目共享的类库。在解决方案目录中,输入以下命令:

dotnet new classlib -o SchemaLibrary

安装Microsoft.ML NuGet 包(此解决方案是使用版本 1.4.0 构建的)。整个解决方案都使用Microsoft.ML包。

dotnet add SchemaLibrary package Microsoft.ML

将库项目添加到解决方案。

dotnet sln add SchemaLibrary

创建训练控制台应用程序

控制台应用程序包含用于训练模型的一系列数据转换和算法。在解决方案目录中,创建新的控制台应用程序。

dotnet new console -o TrainingConsole

将控制台应用程序添加到解决方案。

dotnet sln add TrainingConsole

引用 SchemaLibrary 项目。

dotnet add TrainingConsole reference SchemaLibrary

创建 Blazor WebAssembly Web 应用程序

Web 应用程序包含一些输入元素,因此用户可以提供模型随后用于进行预测的新数据。在解决方案目录中,创建新的 Blazor WebAssembly 应用程序。

dotnet new blazorwasm -o BlazorWebApp

将 Web 应用程序项目添加到解决方案。

dotnet sln add BlazorWebApp

引用 SchemaLibrary 项目。

dotnet add BlazorWebApp reference SchemaLibrary

定义架构

了解数据

用于训练模型的数据来自iris dataset。它包含四个数值列,即花瓣和萼片的度量,最后一列为鸢尾花的种类。这是数据的示例。

 

Sepal length (cm) Sepal width (cm) Petal length (cm) Petal width (cm) Class (iris species)
5.1 3.5 1.4 0.2 Iris-setosa
7.0 3.2 4.7 1.4 Iris-versicolor
6.3 3.3 6.0 2.5 Iris-virginica

定义模型输入架构

SchemaLibrary项目中,创建一个ModelInput类,用于数据建模并作为模型输入。 

ni ModelInput.cs

ModelInput类应如下所示:

using Microsoft.ML.Data;

namespace SchemaLibrary
{
    public class ModelInput
    {
        [LoadColumn(0)]
        public float SepalLength { get; set; }

        [LoadColumn(1)]
        public float SepalWidth { get; set; }

        [LoadColumn(2)]
        public float PetalLength { get; set; }

        [LoadColumn(3)]
        public float PetalWidth { get; set; }

        [LoadColumn(4)]
        public string Label { get; set; }
    }
}

请注意,该列现在是一个称为ClassLabel的属性。原因有二:

  1. 避免使用class关键字。
  2. 在ML.NET中,算法要预测的列的默认列名称为Label。

另请注意每个属性顶部的LoadColumn属性。这用于告诉加载程序列的索引,其中相应属性的数据所在的位置。

定义模型输出架构

与输入架构类似,有模型输出的架构。此解决方案中使用的模型类型是多类分类模型,因为鸢尾花种有两个以上类别可供选择。多分类模型输出称为一个列,该列包含预测类别的名称。在SchemaLibrary项目中,创建一个PredictedLabelModelOutput类,用于对模型所做的预测建模。 

ni ModelOutput.cs

ModelOutput类应如下所示:

namespace SchemaLibrary
{
    public class ModelOutput
    {
        public string PredictedLabel { get; set; }
    }
}

训练模型

现在是时候创建训练模型的应用程序了。

获取数据

下载数据并将其保存在TrainingConsole项目目录中。

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

定义数据准备和训练步骤

TrainingConsole项目中,打开Program.cs文件,并在顶部添加以下内容:

using System;
using System.Linq;
using Microsoft.ML;
using SchemaLibrary;

然后,删除Main方法内的内容,并将其替换为以下内容。

// 1. Initialize MLContext
MLContext mlCOntext= new MLContext();

// 2. Load the data
IDataView data = mlContext.Data.LoadFromTextFile("iris.data", separatorChar:',');

// 3. Shuffle the data
IDataView shuffledData = mlContext.Data.ShuffleRows(data);

// 3. Define the data preparation and training pipeline.
IEstimator pipeline = 
    mlContext.Transforms.Concatenate("Features","SepalLength","SepalWidth","PetalLength","PetalWidth")
        .Append(mlContext.Transforms.Normali***Max("Features"))
        .Append(mlContext.Transforms.Conversion.MapValueToKey("Label"))
        .Append(mlContext.MulticlassClassification.Trainers.NaiveBayes())
        .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

// 4. Train with cross-validation
var cvResults = mlContext.MulticlassClassification.CrossValidate(shuffledData, pipeline);

// 5. Get the highest performing model and its accuracy
(ITransformer, double) model = 
    cvResults
        .OrderByDescending(fold => fold.Metrics.MacroAccuracy)
        .Select(fold => (fold.Model, fold.Metrics.MacroAccuracy))
        .First();

Console.WriteLine($"Top performing model's macro-accuracy: {model.Item2}");

// 6. Save the model
mlContext.Model.Save(model.Item1, data.Schema, "model.zip");

Console.WriteLine("Model trained");

训练应用程序从文件iris.data加载数据并应用一系列转换。首先,所有单独的数字列都合并到单个矢量中,并存储在称为Features的新列中。然后,该Features列需要预处理归一化,MapValueToKey转换用于将Label列中的文本转换为数字。然后,转换后的数据用于使用NaiveBayes算法训练模型。请注意,在撰写本文时,对于多分类问题,只有 Naive Bayes 已确认与 Blazor WebAssembly 合作。最后,将PredictedLabel存储为数字,以便必须将其转换回文本。

使用Fit方法,将数据应用于管道。由于数据集很小,因此使用称为交叉验证的技术来构建更健壮的模型。训练模型后,具有最高性能的模型将序列化并保存到名为model.zip的文件,以供以后在 Web 应用程序中使用。

最终Program.cs文件应类似于以下内容:

using System;
using System.Linq;
using Microsoft.ML;
using SchemaLibrary;

namespace TrainingConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1. Initialize MLContext
            MLContext mlCOntext= new MLContext();

            // 2. Load the data
            IDataView data = mlContext.Data.LoadFromTextFile("iris.data", separatorChar:',');

            // 3. Shuffle the data
            IDataView shuffledData = mlContext.Data.ShuffleRows(data);

            // 3. Define the data preparation and training pipeline.
            IEstimator pipeline = 
                mlContext.Transforms.Concatenate("Features","SepalLength","SepalWidth","PetalLength","PetalWidth")
                    .Append(mlContext.Transforms.Normali***Max("Features"))
                    .Append(mlContext.Transforms.Conversion.MapValueToKey("Label"))
                    .Append(mlContext.MulticlassClassification.Trainers.NaiveBayes())
                    .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

            // 4. Train with cross-validation
            var cvResults = mlContext.MulticlassClassification.CrossValidate(shuffledData, pipeline);

            // 5. Get the highest performing model and its accuracy
            (ITransformer, double) model = 
                cvResults
                    .OrderByDescending(fold => fold.Metrics.MacroAccuracy)
                    .Select(fold => (fold.Model, fold.Metrics.MacroAccuracy))
                    .First();

            Console.WriteLine($"Top performing model's macro-accuracy: {model.Item2}");

            // 6. Save the model
            mlContext.Model.Save(model.Item1, data.Schema, "model.zip");

            Console.WriteLine("Model trained");
        }
    }
}

运行应用程序

TrainConsole项目目录中,使用以下命令运行应用程序并训练模型:

dotnet run

托管模型

保存模型后,使用 Azure 门户创建 Azure 存储帐户。

在 Blazor WebAssembly 静态网站中部署ML.NET机器学习模型

 

然后,导航到新创建的存储帐户资源,并创建名为models的 Blob 容器。

在 Blazor WebAssembly 静态网站中部署ML.NET机器学习模型

 创建容器后,导航到它并上传model.zip文件。

在 Blazor WebAssembly 静态网站中部署ML.NET机器学习模型  

创建预测网页

要进行预测,请创建一个网页以获取用户输入。然后向模型提供用户输入,并将预测显示给用户。

设置导入

BlazorWebApp项目目录中,打开_Imports.razor文件。这包含应用程序中页面和组件的 using 语句。添加以下使用语句:

@using System.IO
@using Microsoft.ML
@using SchemaLibrary

创建用户输入页

BlazorWebApp项目中,在Pages目录中创建一个名为"Prediction.razor"的新razor页面。

ni Prediction.razor

向其中添加以下内容:

@page "/prediction"
@inject HttpClient _client

<label>Sepal Length: label>
<input type="text" @bind="_sepalLength"><br>
<label>Sepal Width: label>
<input type="text" @bind="_sepalWidth"><br>
<label>Petal Length: label>
<input type="text" @bind="_petalLength"><br>
<label>Petal Width: label>
<input type="text" @bind="_petalWidth"><br>
<button @onclick="GetPrediction">Make predictionbutton>
@if(@ModelPrediction == null)
{
    <p>Enter data to get a predictionp>
} else
{
    <p>@ModelPredictionp>
}


@code {
    private PredictionEngine<ModelInput,ModelOutput> _predictionEngine;
    private string _sepalLength, _sepalWidth, _petalLength, _petalWidth, ModelPrediction;

    protected override async Task OnInitializedAsync()
    {
        Stream savedModel = await _client.GetStreamAsync("<YOUR-MODEL-ENDPOINT>");
        MLContext mlCOntext= new MLContext();
        ITransformer _model = mlContext.Model.Load(savedModel,out DataViewSchema schema);
        _predictiOnEngine= mlContext.Model.CreatePredictionEngine<ModelInput,ModelOutput>(_model);
    }

    private void GetPrediction()
    {
        ModelInput input = new ModelInput
        {
            SepalLength=float.Parse(_sepalLength),
            SepalWidth=float.Parse(_sepalWidth),
            PetalLength=float.Parse(_petalLength),
            PetalWidth=float.Parse(_petalWidth)
        };

        ModelOutput prediction = _predictionEngine.Predict(input);

        ModelPrediction = prediction.PredictedLabel;
    }
}

Prediction.razor页包含模型原始训练的每个列的文本输入元素。初始化页面时,将从 Azure 存储加载模型并创建PredictionEngine请确保将替换为包含模型的 blob 的 URL。PredictionEngine是进行单个预测的便利 API。传统上,当模型用作 Web 服务时,建议使用该PredictionEnginePool服务,因为它在多线程应用程序中具有线程安全且性能更高。但是,在这种情况下,由于模型被下载到单个用户的浏览器上,因此可以使用PredictionEngine。用户输入输入值并单击"创建预测"按钮后,该GetPrediction方法通过获取用户输入并使用PredictionEngine进行预测来执行。然后,预测将显示在浏览器中。

添加到导航菜单

BlazorWebApp项目中,在Shared目录中打开NavMenu.razor文件。

将以下列表项添加到

    元素。

    <li class="nav-item px-3">
        <NavLink class="nav-link" href="prediction">
            <span class="oi oi-list-rich" aria-hidden="true">span> Prediction
        NavLink>
    li>

    最终的NavMenu.razor页面应如下所示:

    <div class="top-row pl-4 navbar navbar-dark">
        <a class="navbar-brand" href="">BlazorWebAppa>
        <button class="navbar-toggler" @onclick="ToggleNavMenu">
            <span class="navbar-toggler-icon">span>
        button>
    div>
    
    <div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
        <ul class="nav flex-column">
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                    <span class="oi oi-home" aria-hidden="true">span> Home
                NavLink>
            li>
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="counter">
                    <span class="oi oi-plus" aria-hidden="true">span> Counter
                NavLink>
            li>
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="fetchdata">
                    <span class="oi oi-list-rich" aria-hidden="true">span> Fetch data
                NavLink>
            li>
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="prediction">
                    <span class="oi oi-list-rich" aria-hidden="true">span> Prediction
                NavLink>
            li>
        ul>
    div>
    
    @code {
        private bool collapseNavMenu = true;
    
        private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
    
        private void ToggleNavMenu()
        {
            collapseNavMenu = !collapseNavMenu;
        }
    }

    配置 Web 应用程序

    Web 应用程序将作为 Azure 存储上的静态站点托管。

    在 Azure 门户中,导航到托管模型的存储帐户资源。

    启用静态网站

    为存储帐户启用静态网站,并将索引文档名称和错误文档路径设置为index.html

    在 Blazor WebAssembly 静态网站中部署ML.NET机器学习模型

     此时,在存储帐户中创建了名为$web的新容器。这是您网站的所有静态文件将驻留的位置。此外,还会创建一个主终结点。这是您将用于访问应用程序的 URL

    配置 CORS

    存储帐户具有一些默认的 CORS 设置。为了从应用程序下载和使用模型,您必须对其进行配置。

    在 Blazor WebAssembly 静态网站中部署ML.NET机器学习模型

    对于"Allowed origins",请输入主终结点。

    发布和部署 Web 应用程序

    要发布应用程序,请运行以下命令:

    dotnet publish -c Release

    这将生成在BlazorWebApp项目的 bin/Release/netstandard2.1/publish/BlazorWebApp/dist 目录中所需的文件托管为Web 应用程序静态网站。

    要部署应用程序,请使用 Azure 存储资源管理器将dist目录中的所有文件复制到 Azure 存储帐户的$web容器中。

    在 Blazor WebAssembly 静态网站中部署ML.NET机器学习模型

      

    测试应用程序

    在浏览器中,导航到静态网站的主终结点,然后选择"Prediction"页。输入数据并单击"Make prediction"。页面应如下所示。

    在 Blazor WebAssembly 静态网站中部署ML.NET机器学习模型

    您可能会注意到,Naive Bayes 在此数据集上的性能不是最好的,因此某些预测可能不太准确。我现在可以接受这一点,因为这是一个概念验证,以展示这些技术如何协同工作。也许使用更好的数据集可以产生更好的结果。

    结论

    在这篇文章中,我考虑如何将ML.NET多分类模型与 Blazor WebAssembly 静态网站一起部署到 Azure。虽然由于 WebAssembly 和 Blazor WebAssembly 的早期阶段,与其他部署方法相比,这一点更为有限,但这表明了这些技术的可能性。以这种方式部署可减少部署这些模型所需的资源量,并将处理从服务器或 Web 服务转移到客户端的浏览器,从而使机器学习模型的部署和分发更加高效、可扩展且更具成本效益。

     SchemaLibrary 


推荐阅读
  • 本文介绍了多种Eclipse插件,包括XML Schema Infoset Model (XSD)、Graphical Editing Framework (GEF)、Eclipse Modeling Framework (EMF)等,涵盖了从Web开发到图形界面编辑的多个方面。 ... [详细]
  • 微信小程序支付官方参数小程序中代码后端发起支付代码支付回调官方参数文档地址:https:developers.weixin.qq.comminiprogramdeva ... [详细]
  • 本文档提供了详细的MySQL安装步骤,包括解压安装文件、选择安装类型、配置MySQL服务以及设置管理员密码等关键环节,帮助用户顺利完成MySQL的安装。 ... [详细]
  • 深入探讨Web服务器与动态语言的交互机制:CGI、FastCGI与PHP-FPM
    本文详细解析了Web服务器(如Apache、Nginx等)与动态语言(如PHP)之间通过CGI、FastCGI及PHP-FPM进行交互的具体过程,旨在帮助开发者更好地理解这些技术背后的原理。 ... [详细]
  • Web网络基础
    目录儿1使用HTTP协议访问Web2HTTP的诞生2.1因特网的起源2.2互联网、因特网与万维网2.3万维网与HTTP3网络基础TCPIP3.1TCPIP协议族3.2TCPIP的分 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置单节点的Redis服务,包括下载、解压、编译安装以及启动服务的具体步骤。 ... [详细]
  • 代码生成器实战教程:提升编程效率的利器
    本系列文章旨在通过一系列实践案例,详细介绍如何利用代码生成器提高开发效率。本文将引导您完成从下载安装到实际应用的全过程。 ... [详细]
  • 本文详细介绍了如何通过配置 Chrome 和 VS Code 来实现对 Vue 项目的高效调试。步骤包括启用 Chrome 的远程调试功能、安装 VS Code 插件以及正确配置 launch.json 文件。 ... [详细]
  • 作为一名CSS初学者,我在博客园中尝试通过CSS美化页面,特别是为超链接添加图标,以提升阅读体验。本文将分享如何使用CSS和字体图标库来实现这一功能。 ... [详细]
  • 本文探讨了Web API 2中特性的路由机制,特别是如何利用它来构建RESTful风格的URI。文章不仅介绍了基本的特性路由使用方法,还详细说明了如何通过特性路由进行API版本控制、HTTP方法的指定、路由前缀的应用以及路由约束的设置。 ... [详细]
  • Golang与微服务架构:构建高效微服务
    本文探讨了Golang在微服务架构中的应用,包括Golang的基本概念、微服务开发的优势、常用开发工具以及具体实践案例。 ... [详细]
  • electronvue使用electronupdater实现自动更新
    今天呢,给大家带来一篇干货满满的electron-vue自动升级的教程,话不多说,开始我的表演!配置文件package.jsonbu ... [详细]
  • VMware 15.5.7 中文版激活方法
    本文提供了一种有效的方法来激活 VMware 15.5.7 的中文版本,同时介绍了如何利用最新的激活码进行操作,确保用户能够顺利使用。 ... [详细]
  • 本文探讨了六项Java特性,它们虽然强大,但在不当使用时可能会给应用程序带来严重问题。文章基于作者Nikita Salnikov Tarnovski多年的应用性能调优经验,提供了对这些特性的深入分析。 ... [详细]
  • 本文详细探讨了 HAProxy 的基本概念及其与 LVS(Linux Virtual Server)的比较,特别是在内核空间与用户空间的工作差异。文章还深入介绍了 HAProxy 独有的数据结构——弹性二叉树,以及其在高并发场景下的表现。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有