热门标签 | 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 


推荐阅读
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文详细介绍了解决全栈跨域问题的方法及步骤,包括添加权限、设置Access-Control-Allow-Origin、白名单等。通过这些操作,可以实现在不同服务器上的数据访问,并解决后台报错问题。同时,还提供了解决second页面访问数据的方法。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
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社区 版权所有