使用 .NET 5 體驗大數(shù)據(jù)和機器學習
.NET 5 旨在提供統(tǒng)一的運行時和框架,使其在各平臺都有統(tǒng)一的運行時行為和開發(fā)體驗。微軟發(fā)布了與 .NET 協(xié)作的大數(shù)據(jù)(.NET for Spark)和機器學習(ML.NET)工具,這些工具共同提供了富有成效的端到端體驗。在本文中,我們將介紹 .NET for Spark、大數(shù)據(jù)、ML.NET 和機器學習的基礎(chǔ)知識,我們將研究其 API 和功能,向你展示如何開始構(gòu)建和消費你自己的 Spark 作業(yè)和 ML.NET 模型。
什么是大數(shù)據(jù)
大數(shù)據(jù)是一個幾乎不言自明的行業(yè)術(shù)語。該術(shù)語指的是大型數(shù)據(jù)集,通常涉及 TB 甚至 PB 級的信息,這些數(shù)據(jù)集被用作分析的輸入,以揭示數(shù)據(jù)中的模式和趨勢。大數(shù)據(jù)與傳統(tǒng)工作負載之間的關(guān)鍵區(qū)別在于,大數(shù)據(jù)往往過于龐大、復(fù)雜或多變,傳統(tǒng)數(shù)據(jù)庫和應(yīng)用程序無法處理。一種流行的數(shù)據(jù)分類方式被稱為 "3V"(譯注:即3個V,Volume 容量、Velocity 速度、Variety 多樣性)。
大數(shù)據(jù)解決方案是為適應(yīng)高容量、處理復(fù)雜多樣的數(shù)據(jù)結(jié)構(gòu)而定制的,并通過批處理(靜態(tài))和流處理(動態(tài))來管理速度。
大多數(shù)大數(shù)據(jù)解決方案都提供了在數(shù)據(jù)倉庫中存儲數(shù)據(jù)的方式,數(shù)據(jù)倉庫通常是一個為快速檢索和為并行處理而優(yōu)化的分布式集群。處理大數(shù)據(jù)往往涉及多個步驟,如下圖所示:

.NET 5 開發(fā)人員如果需要基于大型數(shù)據(jù)集進行分析和洞察,可以使用基于流行的大數(shù)據(jù)解決方案 Apache Spark 的 .NET 實現(xiàn):.NET for Spark。
.NET for Spark
.NET for Spark 基于 Apache Spark,這是一個用于處理大數(shù)據(jù)的開源分析引擎。它被設(shè)計為在內(nèi)存中處理大量數(shù)據(jù),以提供比其他依賴持久化存儲的解決方案更好的性能。它是一個分布式系統(tǒng),并行處理工作負載。它為加載數(shù)據(jù)、查詢數(shù)據(jù)、處理數(shù)據(jù)和輸出數(shù)據(jù)提供支持。
Apache Spark 支持 Java、Scala、Python、R 和 SQL。微軟創(chuàng)建了 .NET for Spark 以增加對 .NET 的支持。該解決方案提供了免費、開放、跨平臺的工具,用于使用 .NET 所支持的語言(如 C#和 F#)構(gòu)建大數(shù)據(jù)應(yīng)用程序,這樣你就可以使用現(xiàn)有的 .NET 庫,同時利用 SparkSQL 等 Spark 特性。

以下代碼展示了一個小而完整的 .NET for Spark 應(yīng)用程序,它讀取一個文本文件并按降序輸出字數(shù)。
- using Microsoft.Spark.Sql;
- namespace MySparkApp
- {
- class Program
- {
- static void Main(string[] args)
- {
- // Create a Spark session.
- SparkSession spark = SparkSession.Builder().AppName("word_count_sample").GetOrCreate();
- // Create initial DataFrame.
- DataFrame dataFrame = spark.Read().Text("input.txt");
- // Count words.
- DataFrame words = dataFrame.Select(Functions.Split(Functions.Col("value"), " ").Alias("words"))
- .Select(Functions.Explode(Functions .Col("words"))
- .Alias("word"))
- .GroupBy("word")
- .Count()
- .OrderBy(Functions.Col("count").Desc());
- // Show results.
- words.Show();
- // Stop Spark session.
- spark.Stop();
- }
- }
- }
在開發(fā)機器上配置 .NET for Spark 需要安裝幾個依賴,包括 Java SDK 和 Apache Spark。你可以在這里(https://aka.ms/go-spark-net)查看手把手的入門指南。
Spark for .NET 可在多種環(huán)境中運行,并可部署到云中運行??刹渴鹉繕税?Azure HDInsight、Azure Synapse、AWS EMR Spark 和 Databricks 等。如果數(shù)據(jù)作為項目可用的一部分,你可以將其與其他 project 文件一起提交。
大數(shù)據(jù)通常與機器學習一起使用,以獲得關(guān)于數(shù)據(jù)的洞察。
什么是機器學習
首先,我們先來介紹一下人工智能和機器學習的基本知識。
人工智能(AI)是指計算機模仿人類智慧和能力,如推理和尋找意義。典型的人工智能技術(shù)通常是從規(guī)則或邏輯系統(tǒng)開始的。作為一個簡單的例子,想一想這樣的場景:你想把某樣東西分類為“面包”或“不是面包”。當你開始時,這似乎是一個簡單的問題,例如“如果它有眼睛,它就不是面包”。然而,你很快就會開始意識到,有很多不同的特征可以將某物定性為面包與非面包,而且特征越多,一系列的 if 語句就會越長越復(fù)雜,如下圖所示:

從上圖中的例子可以看出,傳統(tǒng)的、基于規(guī)則的人工智能技術(shù)往往難以擴展。這就是機器學習的作用。機器學習(ML)是人工智能的一個子集,它能在過去的數(shù)據(jù)中找到模式,并從經(jīng)驗中學習,以對新數(shù)據(jù)采取行動。ML 允許計算機在沒有明確的邏輯規(guī)則編程的情況下進行預(yù)測。因此,當你有一個難以(或不可能)用基于規(guī)則的編程解決的問題時,你可以使用 ML。你可以把 ML 看作是 "對不可編程的編程"。
為了用 ML 解決“面包”與“非面包”的問題,你提供面包的例子和非面包的例子(如下圖所示),而不是實現(xiàn)一長串復(fù)雜的 if 語句。你將這些例子傳遞給一個算法,該算法在數(shù)據(jù)中找到模式,并返回一個模型,然后你可以用這個模型來預(yù)測尚未被模型“看到”的圖像是“面包”還是“不是面包”。

上圖展示了 AI 與 ML 的另一種思考方式。AI 將規(guī)則和數(shù)據(jù)作為輸入,預(yù)期輸出基于這些規(guī)則的答案。而 ML 則是將數(shù)據(jù)和答案作為輸入,輸出可用于對新數(shù)據(jù)進行歸納的規(guī)則。

AI 將規(guī)則和數(shù)據(jù)作為輸入,并根據(jù)這些規(guī)則輸出預(yù)期的答案。ML 將數(shù)據(jù)和答案作為輸入,并輸出可用于概括新數(shù)據(jù)的規(guī)則。
ML.NET
微軟在 2019 年 5 月的 Build 上發(fā)布了 ML.NET,這是一個面向.NET 開發(fā)人員的開源、跨平臺 ML 框架。在過去的九年里,微軟的團隊已經(jīng)廣泛使用該框架的內(nèi)部版本來實現(xiàn)流行的 ML 驅(qū)動功能;一些例子包括 Dynamics 365 欺詐檢測、PowerPoint 設(shè)計理念和 Microsoft Defender 防病毒威脅保護。
ML.NET 允許你在.NET 生態(tài)系統(tǒng)中構(gòu)建、訓練和消費 ML 模型,而不需要 ML 或數(shù)據(jù)科學的背景。ML.NET 可以在任何.NET 運行的地方運行。Windows、Linux、macOS、on-prem、離線場景(如 WinForms 或 WPF 桌面應(yīng)用)或任何云端(如 Azure)中。你可以將 ML.NET 用于各種場景,如表 1 所述。
ML.NET 使用自動機器學習(或稱 AutoML)來自動構(gòu)建和訓練 ML 模型的過程,以根據(jù)提供的場景和數(shù)據(jù)找到最佳模型。你可以通過 AutoML.NET API 或 ML.NET 工具來使用 ML.NET 的 AutoML,其中包括 Visual Studio 中的 Model Builder 和跨平臺的 ML.NET CLI,如圖 6 所示。除了訓練最佳模型外,ML.NET 工具還生成在最終用戶.NET 應(yīng)用程序中消費模型所需的文件和 C#代碼,該應(yīng)用程序可以是任何.NET 應(yīng)用程序(桌面、Web、控制臺等)。所有 AutoML 方案都提供了本地訓練選項,圖像分類也允許你利用云的優(yōu)勢,使用 Model Builder 中的 Azure ML 進行訓練。

你可以在 Microsoft Docs 中了解更多關(guān)于 ML.NET 的信息,網(wǎng)址是:https://aka.ms/mlnetdocs。
ML 和大數(shù)據(jù)結(jié)合
大數(shù)據(jù)和 ML 可以很好地結(jié)合在一起。讓我們構(gòu)建一個同時使用 Spark for .NET 和 ML.NET 的管道,以展示大數(shù)據(jù)和 ML 如何一起工作。Markdown 是一種用于編寫文檔和創(chuàng)建靜態(tài)網(wǎng)站的流行語言,它使用的語法不如 HTML 復(fù)雜,但提供的格式控制比純文本更多。這是從 .NET 文檔庫中的摘取一段 markdown 文件內(nèi)容:
- ---
- title: Welcome to .NET
- description: Getting started with the .NET
- family of technologies.
- ms.date: 12/03/2019
- ms.custom: "updateeachrelease"
- ---
- # Welcome to .NET
- See [Get started with .NET Core](core/get-started.md) to learn how to create .NET Core apps.
- Build many types of apps with .NET, such as cloud ,IoT, and games using free cross-platform tools...
破折號之間的部分稱為前頁(front matter),是使用 YAML 描述的有關(guān)文檔的元數(shù)據(jù)。以井號(#)開頭的部分是標題。兩個哈希(##)表示二級標題。“ .NET Core 入門”是一個超鏈接。
我們的目標是處理大量文檔,添加諸如字數(shù)和估計的閱讀時間之類的元數(shù)據(jù),并將相似的文章自動分組在一起。
這是我們將構(gòu)建的管道:
- 為每個文檔建立字數(shù)統(tǒng)計;
- 估計每個文檔的閱讀時間;
- 根據(jù)“ TF-IDF”或“術(shù)語頻率/反向文檔頻率”為每個文檔創(chuàng)建前 20 個單詞的列表(這將在后面說明)。
第一步是拉取文檔存儲庫和需引用的應(yīng)用程序。你可以使用任何包含 Markdown 文件的存儲庫及文件夾結(jié)構(gòu)。本文使用的示例來自 .NET 文檔存儲庫,可從 https://aka.ms/dot-net-docs 克隆。
為.NET 和 Spark 準備本地環(huán)境之后,可以從https://aka.ms/spark-ml-example拉取項目。
解決方案文件夾包含一個批處理命令(在倉庫中有提供),你可以使用該命令來運行所有步驟。
處理 Markdown
DocRepoParser 項目以遞歸方式遍歷存儲庫中的子文件夾,以收集各文檔有關(guān)的元數(shù)據(jù)。Common 項目包含幾個幫助程序類。例如,F(xiàn)ilesHelper 用于所有文件 I/O。它跟蹤存儲文件和文件名的位置,并提供諸如為其他項目讀取文件的服務(wù)。構(gòu)造函數(shù)需要一個標簽(一個唯一標識工作流的數(shù)字)和包含文檔的 repo 或頂級文件夾的路徑。默認情況下,它在用戶的本地應(yīng)用程序數(shù)據(jù)文件夾下創(chuàng)建一個文件夾。如有必要,可以將其覆蓋。
MarkdownParser利用 Microsoft.Toolkit.Parsers解析 Markdown 的庫。該庫有兩個任務(wù):首先,它必須提取標題和子標題;其次,它必須提取單詞。Markdown 文件以 "塊 "的形式暴露出來,代表標題、鏈接和其他 Markdown 特征。塊又包含承載文本的“Inlines”。例如,這段代碼通過迭代行和單元格來解析一個 TableBlock,以找到 Inlines。
- case TableBlock table:
- table.Rows.SelectMany(r => r.Cells)
- .SelectMany(c => c.Inlines)
- .ForEach(i => candidate = RecurseInline(i, candidate, words, titles));
- break;
此代碼提取超鏈接的文本部分:
- case HyperlinkInline hyper:
- if (!string.IsNullOrWhiteSpace(hyper.Text))
- {
- words.Append(hyper.Text.ExtractWords());
- }
- break;
結(jié)果是一個 CSV 文件,如下圖所示:

第一步只是準備要處理的數(shù)據(jù)。下一步使用 Spark for .NET 作業(yè)確定每個文檔的字數(shù),閱讀時間和前 20 個術(shù)語。
構(gòu)建 Spark Job
SparkWordsProcessor項目用來運行 Spark 作業(yè)。雖然該應(yīng)用程序是一個控制臺項目,但它需要 Spark 來運行。runjob.cmd批處理命令將作業(yè)提交到正確配置的 Windows 計算機上運行。典型作業(yè)的模式是創(chuàng)建一個會話或“應(yīng)用程序”,執(zhí)行一些邏輯,然后停止會話。
- var spark = SparkSession.Builder()
- .AppName(nameof(SparkWordsProcessor))
- .GetOrCreate();
- RunJob();
- spark.Stop();
通過將其路徑傳遞給 Spark 會話,可以輕松讀取上一步的文件。
- var docs = spark.Read().HasHeader().Csv(filesHelper.TempDataFile);
- docs.CreateOrReplaceTempView(nameof(docs));
- var totalDocs = docs.Count();
docs變量解析為一個DataFrame。Data Frame 本質(zhì)上是一個帶有一組列和一個通用接口的表,用于與數(shù)據(jù)交互,而不管其底層來源是什么。可以從其他 data frame 中引用一個 data frame。SparkSQL 也可以用來查詢 data frame。你必須創(chuàng)建一個臨時視圖,該視圖為 data frame 提供別名,以便從 SQL 中引用它。通過CreateOrReplaceTempView方法,可以像這樣從 data frame 中查詢行:
- SELECT * FROM docs
totalDocs變量檢索文檔中所有行的計數(shù)。Spark 提供了一個名為Split的將字符串分解為數(shù)組的函數(shù)。Explode函數(shù)將每個數(shù)組項變成一行:
- var words = docs.Select(fileCol,
- Functions.Split(nameof(FileDataParse.Words)
- .AsColumn(), " ")
- .Alias(wordList))
- .Select(fileCol, Functions.Explode(wordList.AsColumn())
- .Alias(word));
該查詢?yōu)槊總€單詞或術(shù)語生成一行。這個 data frame 是生成術(shù)語頻率(TF)或者說每個文檔中每個詞的計數(shù)的基礎(chǔ)。
- var termFrequency = words
- .GroupBy(fileCol, Functions.Lower(word.AsColumn()).Alias(word))
- .Count()
- .OrderBy(fileCol, count.AsColumn().Desc());
Spark 有內(nèi)置的模型,可以確定“術(shù)語頻率/反向文檔頻率”。在這個例子中,你將手動確定術(shù)語頻率來演示它是如何計算的。術(shù)語在每個文檔中以特定的頻率出現(xiàn)。一篇關(guān)于 wizard 的文檔可能有很高的“wizard”一詞計數(shù)。同一篇文檔中,"the "和 "is "這兩個詞的出現(xiàn)次數(shù)可能也很高。對我們來說,很明顯,“wizard”這個詞更重要,也提供了更多的語境。另一方面,Spark 必須經(jīng)過訓練才能識別重要的術(shù)語。為了確定什么是真正重要的,我們將總結(jié)文檔頻率(document frequency),或者說一個詞在 repo 中所有文檔中出現(xiàn)的次數(shù)。這就是“按不同出現(xiàn)次數(shù)分組”:
- var documentFrequency = words
- .GroupBy(Functions.Lower(word.AsColumn())
- .Alias(word))
- .Agg(Functions.CountDistinct(fileCol)
- .Alias(docFrequency));
現(xiàn)在是計算的時候了。一個特殊的方程式可以計算出所謂的反向文檔頻率(inverse document frequency),即 IDF。將總文檔的自然對數(shù)(加一)輸入方程,然后除以該詞的文檔頻率(加一)。
- static double CalculateIdf(int docFrequency, int totalDocuments) =>
- Math.Log(totalDocuments + 1) / (docFrequency + 1);
在所有文檔中出現(xiàn)的詞比出現(xiàn)頻率較低的詞賦值低。例如,給定 1000 個文檔,一個在每個文檔中出現(xiàn)的詞與一個只在少數(shù)文檔中出現(xiàn)的詞(約 1 個)相比,IDF 為 0.003。Spark 支持用戶定義的函數(shù),你可以這樣注冊。
- spark.Udf().Register<int, int, double>(nameof(CalculateIdf), CalculateIdf);
接下來,你可以使用該函數(shù)來計算 data frame 中所有單詞的 IDF:
- var idfPrep = documentFrequency.Select(word.AsColumn(),
- docFrequency.AsColumn())
- .WithColumn(total, Functions.Lit(totalDocs))
- .WithColumn(inverseDocFrequency,
- Functions.CallUDF(nameof(CalculateIdf), docFrequency.AsColumn(), total.AsColumn()
- )
- );
使用文檔頻率 data frame,增加兩列。第一列是文檔的單詞總數(shù)量,第二列是調(diào)用你的 UDF 來計算 IDF。還有一個步驟,就是確定“重要詞”。重要詞是指在所有文檔中不經(jīng)常出現(xiàn),但在當前文檔中經(jīng)常出現(xiàn)的詞,用 TF-IDF 表示,這只是 IDF 和 TF 的產(chǎn)物。考慮“is”的情況,IDF 為 0.002,在文檔中的頻率為 50,而“wizard”的 IDF 為 1,頻率為 10。相比頻率為 10 的“wizard”,“is”的 TF-IDF 計算結(jié)果為 0.1。這讓 Spark 對重要性有了更好的概念,而不僅僅是原始字數(shù)。
到目前為止,你已經(jīng)使用代碼來定義 data frame。讓我們嘗試一下 SparkSQL。為了計算 TF-IDF,你將文檔頻率 data frame 與反向文檔頻率 data frame 連接起來,并創(chuàng)建一個名為termFreq_inverseDocFreq的新列。下面是 SparkSQL:
- var idfJoin = spark.Sql($"SELECT t.File, d.word, d.{docFrequency}, d.{inverseDocFrequency}, t.count, d.{inverseDocFrequency} * t.count as {termFreq_inverseDocFreq} from {nameof(documentFrequency)} d inner join {nameof(termFrequency)} t on t.word = d.word");
探索代碼,看看最后的步驟是如何實現(xiàn)的。這些步驟包括:
到目前為止所描述的所有步驟都為 Spark 提供了一個模板或定義。像 LINQ 查詢一樣,實際的處理在結(jié)果被具體化之前不會發(fā)生(比如計算出總文檔數(shù)時)。最后一步調(diào)用 Collect 來處理和返回結(jié)果,并將其寫入另一個 CSV。然后,你可以使用新文件作為 ML 模型的輸入,下圖是該文件的一部分:

Spark for .NET 使你能夠查詢和塑造數(shù)據(jù)。你在同一個數(shù)據(jù)源上建立了多個 data frame,然后添加它們以獲得關(guān)于重要術(shù)語、字數(shù)和閱讀時間的洞察。下一步是應(yīng)用 ML 來自動生成類別。
預(yù)測類別
最后一步是對文檔進行分類。DocMLCategorization項目包含了 ML.NET 的Microsoft.ML包。雖然 Spark 使用的是 data frame,但 data view 在 ML.NET 中提供了類似的概念。
這個例子為 ML.NET 使用了一個單獨的項目,這樣就可以將模型作為一個獨立的步驟進行訓練。對于許多場景,可以直接從你的.NET for Spark 項目中引用 ML.NET,并將 ML 作為同一工作的一部分來執(zhí)行。
首先,你必須對類進行標記,以便 ML.NET 知道源數(shù)據(jù)中的哪些列映射到類中的屬性。在FileData 類使用 LoadColumn 注解,就像這樣:
- [LoadColumn(0)]
- public string File { get; set; }
- [LoadColumn(1)]
- public string Title { get; set; }
然后,你可以為模型創(chuàng)建上下文,并從上一步中生成的文件中加載 data view:
- var context = new MLContext(seed: 0);
- var dataToTrain = context.Data
- .LoadFromTextFile<FileData>(path: filesHelper.ModelTrainingFile, hasHeader: true, allowQuoting: true, separatorChar: ',');
ML 算法對數(shù)字的處理效果最好,所以文檔中的文本必須轉(zhuǎn)換為數(shù)字向量。ML.NET 為此提供了FeaturizeText方法。在一個步驟中,模型分別:
- 檢測語言
- 將文本標記為單個單詞或標記
- 規(guī)范化文本,以便對單詞的變體進行標準化和大小寫相似化
- 將這些術(shù)語轉(zhuǎn)換為一致的數(shù)值或準備處理的“特征向量”
以下代碼將列轉(zhuǎn)換為特征,然后創(chuàng)建一個結(jié)合了多個特征的“Features”列。
- var pipeline = context.Transforms.Text.FeaturizeText(
- nameof(FileData.Title).Featurized(),
- nameof(FileData.Title)).Append(context.Transforms.Text.FeaturizeText(nameof(FileData.Subtitle1).Featurized(),
- nameof(FileData.Subtitle1))).Append(context.Transforms.Text.FeaturizeText(nameof(FileData.Subtitle2).Featurized(),
- nameof(FileData.Subtitle2))).Append(context.Transforms.Text.FeaturizeText(nameof(FileData.Subtitle3).Featurized(),
- nameof(FileData.Subtitle3))).Append(context.Transforms.Text.FeaturizeText(nameof(FileData.Subtitle4).Featurized(),
- nameof(FileData.Subtitle4))).Append(context.Transforms.Text.FeaturizeText(nameof(FileData.Subtitle5).Featurized(),
- nameof(FileData.Subtitle5))).Append(context.Transforms.Text.FeaturizeText(nameof(FileData.Top20Words).Featurized(),
- nameof(FileData.Top20Words))).Append(context.Transforms.Concatenate(features, nameof(FileData.Title).Featurized(),
- nameof(FileData.Subtitle1).Featurized(),
- nameof(FileData.Subtitle2).Featurized(),
- nameof(FileData.Subtitle3).Featurized(),
- nameof(FileData.Subtitle4).Featurized(),
- nameof(FileData.Subtitle5).Featurized(),
- nameof(FileData.Top20Words).Featurized())
- );
此時,數(shù)據(jù)已經(jīng)為訓練模型做了適當?shù)臏蕚?。訓練是無監(jiān)督的,這意味著它必須用一個例子來推斷信息。你沒有將樣本類別輸入到模型中,所以算法必須通過分析特征如何聚類來找出數(shù)據(jù)的相互關(guān)聯(lián)。你將使用k-means 聚類算法。該算法使用特征計算文檔之間的“距離”,然后圍繞分組后的文檔“繪制”邊界。該算法涉及隨機化,因此兩次運行結(jié)果會是不相同的。主要的挑戰(zhàn)是確定訓練的最佳聚類大小。不同的文檔集最好有不同的最佳類別數(shù),但算法需要你在訓練前輸入類別數(shù)。
代碼在 2 到 20 個簇之間迭代,以確定最佳大小。對于每次運行,它都會獲取特征數(shù)據(jù)并應(yīng)用算法或訓練器。然后,它根據(jù)預(yù)測模型對現(xiàn)有數(shù)據(jù)進行轉(zhuǎn)換。對結(jié)果進行評估,以確定每個簇中文檔的平均距離,并選擇平均距離最小的結(jié)果。
- var options = new KMeansTrainer.Options
- {
- FeatureColumnName = features,
- NumberOfClusters = categories,
- };
- var clusterPipeline = pipeline.Append(context.Clustering.Trainers.KMeans(options));
- var model = clusterPipeline.Fit(dataToTrain);
- var predictions = model.Transform(dataToTrain);
- var metrics = context.Clustering.Evaluate(predictions);
- distances.Add(categories, metrics.AverageDistance);
經(jīng)過培訓和評估后,你可以保存最佳模型,并使用它對數(shù)據(jù)集進行預(yù)測。將生成一個輸出文件以及一個摘要,該摘要顯示有關(guān)每個類別的一些元數(shù)據(jù)并在下面列出標題。標題只是幾個功能之一,因此有時需要仔細研究細節(jié)才能使類別有意義。在本地測試中,教程之類的文檔歸于一組,API 文檔歸于另一組,而例外歸于它們自己的組。
ML zip 文件可與 Prediction Engine 一起用于其他項目中的新數(shù)據(jù)。
機器學習模型另存為單個 zip 文件。該文件可以包含在其他項目中,與 Prediction Engine 一起使用以對新數(shù)據(jù)進行預(yù)測。例如,你可以創(chuàng)建一個 WPF 應(yīng)用程序,該應(yīng)用程序允許用戶瀏覽目錄,然后加載并使用經(jīng)過訓練的模型對文檔進行分類,而無需先對其進行訓練。
下一步是什么
Spark for .NET 計劃與.NET 5 同時在 GA(譯注:GA=General Availability,正式發(fā)布的版本)發(fā)布。請訪問 https://aka.ms/spark-net-roadmap 閱讀路線圖和推出功能的計劃。(譯注:.NET 5 正式發(fā)布時間已過,Spark for .NET 已隨 .NET 5 正式發(fā)布)
本文著重于本地開發(fā)體驗,為了充分利用大數(shù)據(jù)的力量,你可以將 Spark 作業(yè)提交到云中。有各種各樣的云主機可以容納 PB 級數(shù)據(jù),并為你的工作負載提供數(shù)十個核的計算能力。Azure Synapse Analytics 是一項 Azure 服務(wù),旨在承載大量數(shù)據(jù),提供用于運行大數(shù)據(jù)作業(yè)的群集,并允許通過基于圖表的儀表盤進行交互式探索。若要了解如何將 Spark for .NET 作業(yè)提交到 Azure Synapse,請閱讀官方文檔(https://aka.ms/spark-net-synapse)。
下面這張表列舉了 ML.NET 機器學習的常見任務(wù)和場景:
