使用ML.NET进行自定义机器学习

天大地大妈咪最大 提交于 2019-12-04 12:12:29

ML.NET是Microsoft最近发布的用于机器学习的开源,跨平台,代码优先的框架。尽管对我们来说是一个新的框架,但该框架的根源是Microsoft Research,并且在过去十年中已被许多内部团队使用,包括那些您几乎肯定听说过的产品的开发人员-Microsoft Windows,Office和Bing,仅举几例。

ML.NET使.NET开发人员可以轻松地将机器学习集成到其应用程序中,无论是控制台,桌面还是Web。它涵盖了机器学习活动的整个生命周期,从模型的训练和评估到使用和部署。支持许多典型的有监督和无监督机器学习任务,包括分类回归推荐聚类该框架还与TensorFlow集成,使.NET开发人员能够从熟悉的环境调用深度学习模型(适用于诸如对象检测或语音分析之类的任务)。

为什么选择ML.NET?

如今,在为我们的应用程序添加机器学习或AI功能的选项方面,我们总是无所适从。借助NuGet包和仅几行代码,我们就可以利用Azure认知服务的强大功能以高度的准确性和性能执行情感分析,对象检测和OCR等复杂任务。微软确实做了令人难以置信的工作,使各种经验的开发人员都可以使用这些工具。

ML.NET如何适合?您可以使用ML.NET来执行许多与Azure一样的机器学习任务。但是,作为一个高度可配置的基于代码的框架,它肯定会花费多行代码。在差异化方面,您可能会考虑ML.NET的一些关键原因是:

  • 训练特定领域的模型
    许多认知服务模型都在广泛的数据集上进行了训练,以便为各种用例提供​​良好的体验。这非常适合接送和使用以及许多实际需求。但是,如果您正在处理特殊问题,那么通用模型可能不太适合。例如,认知服务将毫不费力地告诉您图像是否包含帽子或动物。如果您想检测和区分不同种类的帽子(例如,您自己的帽子收藏)并且不关心识别动物或其他物体,则可以从训练自己的领域特定模型中受益,ML.NET允许你轻松做。

  • 将数据保存在网络中或用户的机器上
    许多Cognitive Services确实允许您通过提供自定义示例来训练自定义模型或扩展内置模型。在某些情况下,还可以导出和下载模型,以实现离线使用。但是,出于法规或隐私的原因,您可能不希望或被允许上传训练数据或将预测输入发送到云提供商。ML.NET可以以离线方式端到端地用于训练和预测。如果您需要训练和/或预测数据来保持内部,则ML.NET是一个不错的选择。

  • 动态生成ML模型
    作为代码优先的框架,ML.NET使得基于编译时未知的信息来动态生成机器学习模型非常容易。如果您的应用程序支持动态内容(例如,用户定义的模式),并且您希望集成ML功能,则可以选择ML.NET。

  • 修改或扩展框架
    作为一个开放源代码项目,ML.NET的完整源代码可在GitHub上获得,从而使您可以根据需要快速研究实现细节,修复错误甚至添加功能。

  • 避免基于消耗的定价
    ML.NET可以免费使用,无论您执行多少操作。当然,运行自己的系统也要付费!

与Azure认知服务相比,访问这些差异化功能的最大障碍可能是ML.NET对机器学习知识的更高要求。使用ML.NET要求您更多地考虑诸如数据预处理,数据管道,算法选择,模型验证和性能指标之类的事情。虽然理解这些概念将为您提供扎实的机器学习基础,但立即解决所有这些问题可能会有些令人生畏。幸运的是,ML.NET团队已经完成了一些工作,可以帮助新手入门。

缩小差距— AutoML和Model Builder

如果您想使用ML.NET,但是构建管道,选择训练师和评估模型的想法让您三思而后行,那么您可以选择AutoML形式的选择,它ML.NET的配套库。AutoML通过自动化生命周期的各个部分并尝试为您的数据生成最佳的机器学习模型,降低了新机器学习开发人员的进入门槛。具体来说,它会自动:

  • 从SQL或基于文本的源中加载训练数据

  • 执行输入数据的基本预处理,包括检测分类字段和删除对预测无用的字段

  • 探索潜在的算法和参数,迭代训练模型并根据输入数据评估每种算法和有效性

  • (通过CLI或Model Builder使用时)生成代码以加载经过训练的最佳模型,准备提供新的预测

可以从代码(Install-Package Microsoft.ML.AutoML),命令行界面(dotnet tool install -g mlnet)或通过GUI工具(以Visual Studio扩展,Model Builder的形式调用AutoML 

在本文的其余部分,我们将通过一个示例使用Model Builder自动训练机器学习模型并生成使用该模型的代码。

演练—使用Model Builder自动训练出租车票价预测模型

在本演练中,我们将基于时间,距离,乘客人数和付款方式等输入信息,构建一个预测纽约出租车票价的模型。我们将使用ML.NET示例存储库中的数据作为输入。

先决条件:

如果您没有Visual Studio 2017或2019,请在尝试安装Model Builder扩展之前安装其中之一。

步骤1:在Visual Studio中创建一个新项目

ML.NET可在.NET Core所运行的任何x86或x64环境中运行,因此我们可以从许多内置模板开始。在这种情况下,我们将创建一个新的.NET Core控制台应用程序。

 

 

 创建项目后,请等到屏幕上看到熟悉的空控制台应用程序项目。

步骤2:将“机器学习”添加到您的项目中

安装扩展后,我们可以通过在解决方案资源管理器中右键单击我们的项目,然后选择添加->机器学习来调用模型生成器。完成此操作后,您会看到ML.NET Model Builder首屏引导界面。

 

步骤3:为您的数据集配置Model Builder

选择方案

我们与Model Builder的交互首先是从一些预定义的场景中进行选择。本质上,这些是针对特定机器学习任务量身定制的模板。在我们的案例中,我们希望预测出租车价格,因此“价格预测”是一个不错的选择。

 

加载训练数据

下一个任务是指定我们要用于训练的数据。价格预测是监督学习任务的一个示例,其中训练了机器学习模型,通过显示历史数据的示例来进行预测。示例包括模型输入(在我们的示例中为时间,距离和乘客数量)以及输出值(行程的实际票价)。稍后,当我们要预测票价时,我们的模型将采用新行程的详细信息,并将其与从训练数据中得出的关系一起使用,以预测票价。

为了评估机器学习模型的质量,我们通常从训练中排除部分历史数据。这样可以确保我们拥有一些已知的良好输入/输出组合(我们的模型尚未看到),可以将它们与模型的输出进行比较。为此,AutoML会自动撤消部分数据,因此我们可以为其提供完整的数据集。如果完成了可选的先决条件,则应在“选择文件”对话框中选择级联的数据集。否则,您可以粘贴训练数据URL使用级联数据集的好处是您将为AutoML提供更大的训练数据。

加载文件后,Model Builder将自动检测列并提供数据预览。我们需要告诉Model Builder我们要预测哪个领域;在我们的例子中是“ fare_amount”字段。

 

步骤4:使用模型生成器生成最佳模型

训练优化模型

Model Builder使用AutoML迭代探索选项并确定给定数据集的最佳预测算法和参数。迭代时间的上限取决于我们,主要应受训练数据集的大小影响。

ML.NET团队对各种数据集大小的迭代持续时间有一些指导对于我们的数据集(介于2.5mb和5mb之间,取决于您是否将测试数据和训练数据连接在一起),仅十秒钟就足够了。单击“训练”后,Model Builder将开始迭代模型并显示有关其进度的一些详细信息。Model Builder评估它训练的每个模型,并将模型的RSquared得分用作比较它们的机制。

 

审查模型效果

执行优化后,Model Builder将概述该过程,包括它能够在迭代时间内生成的最佳五种配置的评估指标。

 

尽管“Model Builder”会自动选择效果最佳的模型,但是值得花一点时间查看最终指标。如果所选模型的指标不佳,则不太可能在新输入上表现良好。在这种情况下,您可能需要迭代模型训练过程。选项可能包括:

  • 增加AutoML的探索时间(允许它查找更好的算法或参数)
  • 训练数据的数量增加(提供更多示例,更好地代表您的域的可变性)
  • 预处理训练数据(公开可以提高可预测性的新功能,或删除可能无法提高的功能)

在上面的例子中,使用LightGbmRegression训练器生成了最佳模型,其RSquared得分为0.94,这应该表现良好。

步骤5:使用模型

评估后,Model Builder将自动将两个新项目添加到您的解决方案中。第一个是包含模型和输入类的库,现有项目可以引用该库。第二个是带有代码的示例控制台应用程序,该代码演示了如何加载和使用模型。

 

生成了这两个项目后,我们就可以看到实际的模型了。该示例应用程序使用来自训练数据集的硬编码单个输入来演示模型的用法。为了使其更具交互性,您可以使用以下内容替换Program.cs的内容,从而使您可以交互地输入行程详细信息并获得预计的票价:

using System;
using System.IO;
using System.Linq;
using Microsoft.ML;
using PredictTaxiFareML.Model.DataModels;
using static System.Console;
using static System.Environment;

namespace PredictTaxiFareML.ConsoleApp
{
    class Program
    {
        private const string Quit = "quit";
        private const string ModelPath = @"MLModel.zip";
        
        static void Main(string[] args)
        {
            var context = new MLContext().Model;
            var model = context.Load(GetPath(ModelPath), out _);
            var engine = context.CreatePredictionEngine<ModelInput, ModelOutput>(model);

            WriteLine("== AutoML Interactive Taxi Fare Predictor == ");
            while (GetInput(out var input))
                WriteLine($"{NewLine}Predicted fare: " +
                 $"{engine.Predict(input).Score:C}{NewLine}");
        }

        private static bool GetInput(out ModelInput input)
        {
            WriteLine($"{NewLine}Enter trip details:{NewLine}");

            input = new ModelInput
            {
                Passenger_count = ReadF("Passenger count", 1),
                Trip_time_in_secs = ReadF("Trip time (mins)", 1) * 60,
                Trip_distance = ReadF("Distance (mi)", 0),
                Vendor_id = ReadCat("Vendor", "VTS", "CMD"),
                Rate_code = ReadF("Rate code (0 - 6)", 0, 6),
                Payment_type = ReadCat("Payment type", "CRD", "CSH"),
            };

            return true;
        }

        private static float ReadF(string title, 
            float min = float.MinValue, float max = float.MaxValue)
        {
            while (true)
            {
                try { return Clamp(float.Parse(Prompt(title)), min, max); } 
                catch (Exception ex) { WriteLine(ex.Message); }
            }
        }

        private static string ReadCat(string title, params string[] values)
        {
            title = $"{title} [{String.Join(", ", values)}]";

            var ret = "";
            while (!values.Contains(ret))
                ret = Prompt(title);

            return ret;
        }

        private static string Prompt(string title)
        {
            Write($"  - {title}: ");
            return ReadLine().Trim().ToUpper();
        }

        private static float Clamp(float input, float min, float max)
        {
            var ret = Math.Max(Math.Min(input, max), min);

            if (Math.Abs(ret - input) > 0.1)
                WriteLine($"Clamping to {ret}");

            return ret;
        }

        private static string GetPath(string relativePath)
        {
            var root = new FileInfo(typeof(Program).Assembly.Location);
            var asmPath = root.Directory.FullName;

            return Path.Combine(asmPath, relativePath);
        }
    }
}

运行中的代码如下所示:

 

就是这样!我们已经成功地使用了Model Builder来自动生成优化的模型,以便根据出租车费用数据集进行预测。AutoML自动为我们处理了一些棘手的步骤,使我们无需成为机器学习专家就可以从ML.NET的某些独特功能中受益。希望这个例子有助于为您提供使用ML.NET的启发,您自己可以尝试在某些数据上创建自定义模型。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!